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 6000da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); 6010da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 6020da6f3feSBharata B Rao 6030da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 6040da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 6050da6f3feSBharata B Rao env->dcache_line_size))); 6060da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 6070da6f3feSBharata B Rao env->dcache_line_size))); 6080da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 6090da6f3feSBharata B Rao env->icache_line_size))); 6100da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 6110da6f3feSBharata B Rao env->icache_line_size))); 6120da6f3feSBharata B Rao 6130da6f3feSBharata B Rao if (pcc->l1_dcache_size) { 6140da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 6150da6f3feSBharata B Rao pcc->l1_dcache_size))); 6160da6f3feSBharata B Rao } else { 6170da6f3feSBharata B Rao fprintf(stderr, "Warning: Unknown L1 dcache size for cpu\n"); 6180da6f3feSBharata B Rao } 6190da6f3feSBharata B Rao if (pcc->l1_icache_size) { 6200da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 6210da6f3feSBharata B Rao pcc->l1_icache_size))); 6220da6f3feSBharata B Rao } else { 6230da6f3feSBharata B Rao fprintf(stderr, "Warning: Unknown L1 icache size for cpu\n"); 6240da6f3feSBharata B Rao } 6250da6f3feSBharata B Rao 6260da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 6270da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 6280da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", env->slb_nr))); 6290da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 6300da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 6310da6f3feSBharata B Rao 6320da6f3feSBharata B Rao if (env->spr_cb[SPR_PURR].oea_read) { 6330da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 6340da6f3feSBharata B Rao } 6350da6f3feSBharata B Rao 6360da6f3feSBharata B Rao if (env->mmu_model & POWERPC_MMU_1TSEG) { 6370da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 6380da6f3feSBharata B Rao segs, sizeof(segs)))); 6390da6f3feSBharata B Rao } 6400da6f3feSBharata B Rao 6410da6f3feSBharata B Rao /* Advertise VMX/VSX (vector extensions) if available 6420da6f3feSBharata B Rao * 0 / no property == no vector extensions 6430da6f3feSBharata B Rao * 1 == VMX / Altivec available 6440da6f3feSBharata B Rao * 2 == VSX available */ 6450da6f3feSBharata B Rao if (env->insns_flags & PPC_ALTIVEC) { 6460da6f3feSBharata B Rao uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 6470da6f3feSBharata B Rao 6480da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 6490da6f3feSBharata B Rao } 6500da6f3feSBharata B Rao 6510da6f3feSBharata B Rao /* Advertise DFP (Decimal Floating Point) if available 6520da6f3feSBharata B Rao * 0 / no property == no DFP 6530da6f3feSBharata B Rao * 1 == DFP available */ 6540da6f3feSBharata B Rao if (env->insns_flags2 & PPC2_DFP) { 6550da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 6560da6f3feSBharata B Rao } 6570da6f3feSBharata B Rao 6580da6f3feSBharata B Rao page_sizes_prop_size = create_page_sizes_prop(env, page_sizes_prop, 6590da6f3feSBharata B Rao sizeof(page_sizes_prop)); 6600da6f3feSBharata B Rao if (page_sizes_prop_size) { 6610da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 6620da6f3feSBharata B Rao page_sizes_prop, page_sizes_prop_size))); 6630da6f3feSBharata B Rao } 6640da6f3feSBharata B Rao 6650da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", 66622419c2aSDavid Gibson cs->cpu_index / vcpus_per_socket))); 6670da6f3feSBharata B Rao 6680da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", 6690da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)))); 6700da6f3feSBharata B Rao 6710da6f3feSBharata B Rao _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cs)); 6720da6f3feSBharata B Rao 6730da6f3feSBharata B Rao _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, 6740da6f3feSBharata B Rao ppc_get_compat_smt_threads(cpu))); 6750da6f3feSBharata B Rao } 6760da6f3feSBharata B Rao 6770da6f3feSBharata B Rao static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr) 6780da6f3feSBharata B Rao { 6790da6f3feSBharata B Rao CPUState *cs; 6800da6f3feSBharata B Rao int cpus_offset; 6810da6f3feSBharata B Rao char *nodename; 6820da6f3feSBharata B Rao int smt = kvmppc_smt_threads(); 6830da6f3feSBharata B Rao 6840da6f3feSBharata B Rao cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 6850da6f3feSBharata B Rao _FDT(cpus_offset); 6860da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 6870da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 6880da6f3feSBharata B Rao 6890da6f3feSBharata B Rao /* 6900da6f3feSBharata B Rao * We walk the CPUs in reverse order to ensure that CPU DT nodes 6910da6f3feSBharata B Rao * created by fdt_add_subnode() end up in the right order in FDT 6920da6f3feSBharata B Rao * for the guest kernel the enumerate the CPUs correctly. 6930da6f3feSBharata B Rao */ 6940da6f3feSBharata B Rao CPU_FOREACH_REVERSE(cs) { 6950da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 6960da6f3feSBharata B Rao int index = ppc_get_vcpu_dt_id(cpu); 6970da6f3feSBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 6980da6f3feSBharata B Rao int offset; 6990da6f3feSBharata B Rao 7000da6f3feSBharata B Rao if ((index % smt) != 0) { 7010da6f3feSBharata B Rao continue; 7020da6f3feSBharata B Rao } 7030da6f3feSBharata B Rao 7040da6f3feSBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, index); 7050da6f3feSBharata B Rao offset = fdt_add_subnode(fdt, cpus_offset, nodename); 7060da6f3feSBharata B Rao g_free(nodename); 7070da6f3feSBharata B Rao _FDT(offset); 7080da6f3feSBharata B Rao spapr_populate_cpu_dt(cs, fdt, offset, spapr); 7090da6f3feSBharata B Rao } 7100da6f3feSBharata B Rao 7110da6f3feSBharata B Rao } 7120da6f3feSBharata B Rao 71303d196b7SBharata B Rao /* 71403d196b7SBharata B Rao * Adds ibm,dynamic-reconfiguration-memory node. 71503d196b7SBharata B Rao * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation 71603d196b7SBharata B Rao * of this device tree node. 71703d196b7SBharata B Rao */ 71803d196b7SBharata B Rao static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) 71903d196b7SBharata B Rao { 72003d196b7SBharata B Rao MachineState *machine = MACHINE(spapr); 72103d196b7SBharata B Rao int ret, i, offset; 72203d196b7SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 72303d196b7SBharata B Rao uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; 724e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 72503d196b7SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 7266663864eSBharata B Rao int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; 72703d196b7SBharata B Rao 72803d196b7SBharata B Rao /* Allocate enough buffer size to fit in ibm,dynamic-memory */ 72903d196b7SBharata B Rao buf_len = nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE * sizeof(uint32_t) + 73003d196b7SBharata B Rao sizeof(uint32_t); 73103d196b7SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 73203d196b7SBharata B Rao 73303d196b7SBharata B Rao offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory"); 73403d196b7SBharata B Rao 73503d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size, 73603d196b7SBharata B Rao sizeof(prop_lmb_size)); 73703d196b7SBharata B Rao if (ret < 0) { 73803d196b7SBharata B Rao goto out; 73903d196b7SBharata B Rao } 74003d196b7SBharata B Rao 74103d196b7SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff); 74203d196b7SBharata B Rao if (ret < 0) { 74303d196b7SBharata B Rao goto out; 74403d196b7SBharata B Rao } 74503d196b7SBharata B Rao 74603d196b7SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0); 74703d196b7SBharata B Rao if (ret < 0) { 74803d196b7SBharata B Rao goto out; 74903d196b7SBharata B Rao } 75003d196b7SBharata B Rao 75103d196b7SBharata B Rao /* ibm,dynamic-memory */ 75203d196b7SBharata B Rao int_buf[0] = cpu_to_be32(nr_lmbs); 75303d196b7SBharata B Rao cur_index++; 75403d196b7SBharata B Rao for (i = 0; i < nr_lmbs; i++) { 75503d196b7SBharata B Rao sPAPRDRConnector *drc; 75603d196b7SBharata B Rao sPAPRDRConnectorClass *drck; 757e8f986fcSBharata B Rao uint64_t addr = i * lmb_size + spapr->hotplug_memory.base;; 75803d196b7SBharata B Rao uint32_t *dynamic_memory = cur_index; 75903d196b7SBharata B Rao 76003d196b7SBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, 76103d196b7SBharata B Rao addr/lmb_size); 76203d196b7SBharata B Rao g_assert(drc); 76303d196b7SBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 76403d196b7SBharata B Rao 76503d196b7SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 76603d196b7SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 76703d196b7SBharata B Rao dynamic_memory[2] = cpu_to_be32(drck->get_index(drc)); 76803d196b7SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 76903d196b7SBharata B Rao dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL)); 77003d196b7SBharata B Rao if (addr < machine->ram_size || 77103d196b7SBharata B Rao memory_region_present(get_system_memory(), addr)) { 77203d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); 77303d196b7SBharata B Rao } else { 77403d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(0); 77503d196b7SBharata B Rao } 77603d196b7SBharata B Rao 77703d196b7SBharata B Rao cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; 77803d196b7SBharata B Rao } 77903d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len); 78003d196b7SBharata B Rao if (ret < 0) { 78103d196b7SBharata B Rao goto out; 78203d196b7SBharata B Rao } 78303d196b7SBharata B Rao 78403d196b7SBharata B Rao /* ibm,associativity-lookup-arrays */ 78503d196b7SBharata B Rao cur_index = int_buf; 7866663864eSBharata B Rao int_buf[0] = cpu_to_be32(nr_nodes); 78703d196b7SBharata B Rao int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */ 78803d196b7SBharata B Rao cur_index += 2; 7896663864eSBharata B Rao for (i = 0; i < nr_nodes; i++) { 79003d196b7SBharata B Rao uint32_t associativity[] = { 79103d196b7SBharata B Rao cpu_to_be32(0x0), 79203d196b7SBharata B Rao cpu_to_be32(0x0), 79303d196b7SBharata B Rao cpu_to_be32(0x0), 79403d196b7SBharata B Rao cpu_to_be32(i) 79503d196b7SBharata B Rao }; 79603d196b7SBharata B Rao memcpy(cur_index, associativity, sizeof(associativity)); 79703d196b7SBharata B Rao cur_index += 4; 79803d196b7SBharata B Rao } 79903d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf, 80003d196b7SBharata B Rao (cur_index - int_buf) * sizeof(uint32_t)); 80103d196b7SBharata B Rao out: 80203d196b7SBharata B Rao g_free(int_buf); 80303d196b7SBharata B Rao return ret; 80403d196b7SBharata B Rao } 80503d196b7SBharata B Rao 80603d196b7SBharata B Rao int spapr_h_cas_compose_response(sPAPRMachineState *spapr, 80703d196b7SBharata B Rao target_ulong addr, target_ulong size, 80803d196b7SBharata B Rao bool cpu_update, bool memory_update) 80903d196b7SBharata B Rao { 81003d196b7SBharata B Rao void *fdt, *fdt_skel; 81103d196b7SBharata B Rao sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 }; 81203d196b7SBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); 81303d196b7SBharata B Rao 81403d196b7SBharata B Rao size -= sizeof(hdr); 81503d196b7SBharata B Rao 81603d196b7SBharata B Rao /* Create sceleton */ 81703d196b7SBharata B Rao fdt_skel = g_malloc0(size); 81803d196b7SBharata B Rao _FDT((fdt_create(fdt_skel, size))); 81903d196b7SBharata B Rao _FDT((fdt_begin_node(fdt_skel, ""))); 82003d196b7SBharata B Rao _FDT((fdt_end_node(fdt_skel))); 82103d196b7SBharata B Rao _FDT((fdt_finish(fdt_skel))); 82203d196b7SBharata B Rao fdt = g_malloc0(size); 82303d196b7SBharata B Rao _FDT((fdt_open_into(fdt_skel, fdt, size))); 82403d196b7SBharata B Rao g_free(fdt_skel); 82503d196b7SBharata B Rao 82603d196b7SBharata B Rao /* Fixup cpu nodes */ 82703d196b7SBharata B Rao if (cpu_update) { 82803d196b7SBharata B Rao _FDT((spapr_fixup_cpu_dt(fdt, spapr))); 82903d196b7SBharata B Rao } 83003d196b7SBharata B Rao 83103d196b7SBharata B Rao /* Generate memory nodes or ibm,dynamic-reconfiguration-memory node */ 83203d196b7SBharata B Rao if (memory_update && smc->dr_lmb_enabled) { 83303d196b7SBharata B Rao _FDT((spapr_populate_drconf_memory(spapr, fdt))); 83403d196b7SBharata B Rao } 83503d196b7SBharata B Rao 83603d196b7SBharata B Rao /* Pack resulting tree */ 83703d196b7SBharata B Rao _FDT((fdt_pack(fdt))); 83803d196b7SBharata B Rao 83903d196b7SBharata B Rao if (fdt_totalsize(fdt) + sizeof(hdr) > size) { 84003d196b7SBharata B Rao trace_spapr_cas_failed(size); 84103d196b7SBharata B Rao return -1; 84203d196b7SBharata B Rao } 84303d196b7SBharata B Rao 84403d196b7SBharata B Rao cpu_physical_memory_write(addr, &hdr, sizeof(hdr)); 84503d196b7SBharata B Rao cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt)); 84603d196b7SBharata B Rao trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr)); 84703d196b7SBharata B Rao g_free(fdt); 84803d196b7SBharata B Rao 84903d196b7SBharata B Rao return 0; 85003d196b7SBharata B Rao } 85103d196b7SBharata B Rao 85228e02042SDavid Gibson static void spapr_finalize_fdt(sPAPRMachineState *spapr, 85353018216SPaolo Bonzini hwaddr fdt_addr, 85453018216SPaolo Bonzini hwaddr rtas_addr, 85553018216SPaolo Bonzini hwaddr rtas_size) 85653018216SPaolo Bonzini { 8575b2128d2SAlexander Graf MachineState *machine = MACHINE(qdev_get_machine()); 858c20d332aSBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 8595b2128d2SAlexander Graf const char *boot_device = machine->boot_order; 86071461b0fSAlexey Kardashevskiy int ret, i; 86171461b0fSAlexey Kardashevskiy size_t cb = 0; 86271461b0fSAlexey Kardashevskiy char *bootlist; 86353018216SPaolo Bonzini void *fdt; 86453018216SPaolo Bonzini sPAPRPHBState *phb; 86553018216SPaolo Bonzini 86653018216SPaolo Bonzini fdt = g_malloc(FDT_MAX_SIZE); 86753018216SPaolo Bonzini 86853018216SPaolo Bonzini /* open out the base tree into a temp buffer for the final tweaks */ 86953018216SPaolo Bonzini _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE))); 87053018216SPaolo Bonzini 871e8f986fcSBharata B Rao ret = spapr_populate_memory(spapr, fdt); 872e8f986fcSBharata B Rao if (ret < 0) { 873e8f986fcSBharata B Rao fprintf(stderr, "couldn't setup memory nodes in fdt\n"); 874e8f986fcSBharata B Rao exit(1); 87553018216SPaolo Bonzini } 87653018216SPaolo Bonzini 87753018216SPaolo Bonzini ret = spapr_populate_vdevice(spapr->vio_bus, fdt); 87853018216SPaolo Bonzini if (ret < 0) { 87953018216SPaolo Bonzini fprintf(stderr, "couldn't setup vio devices in fdt\n"); 88053018216SPaolo Bonzini exit(1); 88153018216SPaolo Bonzini } 88253018216SPaolo Bonzini 88353018216SPaolo Bonzini QLIST_FOREACH(phb, &spapr->phbs, list) { 88453018216SPaolo Bonzini ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt); 88553018216SPaolo Bonzini } 88653018216SPaolo Bonzini 88753018216SPaolo Bonzini if (ret < 0) { 88853018216SPaolo Bonzini fprintf(stderr, "couldn't setup PCI devices in fdt\n"); 88953018216SPaolo Bonzini exit(1); 89053018216SPaolo Bonzini } 89153018216SPaolo Bonzini 89253018216SPaolo Bonzini /* RTAS */ 89353018216SPaolo Bonzini ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size); 89453018216SPaolo Bonzini if (ret < 0) { 89553018216SPaolo Bonzini fprintf(stderr, "Couldn't set up RTAS device tree properties\n"); 89653018216SPaolo Bonzini } 89753018216SPaolo Bonzini 8980da6f3feSBharata B Rao /* cpus */ 8990da6f3feSBharata B Rao spapr_populate_cpus_dt_node(fdt, spapr); 90053018216SPaolo Bonzini 90171461b0fSAlexey Kardashevskiy bootlist = get_boot_devices_list(&cb, true); 90271461b0fSAlexey Kardashevskiy if (cb && bootlist) { 90371461b0fSAlexey Kardashevskiy int offset = fdt_path_offset(fdt, "/chosen"); 90471461b0fSAlexey Kardashevskiy if (offset < 0) { 90571461b0fSAlexey Kardashevskiy exit(1); 90671461b0fSAlexey Kardashevskiy } 90771461b0fSAlexey Kardashevskiy for (i = 0; i < cb; i++) { 90871461b0fSAlexey Kardashevskiy if (bootlist[i] == '\n') { 90971461b0fSAlexey Kardashevskiy bootlist[i] = ' '; 91071461b0fSAlexey Kardashevskiy } 91171461b0fSAlexey Kardashevskiy 91271461b0fSAlexey Kardashevskiy } 91371461b0fSAlexey Kardashevskiy ret = fdt_setprop_string(fdt, offset, "qemu,boot-list", bootlist); 91471461b0fSAlexey Kardashevskiy } 91571461b0fSAlexey Kardashevskiy 9165b2128d2SAlexander Graf if (boot_device && strlen(boot_device)) { 9175b2128d2SAlexander Graf int offset = fdt_path_offset(fdt, "/chosen"); 9185b2128d2SAlexander Graf 9195b2128d2SAlexander Graf if (offset < 0) { 9205b2128d2SAlexander Graf exit(1); 9215b2128d2SAlexander Graf } 9225b2128d2SAlexander Graf fdt_setprop_string(fdt, offset, "qemu,boot-device", boot_device); 9235b2128d2SAlexander Graf } 9245b2128d2SAlexander Graf 92553018216SPaolo Bonzini if (!spapr->has_graphics) { 92653018216SPaolo Bonzini spapr_populate_chosen_stdout(fdt, spapr->vio_bus); 92753018216SPaolo Bonzini } 92853018216SPaolo Bonzini 929c20d332aSBharata B Rao if (smc->dr_lmb_enabled) { 930c20d332aSBharata B Rao _FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB)); 931c20d332aSBharata B Rao } 932c20d332aSBharata B Rao 93353018216SPaolo Bonzini _FDT((fdt_pack(fdt))); 93453018216SPaolo Bonzini 93553018216SPaolo Bonzini if (fdt_totalsize(fdt) > FDT_MAX_SIZE) { 936730fce59SThomas Huth error_report("FDT too big ! 0x%x bytes (max is 0x%x)", 93753018216SPaolo Bonzini fdt_totalsize(fdt), FDT_MAX_SIZE); 93853018216SPaolo Bonzini exit(1); 93953018216SPaolo Bonzini } 94053018216SPaolo Bonzini 941ad440b4aSAndrew Jones qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 94253018216SPaolo Bonzini cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); 94353018216SPaolo Bonzini 944a21a7a70SGonglei g_free(bootlist); 94553018216SPaolo Bonzini g_free(fdt); 94653018216SPaolo Bonzini } 94753018216SPaolo Bonzini 94853018216SPaolo Bonzini static uint64_t translate_kernel_address(void *opaque, uint64_t addr) 94953018216SPaolo Bonzini { 95053018216SPaolo Bonzini return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR; 95153018216SPaolo Bonzini } 95253018216SPaolo Bonzini 95353018216SPaolo Bonzini static void emulate_spapr_hypercall(PowerPCCPU *cpu) 95453018216SPaolo Bonzini { 95553018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 95653018216SPaolo Bonzini 95753018216SPaolo Bonzini if (msr_pr) { 95853018216SPaolo Bonzini hcall_dprintf("Hypercall made with MSR[PR]=1\n"); 95953018216SPaolo Bonzini env->gpr[3] = H_PRIVILEGE; 96053018216SPaolo Bonzini } else { 96153018216SPaolo Bonzini env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]); 96253018216SPaolo Bonzini } 96353018216SPaolo Bonzini } 96453018216SPaolo Bonzini 965e6b8fd24SSamuel Mendoza-Jonas #define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2)) 966e6b8fd24SSamuel Mendoza-Jonas #define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID) 967e6b8fd24SSamuel Mendoza-Jonas #define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY) 968e6b8fd24SSamuel Mendoza-Jonas #define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY)) 969e6b8fd24SSamuel Mendoza-Jonas #define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY)) 970e6b8fd24SSamuel Mendoza-Jonas 97128e02042SDavid Gibson static void spapr_reset_htab(sPAPRMachineState *spapr) 97253018216SPaolo Bonzini { 97353018216SPaolo Bonzini long shift; 974e6b8fd24SSamuel Mendoza-Jonas int index; 97553018216SPaolo Bonzini 97653018216SPaolo Bonzini /* allocate hash page table. For now we always make this 16mb, 97753018216SPaolo Bonzini * later we should probably make it scale to the size of guest 97853018216SPaolo Bonzini * RAM */ 97953018216SPaolo Bonzini 98053018216SPaolo Bonzini shift = kvmppc_reset_htab(spapr->htab_shift); 98153018216SPaolo Bonzini 98253018216SPaolo Bonzini if (shift > 0) { 98353018216SPaolo Bonzini /* Kernel handles htab, we don't need to allocate one */ 98453018216SPaolo Bonzini spapr->htab_shift = shift; 9857c43bca0SAneesh Kumar K.V kvmppc_kern_htab = true; 98601a57972SSamuel Mendoza-Jonas 98701a57972SSamuel Mendoza-Jonas /* Tell readers to update their file descriptor */ 98801a57972SSamuel Mendoza-Jonas if (spapr->htab_fd >= 0) { 98901a57972SSamuel Mendoza-Jonas spapr->htab_fd_stale = true; 99001a57972SSamuel Mendoza-Jonas } 99153018216SPaolo Bonzini } else { 99253018216SPaolo Bonzini if (!spapr->htab) { 99353018216SPaolo Bonzini /* Allocate an htab if we don't yet have one */ 99453018216SPaolo Bonzini spapr->htab = qemu_memalign(HTAB_SIZE(spapr), HTAB_SIZE(spapr)); 99553018216SPaolo Bonzini } 99653018216SPaolo Bonzini 99753018216SPaolo Bonzini /* And clear it */ 99853018216SPaolo Bonzini memset(spapr->htab, 0, HTAB_SIZE(spapr)); 999e6b8fd24SSamuel Mendoza-Jonas 1000e6b8fd24SSamuel Mendoza-Jonas for (index = 0; index < HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; index++) { 1001e6b8fd24SSamuel Mendoza-Jonas DIRTY_HPTE(HPTE(spapr->htab, index)); 1002e6b8fd24SSamuel Mendoza-Jonas } 100353018216SPaolo Bonzini } 100453018216SPaolo Bonzini 100553018216SPaolo Bonzini /* Update the RMA size if necessary */ 100653018216SPaolo Bonzini if (spapr->vrma_adjust) { 1007b082d65aSAlexey Kardashevskiy spapr->rma_size = kvmppc_rma_size(spapr_node0_size(), 1008b082d65aSAlexey Kardashevskiy spapr->htab_shift); 100953018216SPaolo Bonzini } 101053018216SPaolo Bonzini } 101153018216SPaolo Bonzini 10129e3f9733SAlexander Graf static int find_unknown_sysbus_device(SysBusDevice *sbdev, void *opaque) 10139e3f9733SAlexander Graf { 10149e3f9733SAlexander Graf bool matched = false; 10159e3f9733SAlexander Graf 10169e3f9733SAlexander Graf if (object_dynamic_cast(OBJECT(sbdev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 10179e3f9733SAlexander Graf matched = true; 10189e3f9733SAlexander Graf } 10199e3f9733SAlexander Graf 10209e3f9733SAlexander Graf if (!matched) { 10219e3f9733SAlexander Graf error_report("Device %s is not supported by this machine yet.", 10229e3f9733SAlexander Graf qdev_fw_name(DEVICE(sbdev))); 10239e3f9733SAlexander Graf exit(1); 10249e3f9733SAlexander Graf } 10259e3f9733SAlexander Graf 10269e3f9733SAlexander Graf return 0; 10279e3f9733SAlexander Graf } 10289e3f9733SAlexander Graf 102901a57972SSamuel Mendoza-Jonas /* 103001a57972SSamuel Mendoza-Jonas * A guest reset will cause spapr->htab_fd to become stale if being used. 103101a57972SSamuel Mendoza-Jonas * Reopen the file descriptor to make sure the whole HTAB is properly read. 103201a57972SSamuel Mendoza-Jonas */ 103328e02042SDavid Gibson static int spapr_check_htab_fd(sPAPRMachineState *spapr) 103401a57972SSamuel Mendoza-Jonas { 103501a57972SSamuel Mendoza-Jonas int rc = 0; 103601a57972SSamuel Mendoza-Jonas 103701a57972SSamuel Mendoza-Jonas if (spapr->htab_fd_stale) { 103801a57972SSamuel Mendoza-Jonas close(spapr->htab_fd); 103901a57972SSamuel Mendoza-Jonas spapr->htab_fd = kvmppc_get_htab_fd(false); 104001a57972SSamuel Mendoza-Jonas if (spapr->htab_fd < 0) { 104101a57972SSamuel Mendoza-Jonas error_report("Unable to open fd for reading hash table from KVM: " 104201a57972SSamuel Mendoza-Jonas "%s", strerror(errno)); 104301a57972SSamuel Mendoza-Jonas rc = -1; 104401a57972SSamuel Mendoza-Jonas } 104501a57972SSamuel Mendoza-Jonas spapr->htab_fd_stale = false; 104601a57972SSamuel Mendoza-Jonas } 104701a57972SSamuel Mendoza-Jonas 104801a57972SSamuel Mendoza-Jonas return rc; 104901a57972SSamuel Mendoza-Jonas } 105001a57972SSamuel Mendoza-Jonas 105153018216SPaolo Bonzini static void ppc_spapr_reset(void) 105253018216SPaolo Bonzini { 105328e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 1054182735efSAndreas Färber PowerPCCPU *first_ppc_cpu; 1055b7d1f77aSBenjamin Herrenschmidt uint32_t rtas_limit; 1056259186a7SAndreas Färber 10579e3f9733SAlexander Graf /* Check for unknown sysbus devices */ 10589e3f9733SAlexander Graf foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL); 10599e3f9733SAlexander Graf 106053018216SPaolo Bonzini /* Reset the hash table & recalc the RMA */ 106153018216SPaolo Bonzini spapr_reset_htab(spapr); 106253018216SPaolo Bonzini 106353018216SPaolo Bonzini qemu_devices_reset(); 106453018216SPaolo Bonzini 1065b7d1f77aSBenjamin Herrenschmidt /* 1066b7d1f77aSBenjamin Herrenschmidt * We place the device tree and RTAS just below either the top of the RMA, 1067b7d1f77aSBenjamin Herrenschmidt * or just below 2GB, whichever is lowere, so that it can be 1068b7d1f77aSBenjamin Herrenschmidt * processed with 32-bit real mode code if necessary 1069b7d1f77aSBenjamin Herrenschmidt */ 1070b7d1f77aSBenjamin Herrenschmidt rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR); 1071b7d1f77aSBenjamin Herrenschmidt spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE; 1072b7d1f77aSBenjamin Herrenschmidt spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE; 1073b7d1f77aSBenjamin Herrenschmidt 107453018216SPaolo Bonzini /* Load the fdt */ 107553018216SPaolo Bonzini spapr_finalize_fdt(spapr, spapr->fdt_addr, spapr->rtas_addr, 107653018216SPaolo Bonzini spapr->rtas_size); 107753018216SPaolo Bonzini 1078b7d1f77aSBenjamin Herrenschmidt /* Copy RTAS over */ 1079b7d1f77aSBenjamin Herrenschmidt cpu_physical_memory_write(spapr->rtas_addr, spapr->rtas_blob, 1080b7d1f77aSBenjamin Herrenschmidt spapr->rtas_size); 1081b7d1f77aSBenjamin Herrenschmidt 108253018216SPaolo Bonzini /* Set up the entry state */ 1083182735efSAndreas Färber first_ppc_cpu = POWERPC_CPU(first_cpu); 1084182735efSAndreas Färber first_ppc_cpu->env.gpr[3] = spapr->fdt_addr; 1085182735efSAndreas Färber first_ppc_cpu->env.gpr[5] = 0; 1086182735efSAndreas Färber first_cpu->halted = 0; 10871b718907SDavid Gibson first_ppc_cpu->env.nip = SPAPR_ENTRY_POINT; 108853018216SPaolo Bonzini 108953018216SPaolo Bonzini } 109053018216SPaolo Bonzini 109153018216SPaolo Bonzini static void spapr_cpu_reset(void *opaque) 109253018216SPaolo Bonzini { 109328e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 109453018216SPaolo Bonzini PowerPCCPU *cpu = opaque; 1095259186a7SAndreas Färber CPUState *cs = CPU(cpu); 109653018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 109753018216SPaolo Bonzini 1098259186a7SAndreas Färber cpu_reset(cs); 109953018216SPaolo Bonzini 110053018216SPaolo Bonzini /* All CPUs start halted. CPU0 is unhalted from the machine level 110153018216SPaolo Bonzini * reset code and the rest are explicitly started up by the guest 110253018216SPaolo Bonzini * using an RTAS call */ 1103259186a7SAndreas Färber cs->halted = 1; 110453018216SPaolo Bonzini 110553018216SPaolo Bonzini env->spr[SPR_HIOR] = 0; 110653018216SPaolo Bonzini 11074be21d56SDavid Gibson env->external_htab = (uint8_t *)spapr->htab; 11085736245cSAneesh Kumar K.V if (kvm_enabled() && !env->external_htab) { 11095736245cSAneesh Kumar K.V /* 11105736245cSAneesh Kumar K.V * HV KVM, set external_htab to 1 so our ppc_hash64_load_hpte* 11115736245cSAneesh Kumar K.V * functions do the right thing. 11125736245cSAneesh Kumar K.V */ 11135736245cSAneesh Kumar K.V env->external_htab = (void *)1; 11145736245cSAneesh Kumar K.V } 111553018216SPaolo Bonzini env->htab_base = -1; 1116f3c75d42SAneesh Kumar K.V /* 1117f3c75d42SAneesh Kumar K.V * htab_mask is the mask used to normalize hash value to PTEG index. 1118f3c75d42SAneesh Kumar K.V * htab_shift is log2 of hash table size. 1119f3c75d42SAneesh Kumar K.V * We have 8 hpte per group, and each hpte is 16 bytes. 1120f3c75d42SAneesh Kumar K.V * ie have 128 bytes per hpte entry. 1121f3c75d42SAneesh Kumar K.V */ 112228e02042SDavid Gibson env->htab_mask = (1ULL << (spapr->htab_shift - 7)) - 1; 1123ec4936e1SStefan Weil env->spr[SPR_SDR1] = (target_ulong)(uintptr_t)spapr->htab | 112453018216SPaolo Bonzini (spapr->htab_shift - 18); 112553018216SPaolo Bonzini } 112653018216SPaolo Bonzini 112728e02042SDavid Gibson static void spapr_create_nvram(sPAPRMachineState *spapr) 112853018216SPaolo Bonzini { 11292ff3de68SMarkus Armbruster DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); 11303978b863SPaolo Bonzini DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); 113153018216SPaolo Bonzini 11323978b863SPaolo Bonzini if (dinfo) { 11334be74634SMarkus Armbruster qdev_prop_set_drive_nofail(dev, "drive", blk_by_legacy_dinfo(dinfo)); 113453018216SPaolo Bonzini } 113553018216SPaolo Bonzini 113653018216SPaolo Bonzini qdev_init_nofail(dev); 113753018216SPaolo Bonzini 113853018216SPaolo Bonzini spapr->nvram = (struct sPAPRNVRAM *)dev; 113953018216SPaolo Bonzini } 114053018216SPaolo Bonzini 114128e02042SDavid Gibson static void spapr_rtc_create(sPAPRMachineState *spapr) 114228df36a1SDavid Gibson { 114328df36a1SDavid Gibson DeviceState *dev = qdev_create(NULL, TYPE_SPAPR_RTC); 114428df36a1SDavid Gibson 114528df36a1SDavid Gibson qdev_init_nofail(dev); 114628df36a1SDavid Gibson spapr->rtc = dev; 114774e5ae28SDavid Gibson 114874e5ae28SDavid Gibson object_property_add_alias(qdev_get_machine(), "rtc-time", 114974e5ae28SDavid Gibson OBJECT(spapr->rtc), "date", NULL); 115028df36a1SDavid Gibson } 115128df36a1SDavid Gibson 115253018216SPaolo Bonzini /* Returns whether we want to use VGA or not */ 115353018216SPaolo Bonzini static int spapr_vga_init(PCIBus *pci_bus) 115453018216SPaolo Bonzini { 115553018216SPaolo Bonzini switch (vga_interface_type) { 115653018216SPaolo Bonzini case VGA_NONE: 11577effdaa3SMark Wu return false; 11587effdaa3SMark Wu case VGA_DEVICE: 11597effdaa3SMark Wu return true; 116053018216SPaolo Bonzini case VGA_STD: 116153018216SPaolo Bonzini return pci_vga_init(pci_bus) != NULL; 116253018216SPaolo Bonzini default: 116353018216SPaolo Bonzini fprintf(stderr, "This vga model is not supported," 116453018216SPaolo Bonzini "currently it only supports -vga std\n"); 116553018216SPaolo Bonzini exit(0); 116653018216SPaolo Bonzini } 116753018216SPaolo Bonzini } 116853018216SPaolo Bonzini 1169880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id) 1170880ae7deSDavid Gibson { 117128e02042SDavid Gibson sPAPRMachineState *spapr = (sPAPRMachineState *)opaque; 1172880ae7deSDavid Gibson int err = 0; 1173880ae7deSDavid Gibson 1174631b22eaSStefan Weil /* In earlier versions, there was no separate qdev for the PAPR 1175880ae7deSDavid Gibson * RTC, so the RTC offset was stored directly in sPAPREnvironment. 1176880ae7deSDavid Gibson * So when migrating from those versions, poke the incoming offset 1177880ae7deSDavid Gibson * value into the RTC device */ 1178880ae7deSDavid Gibson if (version_id < 3) { 1179880ae7deSDavid Gibson err = spapr_rtc_import_offset(spapr->rtc, spapr->rtc_offset); 1180880ae7deSDavid Gibson } 1181880ae7deSDavid Gibson 1182880ae7deSDavid Gibson return err; 1183880ae7deSDavid Gibson } 1184880ae7deSDavid Gibson 1185880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id) 1186880ae7deSDavid Gibson { 1187880ae7deSDavid Gibson return version_id < 3; 1188880ae7deSDavid Gibson } 1189880ae7deSDavid Gibson 11904be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = { 11914be21d56SDavid Gibson .name = "spapr", 1192880ae7deSDavid Gibson .version_id = 3, 11934be21d56SDavid Gibson .minimum_version_id = 1, 1194880ae7deSDavid Gibson .post_load = spapr_post_load, 11954be21d56SDavid Gibson .fields = (VMStateField[]) { 1196880ae7deSDavid Gibson /* used to be @next_irq */ 1197880ae7deSDavid Gibson VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4), 11984be21d56SDavid Gibson 11994be21d56SDavid Gibson /* RTC offset */ 120028e02042SDavid Gibson VMSTATE_UINT64_TEST(rtc_offset, sPAPRMachineState, version_before_3), 1201880ae7deSDavid Gibson 120228e02042SDavid Gibson VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2), 12034be21d56SDavid Gibson VMSTATE_END_OF_LIST() 12044be21d56SDavid Gibson }, 12054be21d56SDavid Gibson }; 12064be21d56SDavid Gibson 12074be21d56SDavid Gibson static int htab_save_setup(QEMUFile *f, void *opaque) 12084be21d56SDavid Gibson { 120928e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 12104be21d56SDavid Gibson 12114be21d56SDavid Gibson /* "Iteration" header */ 12124be21d56SDavid Gibson qemu_put_be32(f, spapr->htab_shift); 12134be21d56SDavid Gibson 1214e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 1215e68cb8b4SAlexey Kardashevskiy spapr->htab_save_index = 0; 1216e68cb8b4SAlexey Kardashevskiy spapr->htab_first_pass = true; 1217e68cb8b4SAlexey Kardashevskiy } else { 1218e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1219e68cb8b4SAlexey Kardashevskiy 1220e68cb8b4SAlexey Kardashevskiy spapr->htab_fd = kvmppc_get_htab_fd(false); 122101a57972SSamuel Mendoza-Jonas spapr->htab_fd_stale = false; 1222e68cb8b4SAlexey Kardashevskiy if (spapr->htab_fd < 0) { 1223e68cb8b4SAlexey Kardashevskiy fprintf(stderr, "Unable to open fd for reading hash table from KVM: %s\n", 1224e68cb8b4SAlexey Kardashevskiy strerror(errno)); 1225e68cb8b4SAlexey Kardashevskiy return -1; 1226e68cb8b4SAlexey Kardashevskiy } 12274be21d56SDavid Gibson } 12284be21d56SDavid Gibson 1229e68cb8b4SAlexey Kardashevskiy 1230e68cb8b4SAlexey Kardashevskiy return 0; 1231e68cb8b4SAlexey Kardashevskiy } 12324be21d56SDavid Gibson 123328e02042SDavid Gibson static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr, 12344be21d56SDavid Gibson int64_t max_ns) 12354be21d56SDavid Gibson { 12364be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 12374be21d56SDavid Gibson int index = spapr->htab_save_index; 1238bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 12394be21d56SDavid Gibson 12404be21d56SDavid Gibson assert(spapr->htab_first_pass); 12414be21d56SDavid Gibson 12424be21d56SDavid Gibson do { 12434be21d56SDavid Gibson int chunkstart; 12444be21d56SDavid Gibson 12454be21d56SDavid Gibson /* Consume invalid HPTEs */ 12464be21d56SDavid Gibson while ((index < htabslots) 12474be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 12484be21d56SDavid Gibson index++; 12494be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 12504be21d56SDavid Gibson } 12514be21d56SDavid Gibson 12524be21d56SDavid Gibson /* Consume valid HPTEs */ 12534be21d56SDavid Gibson chunkstart = index; 1254338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 12554be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 12564be21d56SDavid Gibson index++; 12574be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 12584be21d56SDavid Gibson } 12594be21d56SDavid Gibson 12604be21d56SDavid Gibson if (index > chunkstart) { 12614be21d56SDavid Gibson int n_valid = index - chunkstart; 12624be21d56SDavid Gibson 12634be21d56SDavid Gibson qemu_put_be32(f, chunkstart); 12644be21d56SDavid Gibson qemu_put_be16(f, n_valid); 12654be21d56SDavid Gibson qemu_put_be16(f, 0); 12664be21d56SDavid Gibson qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 12674be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 12684be21d56SDavid Gibson 1269bc72ad67SAlex Bligh if ((qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 12704be21d56SDavid Gibson break; 12714be21d56SDavid Gibson } 12724be21d56SDavid Gibson } 12734be21d56SDavid Gibson } while ((index < htabslots) && !qemu_file_rate_limit(f)); 12744be21d56SDavid Gibson 12754be21d56SDavid Gibson if (index >= htabslots) { 12764be21d56SDavid Gibson assert(index == htabslots); 12774be21d56SDavid Gibson index = 0; 12784be21d56SDavid Gibson spapr->htab_first_pass = false; 12794be21d56SDavid Gibson } 12804be21d56SDavid Gibson spapr->htab_save_index = index; 12814be21d56SDavid Gibson } 12824be21d56SDavid Gibson 128328e02042SDavid Gibson static int htab_save_later_pass(QEMUFile *f, sPAPRMachineState *spapr, 12844be21d56SDavid Gibson int64_t max_ns) 12854be21d56SDavid Gibson { 12864be21d56SDavid Gibson bool final = max_ns < 0; 12874be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 12884be21d56SDavid Gibson int examined = 0, sent = 0; 12894be21d56SDavid Gibson int index = spapr->htab_save_index; 1290bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 12914be21d56SDavid Gibson 12924be21d56SDavid Gibson assert(!spapr->htab_first_pass); 12934be21d56SDavid Gibson 12944be21d56SDavid Gibson do { 12954be21d56SDavid Gibson int chunkstart, invalidstart; 12964be21d56SDavid Gibson 12974be21d56SDavid Gibson /* Consume non-dirty HPTEs */ 12984be21d56SDavid Gibson while ((index < htabslots) 12994be21d56SDavid Gibson && !HPTE_DIRTY(HPTE(spapr->htab, index))) { 13004be21d56SDavid Gibson index++; 13014be21d56SDavid Gibson examined++; 13024be21d56SDavid Gibson } 13034be21d56SDavid Gibson 13044be21d56SDavid Gibson chunkstart = index; 13054be21d56SDavid Gibson /* Consume valid dirty HPTEs */ 1306338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 13074be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 13084be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 13094be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13104be21d56SDavid Gibson index++; 13114be21d56SDavid Gibson examined++; 13124be21d56SDavid Gibson } 13134be21d56SDavid Gibson 13144be21d56SDavid Gibson invalidstart = index; 13154be21d56SDavid Gibson /* Consume invalid dirty HPTEs */ 1316338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - invalidstart < USHRT_MAX) 13174be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 13184be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 13194be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13204be21d56SDavid Gibson index++; 13214be21d56SDavid Gibson examined++; 13224be21d56SDavid Gibson } 13234be21d56SDavid Gibson 13244be21d56SDavid Gibson if (index > chunkstart) { 13254be21d56SDavid Gibson int n_valid = invalidstart - chunkstart; 13264be21d56SDavid Gibson int n_invalid = index - invalidstart; 13274be21d56SDavid Gibson 13284be21d56SDavid Gibson qemu_put_be32(f, chunkstart); 13294be21d56SDavid Gibson qemu_put_be16(f, n_valid); 13304be21d56SDavid Gibson qemu_put_be16(f, n_invalid); 13314be21d56SDavid Gibson qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 13324be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 13334be21d56SDavid Gibson sent += index - chunkstart; 13344be21d56SDavid Gibson 1335bc72ad67SAlex Bligh if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 13364be21d56SDavid Gibson break; 13374be21d56SDavid Gibson } 13384be21d56SDavid Gibson } 13394be21d56SDavid Gibson 13404be21d56SDavid Gibson if (examined >= htabslots) { 13414be21d56SDavid Gibson break; 13424be21d56SDavid Gibson } 13434be21d56SDavid Gibson 13444be21d56SDavid Gibson if (index >= htabslots) { 13454be21d56SDavid Gibson assert(index == htabslots); 13464be21d56SDavid Gibson index = 0; 13474be21d56SDavid Gibson } 13484be21d56SDavid Gibson } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final)); 13494be21d56SDavid Gibson 13504be21d56SDavid Gibson if (index >= htabslots) { 13514be21d56SDavid Gibson assert(index == htabslots); 13524be21d56SDavid Gibson index = 0; 13534be21d56SDavid Gibson } 13544be21d56SDavid Gibson 13554be21d56SDavid Gibson spapr->htab_save_index = index; 13564be21d56SDavid Gibson 1357e68cb8b4SAlexey Kardashevskiy return (examined >= htabslots) && (sent == 0) ? 1 : 0; 13584be21d56SDavid Gibson } 13594be21d56SDavid Gibson 1360e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS 5000000 /* 5 ms */ 1361e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE 2048 1362e68cb8b4SAlexey Kardashevskiy 13634be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque) 13644be21d56SDavid Gibson { 136528e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 1366e68cb8b4SAlexey Kardashevskiy int rc = 0; 13674be21d56SDavid Gibson 13684be21d56SDavid Gibson /* Iteration header */ 13694be21d56SDavid Gibson qemu_put_be32(f, 0); 13704be21d56SDavid Gibson 1371e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1372e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1373e68cb8b4SAlexey Kardashevskiy 137401a57972SSamuel Mendoza-Jonas rc = spapr_check_htab_fd(spapr); 137501a57972SSamuel Mendoza-Jonas if (rc < 0) { 137601a57972SSamuel Mendoza-Jonas return rc; 137701a57972SSamuel Mendoza-Jonas } 137801a57972SSamuel Mendoza-Jonas 1379e68cb8b4SAlexey Kardashevskiy rc = kvmppc_save_htab(f, spapr->htab_fd, 1380e68cb8b4SAlexey Kardashevskiy MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); 1381e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1382e68cb8b4SAlexey Kardashevskiy return rc; 1383e68cb8b4SAlexey Kardashevskiy } 1384e68cb8b4SAlexey Kardashevskiy } else if (spapr->htab_first_pass) { 13854be21d56SDavid Gibson htab_save_first_pass(f, spapr, MAX_ITERATION_NS); 13864be21d56SDavid Gibson } else { 1387e68cb8b4SAlexey Kardashevskiy rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS); 13884be21d56SDavid Gibson } 13894be21d56SDavid Gibson 13904be21d56SDavid Gibson /* End marker */ 13914be21d56SDavid Gibson qemu_put_be32(f, 0); 13924be21d56SDavid Gibson qemu_put_be16(f, 0); 13934be21d56SDavid Gibson qemu_put_be16(f, 0); 13944be21d56SDavid Gibson 1395e68cb8b4SAlexey Kardashevskiy return rc; 13964be21d56SDavid Gibson } 13974be21d56SDavid Gibson 13984be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque) 13994be21d56SDavid Gibson { 140028e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 14014be21d56SDavid Gibson 14024be21d56SDavid Gibson /* Iteration header */ 14034be21d56SDavid Gibson qemu_put_be32(f, 0); 14044be21d56SDavid Gibson 1405e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1406e68cb8b4SAlexey Kardashevskiy int rc; 1407e68cb8b4SAlexey Kardashevskiy 1408e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1409e68cb8b4SAlexey Kardashevskiy 141001a57972SSamuel Mendoza-Jonas rc = spapr_check_htab_fd(spapr); 141101a57972SSamuel Mendoza-Jonas if (rc < 0) { 141201a57972SSamuel Mendoza-Jonas return rc; 141301a57972SSamuel Mendoza-Jonas } 141401a57972SSamuel Mendoza-Jonas 1415e68cb8b4SAlexey Kardashevskiy rc = kvmppc_save_htab(f, spapr->htab_fd, MAX_KVM_BUF_SIZE, -1); 1416e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1417e68cb8b4SAlexey Kardashevskiy return rc; 1418e68cb8b4SAlexey Kardashevskiy } 1419e68cb8b4SAlexey Kardashevskiy close(spapr->htab_fd); 1420e68cb8b4SAlexey Kardashevskiy spapr->htab_fd = -1; 1421e68cb8b4SAlexey Kardashevskiy } else { 14224be21d56SDavid Gibson htab_save_later_pass(f, spapr, -1); 1423e68cb8b4SAlexey Kardashevskiy } 14244be21d56SDavid Gibson 14254be21d56SDavid Gibson /* End marker */ 14264be21d56SDavid Gibson qemu_put_be32(f, 0); 14274be21d56SDavid Gibson qemu_put_be16(f, 0); 14284be21d56SDavid Gibson qemu_put_be16(f, 0); 14294be21d56SDavid Gibson 14304be21d56SDavid Gibson return 0; 14314be21d56SDavid Gibson } 14324be21d56SDavid Gibson 14334be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id) 14344be21d56SDavid Gibson { 143528e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 14364be21d56SDavid Gibson uint32_t section_hdr; 1437e68cb8b4SAlexey Kardashevskiy int fd = -1; 14384be21d56SDavid Gibson 14394be21d56SDavid Gibson if (version_id < 1 || version_id > 1) { 14404be21d56SDavid Gibson fprintf(stderr, "htab_load() bad version\n"); 14414be21d56SDavid Gibson return -EINVAL; 14424be21d56SDavid Gibson } 14434be21d56SDavid Gibson 14444be21d56SDavid Gibson section_hdr = qemu_get_be32(f); 14454be21d56SDavid Gibson 14464be21d56SDavid Gibson if (section_hdr) { 14474be21d56SDavid Gibson /* First section, just the hash shift */ 14484be21d56SDavid Gibson if (spapr->htab_shift != section_hdr) { 1449613e7a76SBharata B Rao error_report("htab_shift mismatch: source %d target %d", 1450613e7a76SBharata B Rao section_hdr, spapr->htab_shift); 14514be21d56SDavid Gibson return -EINVAL; 14524be21d56SDavid Gibson } 14534be21d56SDavid Gibson return 0; 14544be21d56SDavid Gibson } 14554be21d56SDavid Gibson 1456e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1457e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1458e68cb8b4SAlexey Kardashevskiy 1459e68cb8b4SAlexey Kardashevskiy fd = kvmppc_get_htab_fd(true); 1460e68cb8b4SAlexey Kardashevskiy if (fd < 0) { 1461e68cb8b4SAlexey Kardashevskiy fprintf(stderr, "Unable to open fd to restore KVM hash table: %s\n", 1462e68cb8b4SAlexey Kardashevskiy strerror(errno)); 1463e68cb8b4SAlexey Kardashevskiy } 1464e68cb8b4SAlexey Kardashevskiy } 1465e68cb8b4SAlexey Kardashevskiy 14664be21d56SDavid Gibson while (true) { 14674be21d56SDavid Gibson uint32_t index; 14684be21d56SDavid Gibson uint16_t n_valid, n_invalid; 14694be21d56SDavid Gibson 14704be21d56SDavid Gibson index = qemu_get_be32(f); 14714be21d56SDavid Gibson n_valid = qemu_get_be16(f); 14724be21d56SDavid Gibson n_invalid = qemu_get_be16(f); 14734be21d56SDavid Gibson 14744be21d56SDavid Gibson if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) { 14754be21d56SDavid Gibson /* End of Stream */ 14764be21d56SDavid Gibson break; 14774be21d56SDavid Gibson } 14784be21d56SDavid Gibson 1479e68cb8b4SAlexey Kardashevskiy if ((index + n_valid + n_invalid) > 14804be21d56SDavid Gibson (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) { 14814be21d56SDavid Gibson /* Bad index in stream */ 14824be21d56SDavid Gibson fprintf(stderr, "htab_load() bad index %d (%hd+%hd entries) " 1483e68cb8b4SAlexey Kardashevskiy "in htab stream (htab_shift=%d)\n", index, n_valid, n_invalid, 1484e68cb8b4SAlexey Kardashevskiy spapr->htab_shift); 14854be21d56SDavid Gibson return -EINVAL; 14864be21d56SDavid Gibson } 14874be21d56SDavid Gibson 1488e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 14894be21d56SDavid Gibson if (n_valid) { 14904be21d56SDavid Gibson qemu_get_buffer(f, HPTE(spapr->htab, index), 14914be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 14924be21d56SDavid Gibson } 14934be21d56SDavid Gibson if (n_invalid) { 14944be21d56SDavid Gibson memset(HPTE(spapr->htab, index + n_valid), 0, 14954be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_invalid); 14964be21d56SDavid Gibson } 1497e68cb8b4SAlexey Kardashevskiy } else { 1498e68cb8b4SAlexey Kardashevskiy int rc; 1499e68cb8b4SAlexey Kardashevskiy 1500e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 1501e68cb8b4SAlexey Kardashevskiy 1502e68cb8b4SAlexey Kardashevskiy rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid); 1503e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1504e68cb8b4SAlexey Kardashevskiy return rc; 1505e68cb8b4SAlexey Kardashevskiy } 1506e68cb8b4SAlexey Kardashevskiy } 1507e68cb8b4SAlexey Kardashevskiy } 1508e68cb8b4SAlexey Kardashevskiy 1509e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1510e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 1511e68cb8b4SAlexey Kardashevskiy close(fd); 15124be21d56SDavid Gibson } 15134be21d56SDavid Gibson 15144be21d56SDavid Gibson return 0; 15154be21d56SDavid Gibson } 15164be21d56SDavid Gibson 15174be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = { 15184be21d56SDavid Gibson .save_live_setup = htab_save_setup, 15194be21d56SDavid Gibson .save_live_iterate = htab_save_iterate, 15204be21d56SDavid Gibson .save_live_complete = htab_save_complete, 15214be21d56SDavid Gibson .load_state = htab_load, 15224be21d56SDavid Gibson }; 15234be21d56SDavid Gibson 15245b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device, 15255b2128d2SAlexander Graf Error **errp) 15265b2128d2SAlexander Graf { 15275b2128d2SAlexander Graf MachineState *machine = MACHINE(qdev_get_machine()); 15285b2128d2SAlexander Graf machine->boot_order = g_strdup(boot_device); 15295b2128d2SAlexander Graf } 15305b2128d2SAlexander Graf 1531bab99ea0SBharata B Rao static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu) 1532bab99ea0SBharata B Rao { 1533bab99ea0SBharata B Rao CPUPPCState *env = &cpu->env; 1534bab99ea0SBharata B Rao 1535bab99ea0SBharata B Rao /* Set time-base frequency to 512 MHz */ 1536bab99ea0SBharata B Rao cpu_ppc_tb_init(env, TIMEBASE_FREQ); 1537bab99ea0SBharata B Rao 1538bab99ea0SBharata B Rao /* PAPR always has exception vectors in RAM not ROM. To ensure this, 1539bab99ea0SBharata B Rao * MSR[IP] should never be set. 1540bab99ea0SBharata B Rao */ 1541bab99ea0SBharata B Rao env->msr_mask &= ~(1 << 6); 1542bab99ea0SBharata B Rao 1543bab99ea0SBharata B Rao /* Tell KVM that we're in PAPR mode */ 1544bab99ea0SBharata B Rao if (kvm_enabled()) { 1545bab99ea0SBharata B Rao kvmppc_set_papr(cpu); 1546bab99ea0SBharata B Rao } 1547bab99ea0SBharata B Rao 1548bab99ea0SBharata B Rao if (cpu->max_compat) { 1549bab99ea0SBharata B Rao if (ppc_set_compat(cpu, cpu->max_compat) < 0) { 1550bab99ea0SBharata B Rao exit(1); 1551bab99ea0SBharata B Rao } 1552bab99ea0SBharata B Rao } 1553bab99ea0SBharata B Rao 1554bab99ea0SBharata B Rao xics_cpu_setup(spapr->icp, cpu); 1555bab99ea0SBharata B Rao 1556bab99ea0SBharata B Rao qemu_register_reset(spapr_cpu_reset, cpu); 1557bab99ea0SBharata B Rao } 1558bab99ea0SBharata B Rao 1559224245bfSDavid Gibson /* 1560224245bfSDavid Gibson * Reset routine for LMB DR devices. 1561224245bfSDavid Gibson * 1562224245bfSDavid Gibson * Unlike PCI DR devices, LMB DR devices explicitly register this reset 1563224245bfSDavid Gibson * routine. Reset for PCI DR devices will be handled by PHB reset routine 1564224245bfSDavid Gibson * when it walks all its children devices. LMB devices reset occurs 1565224245bfSDavid Gibson * as part of spapr_ppc_reset(). 1566224245bfSDavid Gibson */ 1567224245bfSDavid Gibson static void spapr_drc_reset(void *opaque) 1568224245bfSDavid Gibson { 1569224245bfSDavid Gibson sPAPRDRConnector *drc = opaque; 1570224245bfSDavid Gibson DeviceState *d = DEVICE(drc); 1571224245bfSDavid Gibson 1572224245bfSDavid Gibson if (d) { 1573224245bfSDavid Gibson device_reset(d); 1574224245bfSDavid Gibson } 1575224245bfSDavid Gibson } 1576224245bfSDavid Gibson 1577224245bfSDavid Gibson static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr) 1578224245bfSDavid Gibson { 1579224245bfSDavid Gibson MachineState *machine = MACHINE(spapr); 1580224245bfSDavid Gibson uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 1581e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 1582224245bfSDavid Gibson int i; 1583224245bfSDavid Gibson 1584224245bfSDavid Gibson for (i = 0; i < nr_lmbs; i++) { 1585224245bfSDavid Gibson sPAPRDRConnector *drc; 1586224245bfSDavid Gibson uint64_t addr; 1587224245bfSDavid Gibson 1588e8f986fcSBharata B Rao addr = i * lmb_size + spapr->hotplug_memory.base; 1589224245bfSDavid Gibson drc = spapr_dr_connector_new(OBJECT(spapr), SPAPR_DR_CONNECTOR_TYPE_LMB, 1590224245bfSDavid Gibson addr/lmb_size); 1591224245bfSDavid Gibson qemu_register_reset(spapr_drc_reset, drc); 1592224245bfSDavid Gibson } 1593224245bfSDavid Gibson } 1594224245bfSDavid Gibson 1595224245bfSDavid Gibson /* 1596224245bfSDavid Gibson * If RAM size, maxmem size and individual node mem sizes aren't aligned 1597224245bfSDavid Gibson * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest 1598224245bfSDavid Gibson * since we can't support such unaligned sizes with DRCONF_MEMORY. 1599224245bfSDavid Gibson */ 1600224245bfSDavid Gibson static void spapr_validate_node_memory(MachineState *machine) 1601224245bfSDavid Gibson { 1602224245bfSDavid Gibson int i; 1603224245bfSDavid Gibson 1604224245bfSDavid Gibson if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE || 1605224245bfSDavid Gibson machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) { 1606224245bfSDavid Gibson error_report("Can't support memory configuration where RAM size " 1607224245bfSDavid Gibson "0x" RAM_ADDR_FMT " or maxmem size " 1608224245bfSDavid Gibson "0x" RAM_ADDR_FMT " isn't aligned to %llu MB", 1609224245bfSDavid Gibson machine->ram_size, machine->maxram_size, 1610224245bfSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE/M_BYTE); 1611224245bfSDavid Gibson exit(EXIT_FAILURE); 1612224245bfSDavid Gibson } 1613224245bfSDavid Gibson 1614224245bfSDavid Gibson for (i = 0; i < nb_numa_nodes; i++) { 1615224245bfSDavid Gibson if (numa_info[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) { 1616224245bfSDavid Gibson error_report("Can't support memory configuration where memory size" 1617224245bfSDavid Gibson " %" PRIx64 " of node %d isn't aligned to %llu MB", 1618224245bfSDavid Gibson numa_info[i].node_mem, i, 1619224245bfSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE/M_BYTE); 1620224245bfSDavid Gibson exit(EXIT_FAILURE); 1621224245bfSDavid Gibson } 1622224245bfSDavid Gibson } 1623224245bfSDavid Gibson } 1624224245bfSDavid Gibson 162553018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */ 16263ef96221SMarcel Apfelbaum static void ppc_spapr_init(MachineState *machine) 162753018216SPaolo Bonzini { 162828e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 1629224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 16303ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 16313ef96221SMarcel Apfelbaum const char *kernel_cmdline = machine->kernel_cmdline; 16323ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 163353018216SPaolo Bonzini PowerPCCPU *cpu; 163453018216SPaolo Bonzini PCIHostState *phb; 163553018216SPaolo Bonzini int i; 163653018216SPaolo Bonzini MemoryRegion *sysmem = get_system_memory(); 163753018216SPaolo Bonzini MemoryRegion *ram = g_new(MemoryRegion, 1); 1638658fa66bSAlexey Kardashevskiy MemoryRegion *rma_region; 1639658fa66bSAlexey Kardashevskiy void *rma = NULL; 164053018216SPaolo Bonzini hwaddr rma_alloc_size; 1641b082d65aSAlexey Kardashevskiy hwaddr node0_size = spapr_node0_size(); 164253018216SPaolo Bonzini uint32_t initrd_base = 0; 164353018216SPaolo Bonzini long kernel_size = 0, initrd_size = 0; 1644b7d1f77aSBenjamin Herrenschmidt long load_limit, fw_size; 164516457e7fSBenjamin Herrenschmidt bool kernel_le = false; 164653018216SPaolo Bonzini char *filename; 164753018216SPaolo Bonzini 164853018216SPaolo Bonzini msi_supported = true; 164953018216SPaolo Bonzini 165053018216SPaolo Bonzini QLIST_INIT(&spapr->phbs); 165153018216SPaolo Bonzini 165253018216SPaolo Bonzini cpu_ppc_hypercall = emulate_spapr_hypercall; 165353018216SPaolo Bonzini 165453018216SPaolo Bonzini /* Allocate RMA if necessary */ 1655658fa66bSAlexey Kardashevskiy rma_alloc_size = kvmppc_alloc_rma(&rma); 165653018216SPaolo Bonzini 165753018216SPaolo Bonzini if (rma_alloc_size == -1) { 1658730fce59SThomas Huth error_report("Unable to create RMA"); 165953018216SPaolo Bonzini exit(1); 166053018216SPaolo Bonzini } 166153018216SPaolo Bonzini 1662c4177479SAlexey Kardashevskiy if (rma_alloc_size && (rma_alloc_size < node0_size)) { 166353018216SPaolo Bonzini spapr->rma_size = rma_alloc_size; 166453018216SPaolo Bonzini } else { 1665c4177479SAlexey Kardashevskiy spapr->rma_size = node0_size; 166653018216SPaolo Bonzini 166753018216SPaolo Bonzini /* With KVM, we don't actually know whether KVM supports an 166853018216SPaolo Bonzini * unbounded RMA (PR KVM) or is limited by the hash table size 166953018216SPaolo Bonzini * (HV KVM using VRMA), so we always assume the latter 167053018216SPaolo Bonzini * 167153018216SPaolo Bonzini * In that case, we also limit the initial allocations for RTAS 167253018216SPaolo Bonzini * etc... to 256M since we have no way to know what the VRMA size 167353018216SPaolo Bonzini * is going to be as it depends on the size of the hash table 167453018216SPaolo Bonzini * isn't determined yet. 167553018216SPaolo Bonzini */ 167653018216SPaolo Bonzini if (kvm_enabled()) { 167753018216SPaolo Bonzini spapr->vrma_adjust = 1; 167853018216SPaolo Bonzini spapr->rma_size = MIN(spapr->rma_size, 0x10000000); 167953018216SPaolo Bonzini } 168053018216SPaolo Bonzini } 168153018216SPaolo Bonzini 1682c4177479SAlexey Kardashevskiy if (spapr->rma_size > node0_size) { 1683c4177479SAlexey Kardashevskiy fprintf(stderr, "Error: Numa node 0 has to span the RMA (%#08"HWADDR_PRIx")\n", 1684c4177479SAlexey Kardashevskiy spapr->rma_size); 1685c4177479SAlexey Kardashevskiy exit(1); 1686c4177479SAlexey Kardashevskiy } 1687c4177479SAlexey Kardashevskiy 1688b7d1f77aSBenjamin Herrenschmidt /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */ 1689b7d1f77aSBenjamin Herrenschmidt load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; 169053018216SPaolo Bonzini 169153018216SPaolo Bonzini /* We aim for a hash table of size 1/128 the size of RAM. The 169253018216SPaolo Bonzini * normal rule of thumb is 1/64 the size of RAM, but that's much 169353018216SPaolo Bonzini * more than needed for the Linux guests we support. */ 169453018216SPaolo Bonzini spapr->htab_shift = 18; /* Minimum architected size */ 169553018216SPaolo Bonzini while (spapr->htab_shift <= 46) { 1696ce881f77SBharata B Rao if ((1ULL << (spapr->htab_shift + 7)) >= machine->maxram_size) { 169753018216SPaolo Bonzini break; 169853018216SPaolo Bonzini } 169953018216SPaolo Bonzini spapr->htab_shift++; 170053018216SPaolo Bonzini } 170153018216SPaolo Bonzini 17027b565160SDavid Gibson /* Set up Interrupt Controller before we create the VCPUs */ 1703446f16a6SMarcel Apfelbaum spapr->icp = xics_system_init(machine, 17049e734e3dSBharata B Rao DIV_ROUND_UP(max_cpus * kvmppc_smt_threads(), 1705f303f117SGreg Kurz smp_threads), 17067b565160SDavid Gibson XICS_IRQS); 17077b565160SDavid Gibson 1708224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 1709224245bfSDavid Gibson spapr_validate_node_memory(machine); 1710224245bfSDavid Gibson } 1711224245bfSDavid Gibson 171253018216SPaolo Bonzini /* init CPUs */ 171319fb2c36SBharata B Rao if (machine->cpu_model == NULL) { 171419fb2c36SBharata B Rao machine->cpu_model = kvm_enabled() ? "host" : "POWER7"; 171553018216SPaolo Bonzini } 171653018216SPaolo Bonzini for (i = 0; i < smp_cpus; i++) { 171719fb2c36SBharata B Rao cpu = cpu_ppc_init(machine->cpu_model); 171853018216SPaolo Bonzini if (cpu == NULL) { 171953018216SPaolo Bonzini fprintf(stderr, "Unable to find PowerPC CPU definition\n"); 172053018216SPaolo Bonzini exit(1); 172153018216SPaolo Bonzini } 1722bab99ea0SBharata B Rao spapr_cpu_init(spapr, cpu); 172353018216SPaolo Bonzini } 172453018216SPaolo Bonzini 1725026bfd89SDavid Gibson if (kvm_enabled()) { 1726026bfd89SDavid Gibson /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ 1727026bfd89SDavid Gibson kvmppc_enable_logical_ci_hcalls(); 1728ef9971ddSAlexey Kardashevskiy kvmppc_enable_set_mode_hcall(); 1729026bfd89SDavid Gibson } 1730026bfd89SDavid Gibson 173153018216SPaolo Bonzini /* allocate RAM */ 1732f92f5da1SAlexey Kardashevskiy memory_region_allocate_system_memory(ram, NULL, "ppc_spapr.ram", 1733fb164994SDavid Gibson machine->ram_size); 1734f92f5da1SAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, ram); 173553018216SPaolo Bonzini 1736658fa66bSAlexey Kardashevskiy if (rma_alloc_size && rma) { 1737658fa66bSAlexey Kardashevskiy rma_region = g_new(MemoryRegion, 1); 1738658fa66bSAlexey Kardashevskiy memory_region_init_ram_ptr(rma_region, NULL, "ppc_spapr.rma", 1739658fa66bSAlexey Kardashevskiy rma_alloc_size, rma); 1740658fa66bSAlexey Kardashevskiy vmstate_register_ram_global(rma_region); 1741658fa66bSAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, rma_region); 1742658fa66bSAlexey Kardashevskiy } 1743658fa66bSAlexey Kardashevskiy 17444a1c9cf0SBharata B Rao /* initialize hotplug memory address space */ 17454a1c9cf0SBharata B Rao if (machine->ram_size < machine->maxram_size) { 17464a1c9cf0SBharata B Rao ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size; 17474a1c9cf0SBharata B Rao 17484a1c9cf0SBharata B Rao if (machine->ram_slots > SPAPR_MAX_RAM_SLOTS) { 174919a35c9eSBharata B Rao error_report("Specified number of memory slots %"PRIu64" exceeds max supported %d\n", 175019a35c9eSBharata B Rao machine->ram_slots, SPAPR_MAX_RAM_SLOTS); 17514a1c9cf0SBharata B Rao exit(EXIT_FAILURE); 17524a1c9cf0SBharata B Rao } 17534a1c9cf0SBharata B Rao 17544a1c9cf0SBharata B Rao spapr->hotplug_memory.base = ROUND_UP(machine->ram_size, 17554a1c9cf0SBharata B Rao SPAPR_HOTPLUG_MEM_ALIGN); 17564a1c9cf0SBharata B Rao memory_region_init(&spapr->hotplug_memory.mr, OBJECT(spapr), 17574a1c9cf0SBharata B Rao "hotplug-memory", hotplug_mem_size); 17584a1c9cf0SBharata B Rao memory_region_add_subregion(sysmem, spapr->hotplug_memory.base, 17594a1c9cf0SBharata B Rao &spapr->hotplug_memory.mr); 17604a1c9cf0SBharata B Rao } 17614a1c9cf0SBharata B Rao 1762224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 1763224245bfSDavid Gibson spapr_create_lmb_dr_connectors(spapr); 1764224245bfSDavid Gibson } 1765224245bfSDavid Gibson 176653018216SPaolo Bonzini filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin"); 17674c56440dSStefan Weil if (!filename) { 1768730fce59SThomas Huth error_report("Could not find LPAR rtas '%s'", "spapr-rtas.bin"); 17694c56440dSStefan Weil exit(1); 17704c56440dSStefan Weil } 1771b7d1f77aSBenjamin Herrenschmidt spapr->rtas_size = get_image_size(filename); 1772b7d1f77aSBenjamin Herrenschmidt spapr->rtas_blob = g_malloc(spapr->rtas_size); 1773b7d1f77aSBenjamin Herrenschmidt if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) { 1774730fce59SThomas Huth error_report("Could not load LPAR rtas '%s'", filename); 177553018216SPaolo Bonzini exit(1); 177653018216SPaolo Bonzini } 177753018216SPaolo Bonzini if (spapr->rtas_size > RTAS_MAX_SIZE) { 1778730fce59SThomas Huth error_report("RTAS too big ! 0x%zx bytes (max is 0x%x)", 17792f285bddSPeter Maydell (size_t)spapr->rtas_size, RTAS_MAX_SIZE); 178053018216SPaolo Bonzini exit(1); 178153018216SPaolo Bonzini } 178253018216SPaolo Bonzini g_free(filename); 178353018216SPaolo Bonzini 178453018216SPaolo Bonzini /* Set up EPOW events infrastructure */ 178553018216SPaolo Bonzini spapr_events_init(spapr); 178653018216SPaolo Bonzini 178712f42174SDavid Gibson /* Set up the RTC RTAS interfaces */ 178828df36a1SDavid Gibson spapr_rtc_create(spapr); 178912f42174SDavid Gibson 179053018216SPaolo Bonzini /* Set up VIO bus */ 179153018216SPaolo Bonzini spapr->vio_bus = spapr_vio_bus_init(); 179253018216SPaolo Bonzini 179353018216SPaolo Bonzini for (i = 0; i < MAX_SERIAL_PORTS; i++) { 179453018216SPaolo Bonzini if (serial_hds[i]) { 179553018216SPaolo Bonzini spapr_vty_create(spapr->vio_bus, serial_hds[i]); 179653018216SPaolo Bonzini } 179753018216SPaolo Bonzini } 179853018216SPaolo Bonzini 179953018216SPaolo Bonzini /* We always have at least the nvram device on VIO */ 180053018216SPaolo Bonzini spapr_create_nvram(spapr); 180153018216SPaolo Bonzini 180253018216SPaolo Bonzini /* Set up PCI */ 180353018216SPaolo Bonzini spapr_pci_rtas_init(); 180453018216SPaolo Bonzini 180589dfd6e1SDavid Gibson phb = spapr_create_phb(spapr, 0); 180653018216SPaolo Bonzini 180753018216SPaolo Bonzini for (i = 0; i < nb_nics; i++) { 180853018216SPaolo Bonzini NICInfo *nd = &nd_table[i]; 180953018216SPaolo Bonzini 181053018216SPaolo Bonzini if (!nd->model) { 181153018216SPaolo Bonzini nd->model = g_strdup("ibmveth"); 181253018216SPaolo Bonzini } 181353018216SPaolo Bonzini 181453018216SPaolo Bonzini if (strcmp(nd->model, "ibmveth") == 0) { 181553018216SPaolo Bonzini spapr_vlan_create(spapr->vio_bus, nd); 181653018216SPaolo Bonzini } else { 181729b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL); 181853018216SPaolo Bonzini } 181953018216SPaolo Bonzini } 182053018216SPaolo Bonzini 182153018216SPaolo Bonzini for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { 182253018216SPaolo Bonzini spapr_vscsi_create(spapr->vio_bus); 182353018216SPaolo Bonzini } 182453018216SPaolo Bonzini 182553018216SPaolo Bonzini /* Graphics */ 182653018216SPaolo Bonzini if (spapr_vga_init(phb->bus)) { 182753018216SPaolo Bonzini spapr->has_graphics = true; 1828c6e76503SPaolo Bonzini machine->usb |= defaults_enabled() && !machine->usb_disabled; 182953018216SPaolo Bonzini } 183053018216SPaolo Bonzini 18314ee9ced9SMarcel Apfelbaum if (machine->usb) { 183253018216SPaolo Bonzini pci_create_simple(phb->bus, -1, "pci-ohci"); 1833c86580b8SMarkus Armbruster 183453018216SPaolo Bonzini if (spapr->has_graphics) { 1835c86580b8SMarkus Armbruster USBBus *usb_bus = usb_bus_find(-1); 1836c86580b8SMarkus Armbruster 1837c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-kbd"); 1838c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-mouse"); 183953018216SPaolo Bonzini } 184053018216SPaolo Bonzini } 184153018216SPaolo Bonzini 184253018216SPaolo Bonzini if (spapr->rma_size < (MIN_RMA_SLOF << 20)) { 184353018216SPaolo Bonzini fprintf(stderr, "qemu: pSeries SLOF firmware requires >= " 184453018216SPaolo Bonzini "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF); 184553018216SPaolo Bonzini exit(1); 184653018216SPaolo Bonzini } 184753018216SPaolo Bonzini 184853018216SPaolo Bonzini if (kernel_filename) { 184953018216SPaolo Bonzini uint64_t lowaddr = 0; 185053018216SPaolo Bonzini 185153018216SPaolo Bonzini kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL, 185253018216SPaolo Bonzini NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0); 18533b66da82SAlexey Kardashevskiy if (kernel_size == ELF_LOAD_WRONG_ENDIAN) { 185416457e7fSBenjamin Herrenschmidt kernel_size = load_elf(kernel_filename, 185516457e7fSBenjamin Herrenschmidt translate_kernel_address, NULL, 185616457e7fSBenjamin Herrenschmidt NULL, &lowaddr, NULL, 0, ELF_MACHINE, 0); 185716457e7fSBenjamin Herrenschmidt kernel_le = kernel_size > 0; 185816457e7fSBenjamin Herrenschmidt } 185916457e7fSBenjamin Herrenschmidt if (kernel_size < 0) { 18603b66da82SAlexey Kardashevskiy fprintf(stderr, "qemu: error loading %s: %s\n", 18613b66da82SAlexey Kardashevskiy kernel_filename, load_elf_strerror(kernel_size)); 186253018216SPaolo Bonzini exit(1); 186353018216SPaolo Bonzini } 186453018216SPaolo Bonzini 186553018216SPaolo Bonzini /* load initrd */ 186653018216SPaolo Bonzini if (initrd_filename) { 186753018216SPaolo Bonzini /* Try to locate the initrd in the gap between the kernel 186853018216SPaolo Bonzini * and the firmware. Add a bit of space just in case 186953018216SPaolo Bonzini */ 187053018216SPaolo Bonzini initrd_base = (KERNEL_LOAD_ADDR + kernel_size + 0x1ffff) & ~0xffff; 187153018216SPaolo Bonzini initrd_size = load_image_targphys(initrd_filename, initrd_base, 187253018216SPaolo Bonzini load_limit - initrd_base); 187353018216SPaolo Bonzini if (initrd_size < 0) { 187453018216SPaolo Bonzini fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 187553018216SPaolo Bonzini initrd_filename); 187653018216SPaolo Bonzini exit(1); 187753018216SPaolo Bonzini } 187853018216SPaolo Bonzini } else { 187953018216SPaolo Bonzini initrd_base = 0; 188053018216SPaolo Bonzini initrd_size = 0; 188153018216SPaolo Bonzini } 188253018216SPaolo Bonzini } 188353018216SPaolo Bonzini 18848e7ea787SAndreas Färber if (bios_name == NULL) { 18858e7ea787SAndreas Färber bios_name = FW_FILE_NAME; 18868e7ea787SAndreas Färber } 18878e7ea787SAndreas Färber filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 18884c56440dSStefan Weil if (!filename) { 188968fea5a0SThomas Huth error_report("Could not find LPAR firmware '%s'", bios_name); 18904c56440dSStefan Weil exit(1); 18914c56440dSStefan Weil } 189253018216SPaolo Bonzini fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); 189368fea5a0SThomas Huth if (fw_size <= 0) { 189468fea5a0SThomas Huth error_report("Could not load LPAR firmware '%s'", filename); 189553018216SPaolo Bonzini exit(1); 189653018216SPaolo Bonzini } 189753018216SPaolo Bonzini g_free(filename); 189853018216SPaolo Bonzini 189928e02042SDavid Gibson /* FIXME: Should register things through the MachineState's qdev 190028e02042SDavid Gibson * interface, this is a legacy from the sPAPREnvironment structure 190128e02042SDavid Gibson * which predated MachineState but had a similar function */ 19024be21d56SDavid Gibson vmstate_register(NULL, 0, &vmstate_spapr, spapr); 19034be21d56SDavid Gibson register_savevm_live(NULL, "spapr/htab", -1, 1, 19044be21d56SDavid Gibson &savevm_htab_handlers, spapr); 19054be21d56SDavid Gibson 190653018216SPaolo Bonzini /* Prepare the device tree */ 19073bbf37f2SAndreas Färber spapr->fdt_skel = spapr_create_fdt_skel(initrd_base, initrd_size, 190816457e7fSBenjamin Herrenschmidt kernel_size, kernel_le, 190931fe14d1SNathan Fontenot kernel_cmdline, 191031fe14d1SNathan Fontenot spapr->check_exception_irq); 191153018216SPaolo Bonzini assert(spapr->fdt_skel != NULL); 19125b2128d2SAlexander Graf 191346503c2bSMichael Roth /* used by RTAS */ 191446503c2bSMichael Roth QTAILQ_INIT(&spapr->ccs_list); 191546503c2bSMichael Roth qemu_register_reset(spapr_ccs_reset_hook, spapr); 191646503c2bSMichael Roth 19175b2128d2SAlexander Graf qemu_register_boot_set(spapr_boot_set, spapr); 191853018216SPaolo Bonzini } 191953018216SPaolo Bonzini 1920135a129aSAneesh Kumar K.V static int spapr_kvm_type(const char *vm_type) 1921135a129aSAneesh Kumar K.V { 1922135a129aSAneesh Kumar K.V if (!vm_type) { 1923135a129aSAneesh Kumar K.V return 0; 1924135a129aSAneesh Kumar K.V } 1925135a129aSAneesh Kumar K.V 1926135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "HV")) { 1927135a129aSAneesh Kumar K.V return 1; 1928135a129aSAneesh Kumar K.V } 1929135a129aSAneesh Kumar K.V 1930135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "PR")) { 1931135a129aSAneesh Kumar K.V return 2; 1932135a129aSAneesh Kumar K.V } 1933135a129aSAneesh Kumar K.V 1934135a129aSAneesh Kumar K.V error_report("Unknown kvm-type specified '%s'", vm_type); 1935135a129aSAneesh Kumar K.V exit(1); 1936135a129aSAneesh Kumar K.V } 1937135a129aSAneesh Kumar K.V 193871461b0fSAlexey Kardashevskiy /* 1939627b84f4SGonglei * Implementation of an interface to adjust firmware path 194071461b0fSAlexey Kardashevskiy * for the bootindex property handling. 194171461b0fSAlexey Kardashevskiy */ 194271461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, 194371461b0fSAlexey Kardashevskiy DeviceState *dev) 194471461b0fSAlexey Kardashevskiy { 194571461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \ 194671461b0fSAlexey Kardashevskiy ((type *)object_dynamic_cast(OBJECT(obj), (name))) 194771461b0fSAlexey Kardashevskiy SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); 194871461b0fSAlexey Kardashevskiy sPAPRPHBState *phb = CAST(sPAPRPHBState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); 194971461b0fSAlexey Kardashevskiy 195071461b0fSAlexey Kardashevskiy if (d) { 195171461b0fSAlexey Kardashevskiy void *spapr = CAST(void, bus->parent, "spapr-vscsi"); 195271461b0fSAlexey Kardashevskiy VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); 195371461b0fSAlexey Kardashevskiy USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); 195471461b0fSAlexey Kardashevskiy 195571461b0fSAlexey Kardashevskiy if (spapr) { 195671461b0fSAlexey Kardashevskiy /* 195771461b0fSAlexey Kardashevskiy * Replace "channel@0/disk@0,0" with "disk@8000000000000000": 195871461b0fSAlexey Kardashevskiy * We use SRP luns of the form 8000 | (bus << 8) | (id << 5) | lun 195971461b0fSAlexey Kardashevskiy * in the top 16 bits of the 64-bit LUN 196071461b0fSAlexey Kardashevskiy */ 196171461b0fSAlexey Kardashevskiy unsigned id = 0x8000 | (d->id << 8) | d->lun; 196271461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 196371461b0fSAlexey Kardashevskiy (uint64_t)id << 48); 196471461b0fSAlexey Kardashevskiy } else if (virtio) { 196571461b0fSAlexey Kardashevskiy /* 196671461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (target << 8) | lun 196771461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 196871461b0fSAlexey Kardashevskiy * Note: the quote above is from SLOF and it is wrong, 196971461b0fSAlexey Kardashevskiy * the actual binding is: 197071461b0fSAlexey Kardashevskiy * swap 0100 or 10 << or 20 << ( target lun-id -- srplun ) 197171461b0fSAlexey Kardashevskiy */ 197271461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (d->id << 16) | d->lun; 197371461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 197471461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 197571461b0fSAlexey Kardashevskiy } else if (usb) { 197671461b0fSAlexey Kardashevskiy /* 197771461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (usb-port << 16) | lun 197871461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 197971461b0fSAlexey Kardashevskiy */ 198071461b0fSAlexey Kardashevskiy unsigned usb_port = atoi(usb->port->path); 198171461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (usb_port << 16) | d->lun; 198271461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 198371461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 198471461b0fSAlexey Kardashevskiy } 198571461b0fSAlexey Kardashevskiy } 198671461b0fSAlexey Kardashevskiy 198771461b0fSAlexey Kardashevskiy if (phb) { 198871461b0fSAlexey Kardashevskiy /* Replace "pci" with "pci@800000020000000" */ 198971461b0fSAlexey Kardashevskiy return g_strdup_printf("pci@%"PRIX64, phb->buid); 199071461b0fSAlexey Kardashevskiy } 199171461b0fSAlexey Kardashevskiy 199271461b0fSAlexey Kardashevskiy return NULL; 199371461b0fSAlexey Kardashevskiy } 199471461b0fSAlexey Kardashevskiy 199523825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp) 199623825581SEduardo Habkost { 199728e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 199823825581SEduardo Habkost 199928e02042SDavid Gibson return g_strdup(spapr->kvm_type); 200023825581SEduardo Habkost } 200123825581SEduardo Habkost 200223825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp) 200323825581SEduardo Habkost { 200428e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 200523825581SEduardo Habkost 200628e02042SDavid Gibson g_free(spapr->kvm_type); 200728e02042SDavid Gibson spapr->kvm_type = g_strdup(value); 200823825581SEduardo Habkost } 200923825581SEduardo Habkost 201023825581SEduardo Habkost static void spapr_machine_initfn(Object *obj) 201123825581SEduardo Habkost { 201223825581SEduardo Habkost object_property_add_str(obj, "kvm-type", 201323825581SEduardo Habkost spapr_get_kvm_type, spapr_set_kvm_type, NULL); 201449d2e648SMarcel Apfelbaum object_property_set_description(obj, "kvm-type", 201549d2e648SMarcel Apfelbaum "Specifies the KVM virtualization mode (HV, PR)", 201649d2e648SMarcel Apfelbaum NULL); 201723825581SEduardo Habkost } 201823825581SEduardo Habkost 201934316482SAlexey Kardashevskiy static void ppc_cpu_do_nmi_on_cpu(void *arg) 202034316482SAlexey Kardashevskiy { 202134316482SAlexey Kardashevskiy CPUState *cs = arg; 202234316482SAlexey Kardashevskiy 202334316482SAlexey Kardashevskiy cpu_synchronize_state(cs); 202434316482SAlexey Kardashevskiy ppc_cpu_do_system_reset(cs); 202534316482SAlexey Kardashevskiy } 202634316482SAlexey Kardashevskiy 202734316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) 202834316482SAlexey Kardashevskiy { 202934316482SAlexey Kardashevskiy CPUState *cs; 203034316482SAlexey Kardashevskiy 203134316482SAlexey Kardashevskiy CPU_FOREACH(cs) { 203234316482SAlexey Kardashevskiy async_run_on_cpu(cs, ppc_cpu_do_nmi_on_cpu, cs); 203334316482SAlexey Kardashevskiy } 203434316482SAlexey Kardashevskiy } 203534316482SAlexey Kardashevskiy 2036c20d332aSBharata B Rao static void spapr_add_lmbs(DeviceState *dev, uint64_t addr, uint64_t size, 2037c20d332aSBharata B Rao uint32_t node, Error **errp) 2038c20d332aSBharata B Rao { 2039c20d332aSBharata B Rao sPAPRDRConnector *drc; 2040c20d332aSBharata B Rao sPAPRDRConnectorClass *drck; 2041c20d332aSBharata B Rao uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; 2042c20d332aSBharata B Rao int i, fdt_offset, fdt_size; 2043c20d332aSBharata B Rao void *fdt; 2044c20d332aSBharata B Rao 2045c20d332aSBharata B Rao /* 2046c20d332aSBharata B Rao * Check for DRC connectors and send hotplug notification to the 2047c20d332aSBharata B Rao * guest only in case of hotplugged memory. This allows cold plugged 2048c20d332aSBharata B Rao * memory to be specified at boot time. 2049c20d332aSBharata B Rao */ 2050c20d332aSBharata B Rao if (!dev->hotplugged) { 2051c20d332aSBharata B Rao return; 2052c20d332aSBharata B Rao } 2053c20d332aSBharata B Rao 2054c20d332aSBharata B Rao for (i = 0; i < nr_lmbs; i++) { 2055c20d332aSBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, 2056c20d332aSBharata B Rao addr/SPAPR_MEMORY_BLOCK_SIZE); 2057c20d332aSBharata B Rao g_assert(drc); 2058c20d332aSBharata B Rao 2059c20d332aSBharata B Rao fdt = create_device_tree(&fdt_size); 2060c20d332aSBharata B Rao fdt_offset = spapr_populate_memory_node(fdt, node, addr, 2061c20d332aSBharata B Rao SPAPR_MEMORY_BLOCK_SIZE); 2062c20d332aSBharata B Rao 2063c20d332aSBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 2064c20d332aSBharata B Rao drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp); 2065c20d332aSBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE; 2066c20d332aSBharata B Rao } 2067*0a417869SBharata B Rao spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs); 2068c20d332aSBharata B Rao } 2069c20d332aSBharata B Rao 2070c20d332aSBharata B Rao static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 2071c20d332aSBharata B Rao uint32_t node, Error **errp) 2072c20d332aSBharata B Rao { 2073c20d332aSBharata B Rao Error *local_err = NULL; 2074c20d332aSBharata B Rao sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev); 2075c20d332aSBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 2076c20d332aSBharata B Rao PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); 2077c20d332aSBharata B Rao MemoryRegion *mr = ddc->get_memory_region(dimm); 2078c20d332aSBharata B Rao uint64_t align = memory_region_get_alignment(mr); 2079c20d332aSBharata B Rao uint64_t size = memory_region_size(mr); 2080c20d332aSBharata B Rao uint64_t addr; 2081c20d332aSBharata B Rao 2082c20d332aSBharata B Rao if (size % SPAPR_MEMORY_BLOCK_SIZE) { 2083c20d332aSBharata B Rao error_setg(&local_err, "Hotplugged memory size must be a multiple of " 2084c20d332aSBharata B Rao "%lld MB", SPAPR_MEMORY_BLOCK_SIZE/M_BYTE); 2085c20d332aSBharata B Rao goto out; 2086c20d332aSBharata B Rao } 2087c20d332aSBharata B Rao 2088c20d332aSBharata B Rao pc_dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, &local_err); 2089c20d332aSBharata B Rao if (local_err) { 2090c20d332aSBharata B Rao goto out; 2091c20d332aSBharata B Rao } 2092c20d332aSBharata B Rao 2093c20d332aSBharata B Rao addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err); 2094c20d332aSBharata B Rao if (local_err) { 2095c20d332aSBharata B Rao pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr); 2096c20d332aSBharata B Rao goto out; 2097c20d332aSBharata B Rao } 2098c20d332aSBharata B Rao 2099c20d332aSBharata B Rao spapr_add_lmbs(dev, addr, size, node, &error_abort); 2100c20d332aSBharata B Rao 2101c20d332aSBharata B Rao out: 2102c20d332aSBharata B Rao error_propagate(errp, local_err); 2103c20d332aSBharata B Rao } 2104c20d332aSBharata B Rao 2105c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, 2106c20d332aSBharata B Rao DeviceState *dev, Error **errp) 2107c20d332aSBharata B Rao { 2108c20d332aSBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); 2109c20d332aSBharata B Rao 2110c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 2111b556854bSBharata B Rao int node; 2112c20d332aSBharata B Rao 2113c20d332aSBharata B Rao if (!smc->dr_lmb_enabled) { 2114c20d332aSBharata B Rao error_setg(errp, "Memory hotplug not supported for this machine"); 2115c20d332aSBharata B Rao return; 2116c20d332aSBharata B Rao } 2117c20d332aSBharata B Rao node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP, errp); 2118c20d332aSBharata B Rao if (*errp) { 2119c20d332aSBharata B Rao return; 2120c20d332aSBharata B Rao } 2121c20d332aSBharata B Rao 2122b556854bSBharata B Rao /* 2123b556854bSBharata B Rao * Currently PowerPC kernel doesn't allow hot-adding memory to 2124b556854bSBharata B Rao * memory-less node, but instead will silently add the memory 2125b556854bSBharata B Rao * to the first node that has some memory. This causes two 2126b556854bSBharata B Rao * unexpected behaviours for the user. 2127b556854bSBharata B Rao * 2128b556854bSBharata B Rao * - Memory gets hotplugged to a different node than what the user 2129b556854bSBharata B Rao * specified. 2130b556854bSBharata B Rao * - Since pc-dimm subsystem in QEMU still thinks that memory belongs 2131b556854bSBharata B Rao * to memory-less node, a reboot will set things accordingly 2132b556854bSBharata B Rao * and the previously hotplugged memory now ends in the right node. 2133b556854bSBharata B Rao * This appears as if some memory moved from one node to another. 2134b556854bSBharata B Rao * 2135b556854bSBharata B Rao * So until kernel starts supporting memory hotplug to memory-less 2136b556854bSBharata B Rao * nodes, just prevent such attempts upfront in QEMU. 2137b556854bSBharata B Rao */ 2138b556854bSBharata B Rao if (nb_numa_nodes && !numa_info[node].node_mem) { 2139b556854bSBharata B Rao error_setg(errp, "Can't hotplug memory to memory-less node %d", 2140b556854bSBharata B Rao node); 2141b556854bSBharata B Rao return; 2142b556854bSBharata B Rao } 2143b556854bSBharata B Rao 2144c20d332aSBharata B Rao spapr_memory_plug(hotplug_dev, dev, node, errp); 2145c20d332aSBharata B Rao } 2146c20d332aSBharata B Rao } 2147c20d332aSBharata B Rao 2148c20d332aSBharata B Rao static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, 2149c20d332aSBharata B Rao DeviceState *dev, Error **errp) 2150c20d332aSBharata B Rao { 2151c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 2152c20d332aSBharata B Rao error_setg(errp, "Memory hot unplug not supported by sPAPR"); 2153c20d332aSBharata B Rao } 2154c20d332aSBharata B Rao } 2155c20d332aSBharata B Rao 2156c20d332aSBharata B Rao static HotplugHandler *spapr_get_hotpug_handler(MachineState *machine, 2157c20d332aSBharata B Rao DeviceState *dev) 2158c20d332aSBharata B Rao { 2159c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 2160c20d332aSBharata B Rao return HOTPLUG_HANDLER(machine); 2161c20d332aSBharata B Rao } 2162c20d332aSBharata B Rao return NULL; 2163c20d332aSBharata B Rao } 2164c20d332aSBharata B Rao 216529ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data) 216653018216SPaolo Bonzini { 216729ee3247SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 2168224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc); 216971461b0fSAlexey Kardashevskiy FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); 217034316482SAlexey Kardashevskiy NMIClass *nc = NMI_CLASS(oc); 2171c20d332aSBharata B Rao HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); 217229ee3247SAlexey Kardashevskiy 2173958db90cSMarcel Apfelbaum mc->init = ppc_spapr_init; 2174958db90cSMarcel Apfelbaum mc->reset = ppc_spapr_reset; 2175958db90cSMarcel Apfelbaum mc->block_default_type = IF_SCSI; 217638b02bd8SAlexey Kardashevskiy mc->max_cpus = MAX_CPUMASK_BITS; 2177958db90cSMarcel Apfelbaum mc->no_parallel = 1; 21785b2128d2SAlexander Graf mc->default_boot_order = ""; 2179a34944feSNikunj A Dadhania mc->default_ram_size = 512 * M_BYTE; 2180958db90cSMarcel Apfelbaum mc->kvm_type = spapr_kvm_type; 21819e3f9733SAlexander Graf mc->has_dynamic_sysbus = true; 2182e4024630SLaurent Vivier mc->pci_allow_0_address = true; 2183c20d332aSBharata B Rao mc->get_hotplug_handler = spapr_get_hotpug_handler; 2184c20d332aSBharata B Rao hc->plug = spapr_machine_device_plug; 2185c20d332aSBharata B Rao hc->unplug = spapr_machine_device_unplug; 218600b4fbe2SMarcel Apfelbaum 2187224245bfSDavid Gibson smc->dr_lmb_enabled = false; 218871461b0fSAlexey Kardashevskiy fwc->get_dev_path = spapr_get_fw_dev_path; 218934316482SAlexey Kardashevskiy nc->nmi_monitor_handler = spapr_nmi; 219053018216SPaolo Bonzini } 219153018216SPaolo Bonzini 219229ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = { 219329ee3247SAlexey Kardashevskiy .name = TYPE_SPAPR_MACHINE, 219429ee3247SAlexey Kardashevskiy .parent = TYPE_MACHINE, 21954aee7362SDavid Gibson .abstract = true, 21966ca1502eSAlexey Kardashevskiy .instance_size = sizeof(sPAPRMachineState), 219723825581SEduardo Habkost .instance_init = spapr_machine_initfn, 2198183930c0SDavid Gibson .class_size = sizeof(sPAPRMachineClass), 219929ee3247SAlexey Kardashevskiy .class_init = spapr_machine_class_init, 220071461b0fSAlexey Kardashevskiy .interfaces = (InterfaceInfo[]) { 220171461b0fSAlexey Kardashevskiy { TYPE_FW_PATH_PROVIDER }, 220234316482SAlexey Kardashevskiy { TYPE_NMI }, 2203c20d332aSBharata B Rao { TYPE_HOTPLUG_HANDLER }, 220471461b0fSAlexey Kardashevskiy { } 220571461b0fSAlexey Kardashevskiy }, 220629ee3247SAlexey Kardashevskiy }; 220729ee3247SAlexey Kardashevskiy 220838ff32c6SEduardo Habkost #define SPAPR_COMPAT_2_3 \ 22097619c7b0SMichael Roth HW_COMPAT_2_3 \ 22107619c7b0SMichael Roth {\ 22117619c7b0SMichael Roth .driver = "spapr-pci-host-bridge",\ 22127619c7b0SMichael Roth .property = "dynamic-reconfiguration",\ 22137619c7b0SMichael Roth .value = "off",\ 22147619c7b0SMichael Roth }, 221538ff32c6SEduardo Habkost 2216b194df47SAlexey Kardashevskiy #define SPAPR_COMPAT_2_2 \ 221738ff32c6SEduardo Habkost SPAPR_COMPAT_2_3 \ 22184dfd8eaaSEduardo Habkost HW_COMPAT_2_2 \ 2219b194df47SAlexey Kardashevskiy {\ 2220b194df47SAlexey Kardashevskiy .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\ 2221b194df47SAlexey Kardashevskiy .property = "mem_win_size",\ 2222b194df47SAlexey Kardashevskiy .value = "0x20000000",\ 2223dd754bafSEduardo Habkost }, 2224b194df47SAlexey Kardashevskiy 2225b194df47SAlexey Kardashevskiy #define SPAPR_COMPAT_2_1 \ 22264dfd8eaaSEduardo Habkost SPAPR_COMPAT_2_2 \ 22274dfd8eaaSEduardo Habkost HW_COMPAT_2_1 2228b194df47SAlexey Kardashevskiy 2229d25228e7SJason Wang static void spapr_compat_2_3(Object *obj) 2230d25228e7SJason Wang { 2231ff14e817SDr. David Alan Gilbert savevm_skip_section_footers(); 223213d16814SJuan Quintela global_state_set_optional(); 2233d25228e7SJason Wang } 2234d25228e7SJason Wang 2235b0e966d0SJason Wang static void spapr_compat_2_2(Object *obj) 2236b0e966d0SJason Wang { 2237d25228e7SJason Wang spapr_compat_2_3(obj); 2238b0e966d0SJason Wang } 2239b0e966d0SJason Wang 2240b0e966d0SJason Wang static void spapr_compat_2_1(Object *obj) 2241b0e966d0SJason Wang { 2242b0e966d0SJason Wang spapr_compat_2_2(obj); 2243b0e966d0SJason Wang } 2244b0e966d0SJason Wang 2245d25228e7SJason Wang static void spapr_machine_2_3_instance_init(Object *obj) 2246d25228e7SJason Wang { 2247d25228e7SJason Wang spapr_compat_2_3(obj); 2248d25228e7SJason Wang spapr_machine_initfn(obj); 2249d25228e7SJason Wang } 2250d25228e7SJason Wang 2251b0e966d0SJason Wang static void spapr_machine_2_2_instance_init(Object *obj) 2252b0e966d0SJason Wang { 2253b0e966d0SJason Wang spapr_compat_2_2(obj); 2254b0e966d0SJason Wang spapr_machine_initfn(obj); 2255b0e966d0SJason Wang } 2256b0e966d0SJason Wang 2257b0e966d0SJason Wang static void spapr_machine_2_1_instance_init(Object *obj) 2258b0e966d0SJason Wang { 2259b0e966d0SJason Wang spapr_compat_2_1(obj); 2260b0e966d0SJason Wang spapr_machine_initfn(obj); 2261b0e966d0SJason Wang } 2262b0e966d0SJason Wang 22636026db45SAlexey Kardashevskiy static void spapr_machine_2_1_class_init(ObjectClass *oc, void *data) 22646026db45SAlexey Kardashevskiy { 22656026db45SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 226668a27b20SMichael S. Tsirkin static GlobalProperty compat_props[] = { 2267dd754bafSEduardo Habkost SPAPR_COMPAT_2_1 226868a27b20SMichael S. Tsirkin { /* end of list */ } 226968a27b20SMichael S. Tsirkin }; 22706026db45SAlexey Kardashevskiy 22716026db45SAlexey Kardashevskiy mc->desc = "pSeries Logical Partition (PAPR compliant) v2.1"; 227268a27b20SMichael S. Tsirkin mc->compat_props = compat_props; 22736026db45SAlexey Kardashevskiy } 22746026db45SAlexey Kardashevskiy 22756026db45SAlexey Kardashevskiy static const TypeInfo spapr_machine_2_1_info = { 2276b9f072d0SEduardo Habkost .name = MACHINE_TYPE_NAME("pseries-2.1"), 22776026db45SAlexey Kardashevskiy .parent = TYPE_SPAPR_MACHINE, 22786026db45SAlexey Kardashevskiy .class_init = spapr_machine_2_1_class_init, 2279b0e966d0SJason Wang .instance_init = spapr_machine_2_1_instance_init, 22806026db45SAlexey Kardashevskiy }; 22816026db45SAlexey Kardashevskiy 22824aee7362SDavid Gibson static void spapr_machine_2_2_class_init(ObjectClass *oc, void *data) 22834aee7362SDavid Gibson { 2284b194df47SAlexey Kardashevskiy static GlobalProperty compat_props[] = { 2285dd754bafSEduardo Habkost SPAPR_COMPAT_2_2 2286b194df47SAlexey Kardashevskiy { /* end of list */ } 2287b194df47SAlexey Kardashevskiy }; 22884aee7362SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); 22894aee7362SDavid Gibson 22904aee7362SDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant) v2.2"; 2291b194df47SAlexey Kardashevskiy mc->compat_props = compat_props; 22924aee7362SDavid Gibson } 22934aee7362SDavid Gibson 22944aee7362SDavid Gibson static const TypeInfo spapr_machine_2_2_info = { 2295b9f072d0SEduardo Habkost .name = MACHINE_TYPE_NAME("pseries-2.2"), 22964aee7362SDavid Gibson .parent = TYPE_SPAPR_MACHINE, 22974aee7362SDavid Gibson .class_init = spapr_machine_2_2_class_init, 2298b0e966d0SJason Wang .instance_init = spapr_machine_2_2_instance_init, 22994aee7362SDavid Gibson }; 23004aee7362SDavid Gibson 23013dab0244SAlexey Kardashevskiy static void spapr_machine_2_3_class_init(ObjectClass *oc, void *data) 23023dab0244SAlexey Kardashevskiy { 2303a1a45612SDavid Gibson static GlobalProperty compat_props[] = { 23047619c7b0SMichael Roth SPAPR_COMPAT_2_3 2305a1a45612SDavid Gibson { /* end of list */ } 2306a1a45612SDavid Gibson }; 23073dab0244SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 23083dab0244SAlexey Kardashevskiy 23093dab0244SAlexey Kardashevskiy mc->desc = "pSeries Logical Partition (PAPR compliant) v2.3"; 2310a1a45612SDavid Gibson mc->compat_props = compat_props; 23113dab0244SAlexey Kardashevskiy } 23123dab0244SAlexey Kardashevskiy 23133dab0244SAlexey Kardashevskiy static const TypeInfo spapr_machine_2_3_info = { 2314b9f072d0SEduardo Habkost .name = MACHINE_TYPE_NAME("pseries-2.3"), 23153dab0244SAlexey Kardashevskiy .parent = TYPE_SPAPR_MACHINE, 23163dab0244SAlexey Kardashevskiy .class_init = spapr_machine_2_3_class_init, 2317d25228e7SJason Wang .instance_init = spapr_machine_2_3_instance_init, 2318d25228e7SJason Wang }; 2319d25228e7SJason Wang 2320d25228e7SJason Wang static void spapr_machine_2_4_class_init(ObjectClass *oc, void *data) 2321d25228e7SJason Wang { 2322d25228e7SJason Wang MachineClass *mc = MACHINE_CLASS(oc); 2323d25228e7SJason Wang 2324d25228e7SJason Wang mc->desc = "pSeries Logical Partition (PAPR compliant) v2.4"; 2325d25228e7SJason Wang mc->alias = "pseries"; 2326fb0fc8f6SDavid Gibson mc->is_default = 0; 2327d25228e7SJason Wang } 2328d25228e7SJason Wang 2329d25228e7SJason Wang static const TypeInfo spapr_machine_2_4_info = { 2330b9f072d0SEduardo Habkost .name = MACHINE_TYPE_NAME("pseries-2.4"), 2331d25228e7SJason Wang .parent = TYPE_SPAPR_MACHINE, 2332d25228e7SJason Wang .class_init = spapr_machine_2_4_class_init, 23333dab0244SAlexey Kardashevskiy }; 23343dab0244SAlexey Kardashevskiy 2335fb0fc8f6SDavid Gibson static void spapr_machine_2_5_class_init(ObjectClass *oc, void *data) 2336fb0fc8f6SDavid Gibson { 2337fb0fc8f6SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); 2338224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc); 2339fb0fc8f6SDavid Gibson 2340fb0fc8f6SDavid Gibson mc->name = "pseries-2.5"; 2341fb0fc8f6SDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant) v2.5"; 2342fb0fc8f6SDavid Gibson mc->alias = "pseries"; 2343fb0fc8f6SDavid Gibson mc->is_default = 1; 2344224245bfSDavid Gibson smc->dr_lmb_enabled = true; 2345fb0fc8f6SDavid Gibson } 2346fb0fc8f6SDavid Gibson 2347fb0fc8f6SDavid Gibson static const TypeInfo spapr_machine_2_5_info = { 2348fb0fc8f6SDavid Gibson .name = MACHINE_TYPE_NAME("pseries-2.5"), 2349fb0fc8f6SDavid Gibson .parent = TYPE_SPAPR_MACHINE, 2350fb0fc8f6SDavid Gibson .class_init = spapr_machine_2_5_class_init, 2351fb0fc8f6SDavid Gibson }; 2352fb0fc8f6SDavid Gibson 235329ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void) 235429ee3247SAlexey Kardashevskiy { 235529ee3247SAlexey Kardashevskiy type_register_static(&spapr_machine_info); 23566026db45SAlexey Kardashevskiy type_register_static(&spapr_machine_2_1_info); 23574aee7362SDavid Gibson type_register_static(&spapr_machine_2_2_info); 23583dab0244SAlexey Kardashevskiy type_register_static(&spapr_machine_2_3_info); 2359d25228e7SJason Wang type_register_static(&spapr_machine_2_4_info); 2360fb0fc8f6SDavid Gibson type_register_static(&spapr_machine_2_5_info); 236129ee3247SAlexey Kardashevskiy } 236229ee3247SAlexey Kardashevskiy 236329ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types) 2364