153018216SPaolo Bonzini /* 253018216SPaolo Bonzini * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator 353018216SPaolo Bonzini * 453018216SPaolo Bonzini * Copyright (c) 2004-2007 Fabrice Bellard 553018216SPaolo Bonzini * Copyright (c) 2007 Jocelyn Mayer 653018216SPaolo Bonzini * Copyright (c) 2010 David Gibson, IBM Corporation. 753018216SPaolo Bonzini * 853018216SPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy 953018216SPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal 1053018216SPaolo Bonzini * in the Software without restriction, including without limitation the rights 1153018216SPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1253018216SPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is 1353018216SPaolo Bonzini * furnished to do so, subject to the following conditions: 1453018216SPaolo Bonzini * 1553018216SPaolo Bonzini * The above copyright notice and this permission notice shall be included in 1653018216SPaolo Bonzini * all copies or substantial portions of the Software. 1753018216SPaolo Bonzini * 1853018216SPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1953018216SPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2053018216SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2153018216SPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2253018216SPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2353018216SPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 2453018216SPaolo Bonzini * THE SOFTWARE. 2553018216SPaolo Bonzini * 2653018216SPaolo Bonzini */ 270d75590dSPeter Maydell #include "qemu/osdep.h" 28da34e65cSMarkus Armbruster #include "qapi/error.h" 29fa98fbfcSSam Bobroff #include "qapi/visitor.h" 3053018216SPaolo Bonzini #include "sysemu/sysemu.h" 31e35704baSEduardo Habkost #include "sysemu/numa.h" 3223ff81bdSGreg Kurz #include "sysemu/qtest.h" 3353018216SPaolo Bonzini #include "hw/hw.h" 3403dd024fSPaolo Bonzini #include "qemu/log.h" 3571461b0fSAlexey Kardashevskiy #include "hw/fw-path-provider.h" 3653018216SPaolo Bonzini #include "elf.h" 3753018216SPaolo Bonzini #include "net/net.h" 38ad440b4aSAndrew Jones #include "sysemu/device_tree.h" 3953018216SPaolo Bonzini #include "sysemu/cpus.h" 40b3946626SVincent Palatin #include "sysemu/hw_accel.h" 4153018216SPaolo Bonzini #include "kvm_ppc.h" 42c4b63b7cSJuan Quintela #include "migration/misc.h" 4384a899deSJuan Quintela #include "migration/global_state.h" 44f2a8f0a6SJuan Quintela #include "migration/register.h" 454be21d56SDavid Gibson #include "mmu-hash64.h" 46b4db5413SSuraj Jitindar Singh #include "mmu-book3s-v3.h" 477abd43baSSuraj Jitindar Singh #include "cpu-models.h" 483794d548SAlexey Kardashevskiy #include "qom/cpu.h" 4953018216SPaolo Bonzini 5053018216SPaolo Bonzini #include "hw/boards.h" 510d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h" 5253018216SPaolo Bonzini #include "hw/loader.h" 5353018216SPaolo Bonzini 547804c353SCédric Le Goater #include "hw/ppc/fdt.h" 550d09e41aSPaolo Bonzini #include "hw/ppc/spapr.h" 560d09e41aSPaolo Bonzini #include "hw/ppc/spapr_vio.h" 570d09e41aSPaolo Bonzini #include "hw/pci-host/spapr.h" 5853018216SPaolo Bonzini #include "hw/pci/msi.h" 5953018216SPaolo Bonzini 6053018216SPaolo Bonzini #include "hw/pci/pci.h" 6171461b0fSAlexey Kardashevskiy #include "hw/scsi/scsi.h" 6271461b0fSAlexey Kardashevskiy #include "hw/virtio/virtio-scsi.h" 63c4e13492SFelipe Franciosi #include "hw/virtio/vhost-scsi-common.h" 6453018216SPaolo Bonzini 6553018216SPaolo Bonzini #include "exec/address-spaces.h" 662309832aSDavid Gibson #include "exec/ram_addr.h" 6753018216SPaolo Bonzini #include "hw/usb.h" 6853018216SPaolo Bonzini #include "qemu/config-file.h" 69135a129aSAneesh Kumar K.V #include "qemu/error-report.h" 702a6593cbSAlexey Kardashevskiy #include "trace.h" 7134316482SAlexey Kardashevskiy #include "hw/nmi.h" 726449da45SCédric Le Goater #include "hw/intc/intc.h" 7353018216SPaolo Bonzini 74f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 7594a94e4cSBharata B Rao #include "hw/ppc/spapr_cpu_core.h" 762cc0e2e8SDavid Hildenbrand #include "hw/mem/memory-device.h" 7768a27b20SMichael S. Tsirkin 7853018216SPaolo Bonzini #include <libfdt.h> 7953018216SPaolo Bonzini 8053018216SPaolo Bonzini /* SLOF memory layout: 8153018216SPaolo Bonzini * 8253018216SPaolo Bonzini * SLOF raw image loaded at 0, copies its romfs right below the flat 8353018216SPaolo Bonzini * device-tree, then position SLOF itself 31M below that 8453018216SPaolo Bonzini * 8553018216SPaolo Bonzini * So we set FW_OVERHEAD to 40MB which should account for all of that 8653018216SPaolo Bonzini * and more 8753018216SPaolo Bonzini * 8853018216SPaolo Bonzini * We load our kernel at 4M, leaving space for SLOF initial image 8953018216SPaolo Bonzini */ 9038b02bd8SAlexey Kardashevskiy #define FDT_MAX_SIZE 0x100000 9153018216SPaolo Bonzini #define RTAS_MAX_SIZE 0x10000 92b7d1f77aSBenjamin Herrenschmidt #define RTAS_MAX_ADDR 0x80000000 /* RTAS must stay below that */ 9353018216SPaolo Bonzini #define FW_MAX_SIZE 0x400000 9453018216SPaolo Bonzini #define FW_FILE_NAME "slof.bin" 9553018216SPaolo Bonzini #define FW_OVERHEAD 0x2800000 9653018216SPaolo Bonzini #define KERNEL_LOAD_ADDR FW_MAX_SIZE 9753018216SPaolo Bonzini 9853018216SPaolo Bonzini #define MIN_RMA_SLOF 128UL 9953018216SPaolo Bonzini 1005c7adcf4SGreg Kurz #define PHANDLE_INTC 0x00001111 10153018216SPaolo Bonzini 1025d0fb150SGreg Kurz /* These two functions implement the VCPU id numbering: one to compute them 1035d0fb150SGreg Kurz * all and one to identify thread 0 of a VCORE. Any change to the first one 1045d0fb150SGreg Kurz * is likely to have an impact on the second one, so let's keep them close. 1055d0fb150SGreg Kurz */ 1065d0fb150SGreg Kurz static int spapr_vcpu_id(sPAPRMachineState *spapr, int cpu_index) 1075d0fb150SGreg Kurz { 1081a5008fcSGreg Kurz assert(spapr->vsmt); 1095d0fb150SGreg Kurz return 1105d0fb150SGreg Kurz (cpu_index / smp_threads) * spapr->vsmt + cpu_index % smp_threads; 1115d0fb150SGreg Kurz } 1125d0fb150SGreg Kurz static bool spapr_is_thread0_in_vcore(sPAPRMachineState *spapr, 1135d0fb150SGreg Kurz PowerPCCPU *cpu) 1145d0fb150SGreg Kurz { 1151a5008fcSGreg Kurz assert(spapr->vsmt); 1165d0fb150SGreg Kurz return spapr_get_vcpu_id(cpu) % spapr->vsmt == 0; 1175d0fb150SGreg Kurz } 1185d0fb150SGreg Kurz 11946f7afa3SGreg Kurz static bool pre_2_10_vmstate_dummy_icp_needed(void *opaque) 12046f7afa3SGreg Kurz { 12146f7afa3SGreg Kurz /* Dummy entries correspond to unused ICPState objects in older QEMUs, 12246f7afa3SGreg Kurz * and newer QEMUs don't even have them. In both cases, we don't want 12346f7afa3SGreg Kurz * to send anything on the wire. 12446f7afa3SGreg Kurz */ 12546f7afa3SGreg Kurz return false; 12646f7afa3SGreg Kurz } 12746f7afa3SGreg Kurz 12846f7afa3SGreg Kurz static const VMStateDescription pre_2_10_vmstate_dummy_icp = { 12946f7afa3SGreg Kurz .name = "icp/server", 13046f7afa3SGreg Kurz .version_id = 1, 13146f7afa3SGreg Kurz .minimum_version_id = 1, 13246f7afa3SGreg Kurz .needed = pre_2_10_vmstate_dummy_icp_needed, 13346f7afa3SGreg Kurz .fields = (VMStateField[]) { 13446f7afa3SGreg Kurz VMSTATE_UNUSED(4), /* uint32_t xirr */ 13546f7afa3SGreg Kurz VMSTATE_UNUSED(1), /* uint8_t pending_priority */ 13646f7afa3SGreg Kurz VMSTATE_UNUSED(1), /* uint8_t mfrr */ 13746f7afa3SGreg Kurz VMSTATE_END_OF_LIST() 13846f7afa3SGreg Kurz }, 13946f7afa3SGreg Kurz }; 14046f7afa3SGreg Kurz 14146f7afa3SGreg Kurz static void pre_2_10_vmstate_register_dummy_icp(int i) 14246f7afa3SGreg Kurz { 14346f7afa3SGreg Kurz vmstate_register(NULL, i, &pre_2_10_vmstate_dummy_icp, 14446f7afa3SGreg Kurz (void *)(uintptr_t) i); 14546f7afa3SGreg Kurz } 14646f7afa3SGreg Kurz 14746f7afa3SGreg Kurz static void pre_2_10_vmstate_unregister_dummy_icp(int i) 14846f7afa3SGreg Kurz { 14946f7afa3SGreg Kurz vmstate_unregister(NULL, &pre_2_10_vmstate_dummy_icp, 15046f7afa3SGreg Kurz (void *)(uintptr_t) i); 15146f7afa3SGreg Kurz } 15246f7afa3SGreg Kurz 1531a518e76SCédric Le Goater int spapr_max_server_number(sPAPRMachineState *spapr) 15446f7afa3SGreg Kurz { 1551a5008fcSGreg Kurz assert(spapr->vsmt); 15672194664SGreg Kurz return DIV_ROUND_UP(max_cpus * spapr->vsmt, smp_threads); 15746f7afa3SGreg Kurz } 15846f7afa3SGreg Kurz 159833d4668SAlexey Kardashevskiy static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, 160833d4668SAlexey Kardashevskiy int smt_threads) 161833d4668SAlexey Kardashevskiy { 162833d4668SAlexey Kardashevskiy int i, ret = 0; 163833d4668SAlexey Kardashevskiy uint32_t servers_prop[smt_threads]; 164833d4668SAlexey Kardashevskiy uint32_t gservers_prop[smt_threads * 2]; 16514bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 166833d4668SAlexey Kardashevskiy 167d6e166c0SDavid Gibson if (cpu->compat_pvr) { 168d6e166c0SDavid Gibson ret = fdt_setprop_cell(fdt, offset, "cpu-version", cpu->compat_pvr); 1696d9412eaSAlexey Kardashevskiy if (ret < 0) { 1706d9412eaSAlexey Kardashevskiy return ret; 1716d9412eaSAlexey Kardashevskiy } 1726d9412eaSAlexey Kardashevskiy } 1736d9412eaSAlexey Kardashevskiy 174833d4668SAlexey Kardashevskiy /* Build interrupt servers and gservers properties */ 175833d4668SAlexey Kardashevskiy for (i = 0; i < smt_threads; i++) { 176833d4668SAlexey Kardashevskiy servers_prop[i] = cpu_to_be32(index + i); 177833d4668SAlexey Kardashevskiy /* Hack, direct the group queues back to cpu 0 */ 178833d4668SAlexey Kardashevskiy gservers_prop[i*2] = cpu_to_be32(index + i); 179833d4668SAlexey Kardashevskiy gservers_prop[i*2 + 1] = 0; 180833d4668SAlexey Kardashevskiy } 181833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 182833d4668SAlexey Kardashevskiy servers_prop, sizeof(servers_prop)); 183833d4668SAlexey Kardashevskiy if (ret < 0) { 184833d4668SAlexey Kardashevskiy return ret; 185833d4668SAlexey Kardashevskiy } 186833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-gserver#s", 187833d4668SAlexey Kardashevskiy gservers_prop, sizeof(gservers_prop)); 188833d4668SAlexey Kardashevskiy 189833d4668SAlexey Kardashevskiy return ret; 190833d4668SAlexey Kardashevskiy } 191833d4668SAlexey Kardashevskiy 19299861ecbSIgor Mammedov static int spapr_fixup_cpu_numa_dt(void *fdt, int offset, PowerPCCPU *cpu) 1930da6f3feSBharata B Rao { 19414bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 1950da6f3feSBharata B Rao uint32_t associativity[] = {cpu_to_be32(0x5), 1960da6f3feSBharata B Rao cpu_to_be32(0x0), 1970da6f3feSBharata B Rao cpu_to_be32(0x0), 1980da6f3feSBharata B Rao cpu_to_be32(0x0), 19915f8b142SIgor Mammedov cpu_to_be32(cpu->node_id), 2000da6f3feSBharata B Rao cpu_to_be32(index)}; 2010da6f3feSBharata B Rao 2020da6f3feSBharata B Rao /* Advertise NUMA via ibm,associativity */ 20399861ecbSIgor Mammedov return fdt_setprop(fdt, offset, "ibm,associativity", associativity, 2040da6f3feSBharata B Rao sizeof(associativity)); 2050da6f3feSBharata B Rao } 2060da6f3feSBharata B Rao 20786d5771aSSam Bobroff /* Populate the "ibm,pa-features" property */ 208ee76a09fSDavid Gibson static void spapr_populate_pa_features(sPAPRMachineState *spapr, 209ee76a09fSDavid Gibson PowerPCCPU *cpu, 210ee76a09fSDavid Gibson void *fdt, int offset, 211e957f6a9SSam Bobroff bool legacy_guest) 21286d5771aSSam Bobroff { 21386d5771aSSam Bobroff uint8_t pa_features_206[] = { 6, 0, 21486d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 }; 21586d5771aSSam Bobroff uint8_t pa_features_207[] = { 24, 0, 21686d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, 21786d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 21886d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 21986d5771aSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 }; 2209fb4541fSSam Bobroff uint8_t pa_features_300[] = { 66, 0, 2219fb4541fSSam Bobroff /* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */ 2229fb4541fSSam Bobroff /* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, SSO, 5: LE|CFAR|EB|LSQ */ 22386d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, /* 0 - 5 */ 2249fb4541fSSam Bobroff /* 6: DS207 */ 22586d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */ 2269fb4541fSSam Bobroff /* 16: Vector */ 22786d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */ 2289fb4541fSSam Bobroff /* 18: Vec. Scalar, 20: Vec. XOR, 22: HTM */ 2299bf502feSDavid Gibson 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */ 2309fb4541fSSam Bobroff /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */ 2319fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */ 2329fb4541fSSam Bobroff /* 30: MMR, 32: LE atomic, 34: EBB + ext EBB */ 2339fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */ 2349fb4541fSSam Bobroff /* 36: SPR SO, 38: Copy/Paste, 40: Radix MMU */ 2359fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 36 - 41 */ 2369fb4541fSSam Bobroff /* 42: PM, 44: PC RA, 46: SC vec'd */ 2379fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */ 2389fb4541fSSam Bobroff /* 48: SIMD, 50: QP BFP, 52: String */ 2399fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */ 2409fb4541fSSam Bobroff /* 54: DecFP, 56: DecI, 58: SHA */ 2419fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */ 2429fb4541fSSam Bobroff /* 60: NM atomic, 62: RNG */ 2439fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */ 2449fb4541fSSam Bobroff }; 2457abd43baSSuraj Jitindar Singh uint8_t *pa_features = NULL; 24686d5771aSSam Bobroff size_t pa_size; 24786d5771aSSam Bobroff 2487abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06, 0, cpu->compat_pvr)) { 24986d5771aSSam Bobroff pa_features = pa_features_206; 25086d5771aSSam Bobroff pa_size = sizeof(pa_features_206); 2517abd43baSSuraj Jitindar Singh } 2527abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07, 0, cpu->compat_pvr)) { 25386d5771aSSam Bobroff pa_features = pa_features_207; 25486d5771aSSam Bobroff pa_size = sizeof(pa_features_207); 2557abd43baSSuraj Jitindar Singh } 2567abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0, cpu->compat_pvr)) { 25786d5771aSSam Bobroff pa_features = pa_features_300; 25886d5771aSSam Bobroff pa_size = sizeof(pa_features_300); 2597abd43baSSuraj Jitindar Singh } 2607abd43baSSuraj Jitindar Singh if (!pa_features) { 26186d5771aSSam Bobroff return; 26286d5771aSSam Bobroff } 26386d5771aSSam Bobroff 26426cd35b8SDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_CI_LARGEPAGE)) { 26586d5771aSSam Bobroff /* 26686d5771aSSam Bobroff * Note: we keep CI large pages off by default because a 64K capable 26786d5771aSSam Bobroff * guest provisioned with large pages might otherwise try to map a qemu 26886d5771aSSam Bobroff * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages 26986d5771aSSam Bobroff * even if that qemu runs on a 4k host. 27086d5771aSSam Bobroff * We dd this bit back here if we are confident this is not an issue 27186d5771aSSam Bobroff */ 27286d5771aSSam Bobroff pa_features[3] |= 0x20; 27386d5771aSSam Bobroff } 2744e5fe368SSuraj Jitindar Singh if ((spapr_get_cap(spapr, SPAPR_CAP_HTM) != 0) && pa_size > 24) { 27586d5771aSSam Bobroff pa_features[24] |= 0x80; /* Transactional memory support */ 27686d5771aSSam Bobroff } 277e957f6a9SSam Bobroff if (legacy_guest && pa_size > 40) { 278e957f6a9SSam Bobroff /* Workaround for broken kernels that attempt (guest) radix 279e957f6a9SSam Bobroff * mode when they can't handle it, if they see the radix bit set 280e957f6a9SSam Bobroff * in pa-features. So hide it from them. */ 281e957f6a9SSam Bobroff pa_features[40 + 2] &= ~0x80; /* Radix MMU */ 282e957f6a9SSam Bobroff } 28386d5771aSSam Bobroff 28486d5771aSSam Bobroff _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size))); 28586d5771aSSam Bobroff } 28686d5771aSSam Bobroff 28728e02042SDavid Gibson static int spapr_fixup_cpu_dt(void *fdt, sPAPRMachineState *spapr) 28853018216SPaolo Bonzini { 28982677ed2SAlexey Kardashevskiy int ret = 0, offset, cpus_offset; 29082677ed2SAlexey Kardashevskiy CPUState *cs; 29153018216SPaolo Bonzini char cpu_model[32]; 29253018216SPaolo Bonzini uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 29353018216SPaolo Bonzini 29482677ed2SAlexey Kardashevskiy CPU_FOREACH(cs) { 29582677ed2SAlexey Kardashevskiy PowerPCCPU *cpu = POWERPC_CPU(cs); 29682677ed2SAlexey Kardashevskiy DeviceClass *dc = DEVICE_GET_CLASS(cs); 29714bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 298abbc1247SDavid Gibson int compat_smt = MIN(smp_threads, ppc_compat_max_vthreads(cpu)); 29953018216SPaolo Bonzini 3005d0fb150SGreg Kurz if (!spapr_is_thread0_in_vcore(spapr, cpu)) { 30153018216SPaolo Bonzini continue; 30253018216SPaolo Bonzini } 30353018216SPaolo Bonzini 30482677ed2SAlexey Kardashevskiy snprintf(cpu_model, 32, "%s@%x", dc->fw_name, index); 30553018216SPaolo Bonzini 30682677ed2SAlexey Kardashevskiy cpus_offset = fdt_path_offset(fdt, "/cpus"); 30782677ed2SAlexey Kardashevskiy if (cpus_offset < 0) { 308a4f3885cSGreg Kurz cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 30982677ed2SAlexey Kardashevskiy if (cpus_offset < 0) { 31082677ed2SAlexey Kardashevskiy return cpus_offset; 31182677ed2SAlexey Kardashevskiy } 31282677ed2SAlexey Kardashevskiy } 31382677ed2SAlexey Kardashevskiy offset = fdt_subnode_offset(fdt, cpus_offset, cpu_model); 31482677ed2SAlexey Kardashevskiy if (offset < 0) { 31582677ed2SAlexey Kardashevskiy offset = fdt_add_subnode(fdt, cpus_offset, cpu_model); 31653018216SPaolo Bonzini if (offset < 0) { 31753018216SPaolo Bonzini return offset; 31853018216SPaolo Bonzini } 31982677ed2SAlexey Kardashevskiy } 32053018216SPaolo Bonzini 3210da6f3feSBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,pft-size", 3220da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)); 32353018216SPaolo Bonzini if (ret < 0) { 32453018216SPaolo Bonzini return ret; 32553018216SPaolo Bonzini } 32653018216SPaolo Bonzini 32799861ecbSIgor Mammedov if (nb_numa_nodes > 1) { 32899861ecbSIgor Mammedov ret = spapr_fixup_cpu_numa_dt(fdt, offset, cpu); 32953018216SPaolo Bonzini if (ret < 0) { 33053018216SPaolo Bonzini return ret; 33153018216SPaolo Bonzini } 33299861ecbSIgor Mammedov } 333833d4668SAlexey Kardashevskiy 33412dbeb16SDavid Gibson ret = spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt); 335833d4668SAlexey Kardashevskiy if (ret < 0) { 336833d4668SAlexey Kardashevskiy return ret; 337833d4668SAlexey Kardashevskiy } 338e957f6a9SSam Bobroff 339ee76a09fSDavid Gibson spapr_populate_pa_features(spapr, cpu, fdt, offset, 340e957f6a9SSam Bobroff spapr->cas_legacy_guest_workaround); 34153018216SPaolo Bonzini } 34253018216SPaolo Bonzini return ret; 34353018216SPaolo Bonzini } 34453018216SPaolo Bonzini 345c86c1affSDaniel Henrique Barboza static hwaddr spapr_node0_size(MachineState *machine) 346b082d65aSAlexey Kardashevskiy { 347b082d65aSAlexey Kardashevskiy if (nb_numa_nodes) { 348b082d65aSAlexey Kardashevskiy int i; 349b082d65aSAlexey Kardashevskiy for (i = 0; i < nb_numa_nodes; ++i) { 350b082d65aSAlexey Kardashevskiy if (numa_info[i].node_mem) { 351fb164994SDavid Gibson return MIN(pow2floor(numa_info[i].node_mem), 352fb164994SDavid Gibson machine->ram_size); 353b082d65aSAlexey Kardashevskiy } 354b082d65aSAlexey Kardashevskiy } 355b082d65aSAlexey Kardashevskiy } 356fb164994SDavid Gibson return machine->ram_size; 357b082d65aSAlexey Kardashevskiy } 358b082d65aSAlexey Kardashevskiy 359a1d59c0fSAlexey Kardashevskiy static void add_str(GString *s, const gchar *s1) 360a1d59c0fSAlexey Kardashevskiy { 361a1d59c0fSAlexey Kardashevskiy g_string_append_len(s, s1, strlen(s1) + 1); 362a1d59c0fSAlexey Kardashevskiy } 36353018216SPaolo Bonzini 36403d196b7SBharata B Rao static int spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start, 36526a8c353SAlexey Kardashevskiy hwaddr size) 36626a8c353SAlexey Kardashevskiy { 36726a8c353SAlexey Kardashevskiy uint32_t associativity[] = { 36826a8c353SAlexey Kardashevskiy cpu_to_be32(0x4), /* length */ 36926a8c353SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(0x0), 370c3b4f589SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(nodeid) 37126a8c353SAlexey Kardashevskiy }; 37226a8c353SAlexey Kardashevskiy char mem_name[32]; 37326a8c353SAlexey Kardashevskiy uint64_t mem_reg_property[2]; 37426a8c353SAlexey Kardashevskiy int off; 37526a8c353SAlexey Kardashevskiy 37626a8c353SAlexey Kardashevskiy mem_reg_property[0] = cpu_to_be64(start); 37726a8c353SAlexey Kardashevskiy mem_reg_property[1] = cpu_to_be64(size); 37826a8c353SAlexey Kardashevskiy 37926a8c353SAlexey Kardashevskiy sprintf(mem_name, "memory@" TARGET_FMT_lx, start); 38026a8c353SAlexey Kardashevskiy off = fdt_add_subnode(fdt, 0, mem_name); 38126a8c353SAlexey Kardashevskiy _FDT(off); 38226a8c353SAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 38326a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 38426a8c353SAlexey Kardashevskiy sizeof(mem_reg_property)))); 38526a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity, 38626a8c353SAlexey Kardashevskiy sizeof(associativity)))); 38703d196b7SBharata B Rao return off; 38826a8c353SAlexey Kardashevskiy } 38926a8c353SAlexey Kardashevskiy 39028e02042SDavid Gibson static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt) 39153018216SPaolo Bonzini { 392fb164994SDavid Gibson MachineState *machine = MACHINE(spapr); 3937db8a127SAlexey Kardashevskiy hwaddr mem_start, node_size; 3947db8a127SAlexey Kardashevskiy int i, nb_nodes = nb_numa_nodes; 3957db8a127SAlexey Kardashevskiy NodeInfo *nodes = numa_info; 3967db8a127SAlexey Kardashevskiy NodeInfo ramnode; 39753018216SPaolo Bonzini 3987db8a127SAlexey Kardashevskiy /* No NUMA nodes, assume there is just one node with whole RAM */ 3997db8a127SAlexey Kardashevskiy if (!nb_numa_nodes) { 4007db8a127SAlexey Kardashevskiy nb_nodes = 1; 401fb164994SDavid Gibson ramnode.node_mem = machine->ram_size; 4027db8a127SAlexey Kardashevskiy nodes = &ramnode; 4035fe269b1SPaul Mackerras } 40453018216SPaolo Bonzini 4057db8a127SAlexey Kardashevskiy for (i = 0, mem_start = 0; i < nb_nodes; ++i) { 4067db8a127SAlexey Kardashevskiy if (!nodes[i].node_mem) { 4077db8a127SAlexey Kardashevskiy continue; 40853018216SPaolo Bonzini } 409fb164994SDavid Gibson if (mem_start >= machine->ram_size) { 4105fe269b1SPaul Mackerras node_size = 0; 4115fe269b1SPaul Mackerras } else { 4127db8a127SAlexey Kardashevskiy node_size = nodes[i].node_mem; 413fb164994SDavid Gibson if (node_size > machine->ram_size - mem_start) { 414fb164994SDavid Gibson node_size = machine->ram_size - mem_start; 4155fe269b1SPaul Mackerras } 4165fe269b1SPaul Mackerras } 4177db8a127SAlexey Kardashevskiy if (!mem_start) { 418b472b1a7SDaniel Henrique Barboza /* spapr_machine_init() checks for rma_size <= node0_size 419b472b1a7SDaniel Henrique Barboza * already */ 420e8f986fcSBharata B Rao spapr_populate_memory_node(fdt, i, 0, spapr->rma_size); 4217db8a127SAlexey Kardashevskiy mem_start += spapr->rma_size; 4227db8a127SAlexey Kardashevskiy node_size -= spapr->rma_size; 4237db8a127SAlexey Kardashevskiy } 4246010818cSAlexey Kardashevskiy for ( ; node_size; ) { 4256010818cSAlexey Kardashevskiy hwaddr sizetmp = pow2floor(node_size); 4266010818cSAlexey Kardashevskiy 4276010818cSAlexey Kardashevskiy /* mem_start != 0 here */ 4286010818cSAlexey Kardashevskiy if (ctzl(mem_start) < ctzl(sizetmp)) { 4296010818cSAlexey Kardashevskiy sizetmp = 1ULL << ctzl(mem_start); 4306010818cSAlexey Kardashevskiy } 4316010818cSAlexey Kardashevskiy 4326010818cSAlexey Kardashevskiy spapr_populate_memory_node(fdt, i, mem_start, sizetmp); 4336010818cSAlexey Kardashevskiy node_size -= sizetmp; 4346010818cSAlexey Kardashevskiy mem_start += sizetmp; 4356010818cSAlexey Kardashevskiy } 43653018216SPaolo Bonzini } 43753018216SPaolo Bonzini 43853018216SPaolo Bonzini return 0; 43953018216SPaolo Bonzini } 44053018216SPaolo Bonzini 4410da6f3feSBharata B Rao static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, 4420da6f3feSBharata B Rao sPAPRMachineState *spapr) 4430da6f3feSBharata B Rao { 4440da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 4450da6f3feSBharata B Rao CPUPPCState *env = &cpu->env; 4460da6f3feSBharata B Rao PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 44714bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 4480da6f3feSBharata B Rao uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 4490da6f3feSBharata B Rao 0xffffffff, 0xffffffff}; 450afd10a0fSBharata B Rao uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() 451afd10a0fSBharata B Rao : SPAPR_TIMEBASE_FREQ; 4520da6f3feSBharata B Rao uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; 4530da6f3feSBharata B Rao uint32_t page_sizes_prop[64]; 4540da6f3feSBharata B Rao size_t page_sizes_prop_size; 45522419c2aSDavid Gibson uint32_t vcpus_per_socket = smp_threads * smp_cores; 4560da6f3feSBharata B Rao uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 457abbc1247SDavid Gibson int compat_smt = MIN(smp_threads, ppc_compat_max_vthreads(cpu)); 458af81cf32SBharata B Rao sPAPRDRConnector *drc; 459af81cf32SBharata B Rao int drc_index; 460c64abd1fSSam Bobroff uint32_t radix_AP_encodings[PPC_PAGE_SIZES_MAX_SZ]; 461c64abd1fSSam Bobroff int i; 462af81cf32SBharata B Rao 463fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index); 464af81cf32SBharata B Rao if (drc) { 4650b55aa91SDavid Gibson drc_index = spapr_drc_index(drc); 466af81cf32SBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index))); 467af81cf32SBharata B Rao } 4680da6f3feSBharata B Rao 4690da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); 4700da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 4710da6f3feSBharata B Rao 4720da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 4730da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 4740da6f3feSBharata B Rao env->dcache_line_size))); 4750da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 4760da6f3feSBharata B Rao env->dcache_line_size))); 4770da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 4780da6f3feSBharata B Rao env->icache_line_size))); 4790da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 4800da6f3feSBharata B Rao env->icache_line_size))); 4810da6f3feSBharata B Rao 4820da6f3feSBharata B Rao if (pcc->l1_dcache_size) { 4830da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 4840da6f3feSBharata B Rao pcc->l1_dcache_size))); 4850da6f3feSBharata B Rao } else { 4863dc6f869SAlistair Francis warn_report("Unknown L1 dcache size for cpu"); 4870da6f3feSBharata B Rao } 4880da6f3feSBharata B Rao if (pcc->l1_icache_size) { 4890da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 4900da6f3feSBharata B Rao pcc->l1_icache_size))); 4910da6f3feSBharata B Rao } else { 4923dc6f869SAlistair Francis warn_report("Unknown L1 icache size for cpu"); 4930da6f3feSBharata B Rao } 4940da6f3feSBharata B Rao 4950da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 4960da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 49767d7d66fSDavid Gibson _FDT((fdt_setprop_cell(fdt, offset, "slb-size", cpu->hash64_opts->slb_size))); 49867d7d66fSDavid Gibson _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", cpu->hash64_opts->slb_size))); 4990da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 5000da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 5010da6f3feSBharata B Rao 5020da6f3feSBharata B Rao if (env->spr_cb[SPR_PURR].oea_read) { 5030da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 5040da6f3feSBharata B Rao } 5050da6f3feSBharata B Rao 50658969eeeSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 5070da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 5080da6f3feSBharata B Rao segs, sizeof(segs)))); 5090da6f3feSBharata B Rao } 5100da6f3feSBharata B Rao 51129386642SDavid Gibson /* Advertise VSX (vector extensions) if available 5120da6f3feSBharata B Rao * 1 == VMX / Altivec available 51329386642SDavid Gibson * 2 == VSX available 51429386642SDavid Gibson * 51529386642SDavid Gibson * Only CPUs for which we create core types in spapr_cpu_core.c 51629386642SDavid Gibson * are possible, and all of those have VMX */ 5174e5fe368SSuraj Jitindar Singh if (spapr_get_cap(spapr, SPAPR_CAP_VSX) != 0) { 51829386642SDavid Gibson _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2))); 51929386642SDavid Gibson } else { 52029386642SDavid Gibson _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1))); 5210da6f3feSBharata B Rao } 5220da6f3feSBharata B Rao 5230da6f3feSBharata B Rao /* Advertise DFP (Decimal Floating Point) if available 5240da6f3feSBharata B Rao * 0 / no property == no DFP 5250da6f3feSBharata B Rao * 1 == DFP available */ 5264e5fe368SSuraj Jitindar Singh if (spapr_get_cap(spapr, SPAPR_CAP_DFP) != 0) { 5270da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 5280da6f3feSBharata B Rao } 5290da6f3feSBharata B Rao 530644a2c99SDavid Gibson page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 5310da6f3feSBharata B Rao sizeof(page_sizes_prop)); 5320da6f3feSBharata B Rao if (page_sizes_prop_size) { 5330da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 5340da6f3feSBharata B Rao page_sizes_prop, page_sizes_prop_size))); 5350da6f3feSBharata B Rao } 5360da6f3feSBharata B Rao 537ee76a09fSDavid Gibson spapr_populate_pa_features(spapr, cpu, fdt, offset, false); 53890da0d5aSBenjamin Herrenschmidt 5390da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", 54022419c2aSDavid Gibson cs->cpu_index / vcpus_per_socket))); 5410da6f3feSBharata B Rao 5420da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", 5430da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)))); 5440da6f3feSBharata B Rao 54599861ecbSIgor Mammedov if (nb_numa_nodes > 1) { 54699861ecbSIgor Mammedov _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cpu)); 54799861ecbSIgor Mammedov } 5480da6f3feSBharata B Rao 54912dbeb16SDavid Gibson _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt)); 550c64abd1fSSam Bobroff 551c64abd1fSSam Bobroff if (pcc->radix_page_info) { 552c64abd1fSSam Bobroff for (i = 0; i < pcc->radix_page_info->count; i++) { 553c64abd1fSSam Bobroff radix_AP_encodings[i] = 554c64abd1fSSam Bobroff cpu_to_be32(pcc->radix_page_info->entries[i]); 555c64abd1fSSam Bobroff } 556c64abd1fSSam Bobroff _FDT((fdt_setprop(fdt, offset, "ibm,processor-radix-AP-encodings", 557c64abd1fSSam Bobroff radix_AP_encodings, 558c64abd1fSSam Bobroff pcc->radix_page_info->count * 559c64abd1fSSam Bobroff sizeof(radix_AP_encodings[0])))); 560c64abd1fSSam Bobroff } 561a8dafa52SSuraj Jitindar Singh 562a8dafa52SSuraj Jitindar Singh /* 563a8dafa52SSuraj Jitindar Singh * We set this property to let the guest know that it can use the large 564a8dafa52SSuraj Jitindar Singh * decrementer and its width in bits. 565a8dafa52SSuraj Jitindar Singh */ 566a8dafa52SSuraj Jitindar Singh if (spapr_get_cap(spapr, SPAPR_CAP_LARGE_DECREMENTER) != SPAPR_CAP_OFF) 567a8dafa52SSuraj Jitindar Singh _FDT((fdt_setprop_u32(fdt, offset, "ibm,dec-bits", 568a8dafa52SSuraj Jitindar Singh pcc->lrg_decr_bits))); 5690da6f3feSBharata B Rao } 5700da6f3feSBharata B Rao 5710da6f3feSBharata B Rao static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr) 5720da6f3feSBharata B Rao { 57304d595b3SEmilio G. Cota CPUState **rev; 5740da6f3feSBharata B Rao CPUState *cs; 57504d595b3SEmilio G. Cota int n_cpus; 5760da6f3feSBharata B Rao int cpus_offset; 5770da6f3feSBharata B Rao char *nodename; 57804d595b3SEmilio G. Cota int i; 5790da6f3feSBharata B Rao 5800da6f3feSBharata B Rao cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 5810da6f3feSBharata B Rao _FDT(cpus_offset); 5820da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 5830da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 5840da6f3feSBharata B Rao 5850da6f3feSBharata B Rao /* 5860da6f3feSBharata B Rao * We walk the CPUs in reverse order to ensure that CPU DT nodes 5870da6f3feSBharata B Rao * created by fdt_add_subnode() end up in the right order in FDT 5880da6f3feSBharata B Rao * for the guest kernel the enumerate the CPUs correctly. 58904d595b3SEmilio G. Cota * 59004d595b3SEmilio G. Cota * The CPU list cannot be traversed in reverse order, so we need 59104d595b3SEmilio G. Cota * to do extra work. 5920da6f3feSBharata B Rao */ 59304d595b3SEmilio G. Cota n_cpus = 0; 59404d595b3SEmilio G. Cota rev = NULL; 59504d595b3SEmilio G. Cota CPU_FOREACH(cs) { 59604d595b3SEmilio G. Cota rev = g_renew(CPUState *, rev, n_cpus + 1); 59704d595b3SEmilio G. Cota rev[n_cpus++] = cs; 59804d595b3SEmilio G. Cota } 59904d595b3SEmilio G. Cota 60004d595b3SEmilio G. Cota for (i = n_cpus - 1; i >= 0; i--) { 60104d595b3SEmilio G. Cota CPUState *cs = rev[i]; 6020da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 60314bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 6040da6f3feSBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 6050da6f3feSBharata B Rao int offset; 6060da6f3feSBharata B Rao 6075d0fb150SGreg Kurz if (!spapr_is_thread0_in_vcore(spapr, cpu)) { 6080da6f3feSBharata B Rao continue; 6090da6f3feSBharata B Rao } 6100da6f3feSBharata B Rao 6110da6f3feSBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, index); 6120da6f3feSBharata B Rao offset = fdt_add_subnode(fdt, cpus_offset, nodename); 6130da6f3feSBharata B Rao g_free(nodename); 6140da6f3feSBharata B Rao _FDT(offset); 6150da6f3feSBharata B Rao spapr_populate_cpu_dt(cs, fdt, offset, spapr); 6160da6f3feSBharata B Rao } 6170da6f3feSBharata B Rao 618eceba347SEmilio G. Cota g_free(rev); 6190da6f3feSBharata B Rao } 6200da6f3feSBharata B Rao 6210e947a89SThomas Huth static int spapr_rng_populate_dt(void *fdt) 6220e947a89SThomas Huth { 6230e947a89SThomas Huth int node; 6240e947a89SThomas Huth int ret; 6250e947a89SThomas Huth 6260e947a89SThomas Huth node = qemu_fdt_add_subnode(fdt, "/ibm,platform-facilities"); 6270e947a89SThomas Huth if (node <= 0) { 6280e947a89SThomas Huth return -1; 6290e947a89SThomas Huth } 6300e947a89SThomas Huth ret = fdt_setprop_string(fdt, node, "device_type", 6310e947a89SThomas Huth "ibm,platform-facilities"); 6320e947a89SThomas Huth ret |= fdt_setprop_cell(fdt, node, "#address-cells", 0x1); 6330e947a89SThomas Huth ret |= fdt_setprop_cell(fdt, node, "#size-cells", 0x0); 6340e947a89SThomas Huth 6350e947a89SThomas Huth node = fdt_add_subnode(fdt, node, "ibm,random-v1"); 6360e947a89SThomas Huth if (node <= 0) { 6370e947a89SThomas Huth return -1; 6380e947a89SThomas Huth } 6390e947a89SThomas Huth ret |= fdt_setprop_string(fdt, node, "compatible", "ibm,random"); 6400e947a89SThomas Huth 6410e947a89SThomas Huth return ret ? -1 : 0; 6420e947a89SThomas Huth } 6430e947a89SThomas Huth 644f47bd1c8SIgor Mammedov static uint32_t spapr_pc_dimm_node(MemoryDeviceInfoList *list, ram_addr_t addr) 645f47bd1c8SIgor Mammedov { 646f47bd1c8SIgor Mammedov MemoryDeviceInfoList *info; 647f47bd1c8SIgor Mammedov 648f47bd1c8SIgor Mammedov for (info = list; info; info = info->next) { 649f47bd1c8SIgor Mammedov MemoryDeviceInfo *value = info->value; 650f47bd1c8SIgor Mammedov 651f47bd1c8SIgor Mammedov if (value && value->type == MEMORY_DEVICE_INFO_KIND_DIMM) { 652f47bd1c8SIgor Mammedov PCDIMMDeviceInfo *pcdimm_info = value->u.dimm.data; 653f47bd1c8SIgor Mammedov 654ccc2cef8SDavid Gibson if (addr >= pcdimm_info->addr && 655f47bd1c8SIgor Mammedov addr < (pcdimm_info->addr + pcdimm_info->size)) { 656f47bd1c8SIgor Mammedov return pcdimm_info->node; 657f47bd1c8SIgor Mammedov } 658f47bd1c8SIgor Mammedov } 659f47bd1c8SIgor Mammedov } 660f47bd1c8SIgor Mammedov 661f47bd1c8SIgor Mammedov return -1; 662f47bd1c8SIgor Mammedov } 663f47bd1c8SIgor Mammedov 664a324d6f1SBharata B Rao struct sPAPRDrconfCellV2 { 665a324d6f1SBharata B Rao uint32_t seq_lmbs; 666a324d6f1SBharata B Rao uint64_t base_addr; 667a324d6f1SBharata B Rao uint32_t drc_index; 668a324d6f1SBharata B Rao uint32_t aa_index; 669a324d6f1SBharata B Rao uint32_t flags; 670a324d6f1SBharata B Rao } QEMU_PACKED; 671a324d6f1SBharata B Rao 672a324d6f1SBharata B Rao typedef struct DrconfCellQueue { 673a324d6f1SBharata B Rao struct sPAPRDrconfCellV2 cell; 674a324d6f1SBharata B Rao QSIMPLEQ_ENTRY(DrconfCellQueue) entry; 675a324d6f1SBharata B Rao } DrconfCellQueue; 676a324d6f1SBharata B Rao 677a324d6f1SBharata B Rao static DrconfCellQueue * 678a324d6f1SBharata B Rao spapr_get_drconf_cell(uint32_t seq_lmbs, uint64_t base_addr, 679a324d6f1SBharata B Rao uint32_t drc_index, uint32_t aa_index, 680a324d6f1SBharata B Rao uint32_t flags) 68103d196b7SBharata B Rao { 682a324d6f1SBharata B Rao DrconfCellQueue *elem; 683a324d6f1SBharata B Rao 684a324d6f1SBharata B Rao elem = g_malloc0(sizeof(*elem)); 685a324d6f1SBharata B Rao elem->cell.seq_lmbs = cpu_to_be32(seq_lmbs); 686a324d6f1SBharata B Rao elem->cell.base_addr = cpu_to_be64(base_addr); 687a324d6f1SBharata B Rao elem->cell.drc_index = cpu_to_be32(drc_index); 688a324d6f1SBharata B Rao elem->cell.aa_index = cpu_to_be32(aa_index); 689a324d6f1SBharata B Rao elem->cell.flags = cpu_to_be32(flags); 690a324d6f1SBharata B Rao 691a324d6f1SBharata B Rao return elem; 692a324d6f1SBharata B Rao } 693a324d6f1SBharata B Rao 694a324d6f1SBharata B Rao /* ibm,dynamic-memory-v2 */ 695a324d6f1SBharata B Rao static int spapr_populate_drmem_v2(sPAPRMachineState *spapr, void *fdt, 696a324d6f1SBharata B Rao int offset, MemoryDeviceInfoList *dimms) 697a324d6f1SBharata B Rao { 698b0c14ec4SDavid Hildenbrand MachineState *machine = MACHINE(spapr); 699cc941111SFabiano Rosas uint8_t *int_buf, *cur_index; 700a324d6f1SBharata B Rao int ret; 70103d196b7SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 702a324d6f1SBharata B Rao uint64_t addr, cur_addr, size; 703b0c14ec4SDavid Hildenbrand uint32_t nr_boot_lmbs = (machine->device_memory->base / lmb_size); 704b0c14ec4SDavid Hildenbrand uint64_t mem_end = machine->device_memory->base + 705b0c14ec4SDavid Hildenbrand memory_region_size(&machine->device_memory->mr); 706cc941111SFabiano Rosas uint32_t node, buf_len, nr_entries = 0; 707a324d6f1SBharata B Rao sPAPRDRConnector *drc; 708a324d6f1SBharata B Rao DrconfCellQueue *elem, *next; 709a324d6f1SBharata B Rao MemoryDeviceInfoList *info; 710a324d6f1SBharata B Rao QSIMPLEQ_HEAD(, DrconfCellQueue) drconf_queue 711a324d6f1SBharata B Rao = QSIMPLEQ_HEAD_INITIALIZER(drconf_queue); 712a324d6f1SBharata B Rao 713a324d6f1SBharata B Rao /* Entry to cover RAM and the gap area */ 714a324d6f1SBharata B Rao elem = spapr_get_drconf_cell(nr_boot_lmbs, 0, 0, -1, 715a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_RESERVED | 716a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 717a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 718a324d6f1SBharata B Rao nr_entries++; 719a324d6f1SBharata B Rao 720b0c14ec4SDavid Hildenbrand cur_addr = machine->device_memory->base; 721a324d6f1SBharata B Rao for (info = dimms; info; info = info->next) { 722a324d6f1SBharata B Rao PCDIMMDeviceInfo *di = info->value->u.dimm.data; 723a324d6f1SBharata B Rao 724a324d6f1SBharata B Rao addr = di->addr; 725a324d6f1SBharata B Rao size = di->size; 726a324d6f1SBharata B Rao node = di->node; 727a324d6f1SBharata B Rao 728a324d6f1SBharata B Rao /* Entry for hot-pluggable area */ 729a324d6f1SBharata B Rao if (cur_addr < addr) { 730a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size); 731a324d6f1SBharata B Rao g_assert(drc); 732a324d6f1SBharata B Rao elem = spapr_get_drconf_cell((addr - cur_addr) / lmb_size, 733a324d6f1SBharata B Rao cur_addr, spapr_drc_index(drc), -1, 0); 734a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 735a324d6f1SBharata B Rao nr_entries++; 736a324d6f1SBharata B Rao } 737a324d6f1SBharata B Rao 738a324d6f1SBharata B Rao /* Entry for DIMM */ 739a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr / lmb_size); 740a324d6f1SBharata B Rao g_assert(drc); 741a324d6f1SBharata B Rao elem = spapr_get_drconf_cell(size / lmb_size, addr, 742a324d6f1SBharata B Rao spapr_drc_index(drc), node, 743a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_ASSIGNED); 744a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 745a324d6f1SBharata B Rao nr_entries++; 746a324d6f1SBharata B Rao cur_addr = addr + size; 747a324d6f1SBharata B Rao } 748a324d6f1SBharata B Rao 749a324d6f1SBharata B Rao /* Entry for remaining hotpluggable area */ 750a324d6f1SBharata B Rao if (cur_addr < mem_end) { 751a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size); 752a324d6f1SBharata B Rao g_assert(drc); 753a324d6f1SBharata B Rao elem = spapr_get_drconf_cell((mem_end - cur_addr) / lmb_size, 754a324d6f1SBharata B Rao cur_addr, spapr_drc_index(drc), -1, 0); 755a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 756a324d6f1SBharata B Rao nr_entries++; 757a324d6f1SBharata B Rao } 758a324d6f1SBharata B Rao 759a324d6f1SBharata B Rao buf_len = nr_entries * sizeof(struct sPAPRDrconfCellV2) + sizeof(uint32_t); 760a324d6f1SBharata B Rao int_buf = cur_index = g_malloc0(buf_len); 761a324d6f1SBharata B Rao *(uint32_t *)int_buf = cpu_to_be32(nr_entries); 762a324d6f1SBharata B Rao cur_index += sizeof(nr_entries); 763a324d6f1SBharata B Rao 764a324d6f1SBharata B Rao QSIMPLEQ_FOREACH_SAFE(elem, &drconf_queue, entry, next) { 765a324d6f1SBharata B Rao memcpy(cur_index, &elem->cell, sizeof(elem->cell)); 766a324d6f1SBharata B Rao cur_index += sizeof(elem->cell); 767a324d6f1SBharata B Rao QSIMPLEQ_REMOVE(&drconf_queue, elem, DrconfCellQueue, entry); 768a324d6f1SBharata B Rao g_free(elem); 769a324d6f1SBharata B Rao } 770a324d6f1SBharata B Rao 771a324d6f1SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory-v2", int_buf, buf_len); 772a324d6f1SBharata B Rao g_free(int_buf); 773a324d6f1SBharata B Rao if (ret < 0) { 774a324d6f1SBharata B Rao return -1; 775a324d6f1SBharata B Rao } 776a324d6f1SBharata B Rao return 0; 777a324d6f1SBharata B Rao } 778a324d6f1SBharata B Rao 779a324d6f1SBharata B Rao /* ibm,dynamic-memory */ 780a324d6f1SBharata B Rao static int spapr_populate_drmem_v1(sPAPRMachineState *spapr, void *fdt, 781a324d6f1SBharata B Rao int offset, MemoryDeviceInfoList *dimms) 782a324d6f1SBharata B Rao { 783b0c14ec4SDavid Hildenbrand MachineState *machine = MACHINE(spapr); 784a324d6f1SBharata B Rao int i, ret; 785a324d6f1SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 7860c9269a5SDavid Hildenbrand uint32_t device_lmb_start = machine->device_memory->base / lmb_size; 787b0c14ec4SDavid Hildenbrand uint32_t nr_lmbs = (machine->device_memory->base + 788b0c14ec4SDavid Hildenbrand memory_region_size(&machine->device_memory->mr)) / 789d0e5a8f2SBharata B Rao lmb_size; 79003d196b7SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 79116c25aefSBharata B Rao 79216c25aefSBharata B Rao /* 793ef001f06SThomas Huth * Allocate enough buffer size to fit in ibm,dynamic-memory 794ef001f06SThomas Huth */ 795a324d6f1SBharata B Rao buf_len = (nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1) * sizeof(uint32_t); 79603d196b7SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 79703d196b7SBharata B Rao int_buf[0] = cpu_to_be32(nr_lmbs); 79803d196b7SBharata B Rao cur_index++; 79903d196b7SBharata B Rao for (i = 0; i < nr_lmbs; i++) { 800d0e5a8f2SBharata B Rao uint64_t addr = i * lmb_size; 80103d196b7SBharata B Rao uint32_t *dynamic_memory = cur_index; 80203d196b7SBharata B Rao 8030c9269a5SDavid Hildenbrand if (i >= device_lmb_start) { 804d0e5a8f2SBharata B Rao sPAPRDRConnector *drc; 805d0e5a8f2SBharata B Rao 806fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, i); 80703d196b7SBharata B Rao g_assert(drc); 80803d196b7SBharata B Rao 80903d196b7SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 81003d196b7SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 8110b55aa91SDavid Gibson dynamic_memory[2] = cpu_to_be32(spapr_drc_index(drc)); 81203d196b7SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 813f47bd1c8SIgor Mammedov dynamic_memory[4] = cpu_to_be32(spapr_pc_dimm_node(dimms, addr)); 814d0e5a8f2SBharata B Rao if (memory_region_present(get_system_memory(), addr)) { 81503d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); 81603d196b7SBharata B Rao } else { 81703d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(0); 81803d196b7SBharata B Rao } 819d0e5a8f2SBharata B Rao } else { 820d0e5a8f2SBharata B Rao /* 821d0e5a8f2SBharata B Rao * LMB information for RMA, boot time RAM and gap b/n RAM and 8220c9269a5SDavid Hildenbrand * device memory region -- all these are marked as reserved 823d0e5a8f2SBharata B Rao * and as having no valid DRC. 824d0e5a8f2SBharata B Rao */ 825d0e5a8f2SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 826d0e5a8f2SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 827d0e5a8f2SBharata B Rao dynamic_memory[2] = cpu_to_be32(0); 828d0e5a8f2SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 829d0e5a8f2SBharata B Rao dynamic_memory[4] = cpu_to_be32(-1); 830d0e5a8f2SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED | 831d0e5a8f2SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 832d0e5a8f2SBharata B Rao } 83303d196b7SBharata B Rao 83403d196b7SBharata B Rao cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; 83503d196b7SBharata B Rao } 83603d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len); 837a324d6f1SBharata B Rao g_free(int_buf); 83803d196b7SBharata B Rao if (ret < 0) { 839a324d6f1SBharata B Rao return -1; 840a324d6f1SBharata B Rao } 841a324d6f1SBharata B Rao return 0; 842a324d6f1SBharata B Rao } 843a324d6f1SBharata B Rao 844a324d6f1SBharata B Rao /* 845a324d6f1SBharata B Rao * Adds ibm,dynamic-reconfiguration-memory node. 846a324d6f1SBharata B Rao * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation 847a324d6f1SBharata B Rao * of this device tree node. 848a324d6f1SBharata B Rao */ 849a324d6f1SBharata B Rao static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) 850a324d6f1SBharata B Rao { 851a324d6f1SBharata B Rao MachineState *machine = MACHINE(spapr); 852a324d6f1SBharata B Rao int ret, i, offset; 853a324d6f1SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 854a324d6f1SBharata B Rao uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; 855a324d6f1SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 856a324d6f1SBharata B Rao int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; 857a324d6f1SBharata B Rao MemoryDeviceInfoList *dimms = NULL; 858a324d6f1SBharata B Rao 859a324d6f1SBharata B Rao /* 8600c9269a5SDavid Hildenbrand * Don't create the node if there is no device memory 861a324d6f1SBharata B Rao */ 862a324d6f1SBharata B Rao if (machine->ram_size == machine->maxram_size) { 863a324d6f1SBharata B Rao return 0; 864a324d6f1SBharata B Rao } 865a324d6f1SBharata B Rao 866a324d6f1SBharata B Rao offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory"); 867a324d6f1SBharata B Rao 868a324d6f1SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size, 869a324d6f1SBharata B Rao sizeof(prop_lmb_size)); 870a324d6f1SBharata B Rao if (ret < 0) { 871a324d6f1SBharata B Rao return ret; 872a324d6f1SBharata B Rao } 873a324d6f1SBharata B Rao 874a324d6f1SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff); 875a324d6f1SBharata B Rao if (ret < 0) { 876a324d6f1SBharata B Rao return ret; 877a324d6f1SBharata B Rao } 878a324d6f1SBharata B Rao 879a324d6f1SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0); 880a324d6f1SBharata B Rao if (ret < 0) { 881a324d6f1SBharata B Rao return ret; 882a324d6f1SBharata B Rao } 883a324d6f1SBharata B Rao 884a324d6f1SBharata B Rao /* ibm,dynamic-memory or ibm,dynamic-memory-v2 */ 8852cc0e2e8SDavid Hildenbrand dimms = qmp_memory_device_list(); 886a324d6f1SBharata B Rao if (spapr_ovec_test(spapr->ov5_cas, OV5_DRMEM_V2)) { 887a324d6f1SBharata B Rao ret = spapr_populate_drmem_v2(spapr, fdt, offset, dimms); 888a324d6f1SBharata B Rao } else { 889a324d6f1SBharata B Rao ret = spapr_populate_drmem_v1(spapr, fdt, offset, dimms); 890a324d6f1SBharata B Rao } 891a324d6f1SBharata B Rao qapi_free_MemoryDeviceInfoList(dimms); 892a324d6f1SBharata B Rao 893a324d6f1SBharata B Rao if (ret < 0) { 894a324d6f1SBharata B Rao return ret; 89503d196b7SBharata B Rao } 89603d196b7SBharata B Rao 89703d196b7SBharata B Rao /* ibm,associativity-lookup-arrays */ 898a324d6f1SBharata B Rao buf_len = (nr_nodes * 4 + 2) * sizeof(uint32_t); 899a324d6f1SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 9006663864eSBharata B Rao int_buf[0] = cpu_to_be32(nr_nodes); 90103d196b7SBharata B Rao int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */ 90203d196b7SBharata B Rao cur_index += 2; 9036663864eSBharata B Rao for (i = 0; i < nr_nodes; i++) { 90403d196b7SBharata B Rao uint32_t associativity[] = { 90503d196b7SBharata B Rao cpu_to_be32(0x0), 90603d196b7SBharata B Rao cpu_to_be32(0x0), 90703d196b7SBharata B Rao cpu_to_be32(0x0), 90803d196b7SBharata B Rao cpu_to_be32(i) 90903d196b7SBharata B Rao }; 91003d196b7SBharata B Rao memcpy(cur_index, associativity, sizeof(associativity)); 91103d196b7SBharata B Rao cur_index += 4; 91203d196b7SBharata B Rao } 91303d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf, 91403d196b7SBharata B Rao (cur_index - int_buf) * sizeof(uint32_t)); 91503d196b7SBharata B Rao g_free(int_buf); 916a324d6f1SBharata B Rao 91703d196b7SBharata B Rao return ret; 91803d196b7SBharata B Rao } 91903d196b7SBharata B Rao 9206787d27bSMichael Roth static int spapr_dt_cas_updates(sPAPRMachineState *spapr, void *fdt, 9216787d27bSMichael Roth sPAPROptionVector *ov5_updates) 9226787d27bSMichael Roth { 9236787d27bSMichael Roth sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 924417ece33SMichael Roth int ret = 0, offset; 9256787d27bSMichael Roth 9266787d27bSMichael Roth /* Generate ibm,dynamic-reconfiguration-memory node if required */ 9276787d27bSMichael Roth if (spapr_ovec_test(ov5_updates, OV5_DRCONF_MEMORY)) { 9286787d27bSMichael Roth g_assert(smc->dr_lmb_enabled); 9296787d27bSMichael Roth ret = spapr_populate_drconf_memory(spapr, fdt); 930417ece33SMichael Roth if (ret) { 931417ece33SMichael Roth goto out; 932417ece33SMichael Roth } 9336787d27bSMichael Roth } 9346787d27bSMichael Roth 935417ece33SMichael Roth offset = fdt_path_offset(fdt, "/chosen"); 936417ece33SMichael Roth if (offset < 0) { 937417ece33SMichael Roth offset = fdt_add_subnode(fdt, 0, "chosen"); 938417ece33SMichael Roth if (offset < 0) { 939417ece33SMichael Roth return offset; 940417ece33SMichael Roth } 941417ece33SMichael Roth } 942417ece33SMichael Roth ret = spapr_ovec_populate_dt(fdt, offset, spapr->ov5_cas, 943417ece33SMichael Roth "ibm,architecture-vec-5"); 944417ece33SMichael Roth 945417ece33SMichael Roth out: 9466787d27bSMichael Roth return ret; 9476787d27bSMichael Roth } 9486787d27bSMichael Roth 94910f12e64SDaniel Henrique Barboza static bool spapr_hotplugged_dev_before_cas(void) 95010f12e64SDaniel Henrique Barboza { 95110f12e64SDaniel Henrique Barboza Object *drc_container, *obj; 95210f12e64SDaniel Henrique Barboza ObjectProperty *prop; 95310f12e64SDaniel Henrique Barboza ObjectPropertyIterator iter; 95410f12e64SDaniel Henrique Barboza 95510f12e64SDaniel Henrique Barboza drc_container = container_get(object_get_root(), "/dr-connector"); 95610f12e64SDaniel Henrique Barboza object_property_iter_init(&iter, drc_container); 95710f12e64SDaniel Henrique Barboza while ((prop = object_property_iter_next(&iter))) { 95810f12e64SDaniel Henrique Barboza if (!strstart(prop->type, "link<", NULL)) { 95910f12e64SDaniel Henrique Barboza continue; 96010f12e64SDaniel Henrique Barboza } 96110f12e64SDaniel Henrique Barboza obj = object_property_get_link(drc_container, prop->name, NULL); 96210f12e64SDaniel Henrique Barboza if (spapr_drc_needed(obj)) { 96310f12e64SDaniel Henrique Barboza return true; 96410f12e64SDaniel Henrique Barboza } 96510f12e64SDaniel Henrique Barboza } 96610f12e64SDaniel Henrique Barboza return false; 96710f12e64SDaniel Henrique Barboza } 96810f12e64SDaniel Henrique Barboza 96903d196b7SBharata B Rao int spapr_h_cas_compose_response(sPAPRMachineState *spapr, 97003d196b7SBharata B Rao target_ulong addr, target_ulong size, 9716787d27bSMichael Roth sPAPROptionVector *ov5_updates) 97203d196b7SBharata B Rao { 97303d196b7SBharata B Rao void *fdt, *fdt_skel; 97403d196b7SBharata B Rao sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 }; 97503d196b7SBharata B Rao 97610f12e64SDaniel Henrique Barboza if (spapr_hotplugged_dev_before_cas()) { 97710f12e64SDaniel Henrique Barboza return 1; 97810f12e64SDaniel Henrique Barboza } 97910f12e64SDaniel Henrique Barboza 980827b17c4SGreg Kurz if (size < sizeof(hdr) || size > FW_MAX_SIZE) { 981827b17c4SGreg Kurz error_report("SLOF provided an unexpected CAS buffer size " 982827b17c4SGreg Kurz TARGET_FMT_lu " (min: %zu, max: %u)", 983827b17c4SGreg Kurz size, sizeof(hdr), FW_MAX_SIZE); 984827b17c4SGreg Kurz exit(EXIT_FAILURE); 985827b17c4SGreg Kurz } 986827b17c4SGreg Kurz 98703d196b7SBharata B Rao size -= sizeof(hdr); 98803d196b7SBharata B Rao 98910f12e64SDaniel Henrique Barboza /* Create skeleton */ 99003d196b7SBharata B Rao fdt_skel = g_malloc0(size); 99103d196b7SBharata B Rao _FDT((fdt_create(fdt_skel, size))); 992127f03e4SAlexey Kardashevskiy _FDT((fdt_finish_reservemap(fdt_skel))); 99303d196b7SBharata B Rao _FDT((fdt_begin_node(fdt_skel, ""))); 99403d196b7SBharata B Rao _FDT((fdt_end_node(fdt_skel))); 99503d196b7SBharata B Rao _FDT((fdt_finish(fdt_skel))); 99603d196b7SBharata B Rao fdt = g_malloc0(size); 99703d196b7SBharata B Rao _FDT((fdt_open_into(fdt_skel, fdt, size))); 99803d196b7SBharata B Rao g_free(fdt_skel); 99903d196b7SBharata B Rao 100003d196b7SBharata B Rao /* Fixup cpu nodes */ 100103d196b7SBharata B Rao _FDT((spapr_fixup_cpu_dt(fdt, spapr))); 100203d196b7SBharata B Rao 10036787d27bSMichael Roth if (spapr_dt_cas_updates(spapr, fdt, ov5_updates)) { 10046787d27bSMichael Roth return -1; 100503d196b7SBharata B Rao } 100603d196b7SBharata B Rao 100703d196b7SBharata B Rao /* Pack resulting tree */ 100803d196b7SBharata B Rao _FDT((fdt_pack(fdt))); 100903d196b7SBharata B Rao 101003d196b7SBharata B Rao if (fdt_totalsize(fdt) + sizeof(hdr) > size) { 101103d196b7SBharata B Rao trace_spapr_cas_failed(size); 101203d196b7SBharata B Rao return -1; 101303d196b7SBharata B Rao } 101403d196b7SBharata B Rao 101503d196b7SBharata B Rao cpu_physical_memory_write(addr, &hdr, sizeof(hdr)); 101603d196b7SBharata B Rao cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt)); 101703d196b7SBharata B Rao trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr)); 101803d196b7SBharata B Rao g_free(fdt); 101903d196b7SBharata B Rao 102003d196b7SBharata B Rao return 0; 102103d196b7SBharata B Rao } 102203d196b7SBharata B Rao 10233f5dabceSDavid Gibson static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt) 10243f5dabceSDavid Gibson { 10253f5dabceSDavid Gibson int rtas; 10263f5dabceSDavid Gibson GString *hypertas = g_string_sized_new(256); 10273f5dabceSDavid Gibson GString *qemu_hypertas = g_string_sized_new(256); 10283f5dabceSDavid Gibson uint32_t refpoints[] = { cpu_to_be32(0x4), cpu_to_be32(0x4) }; 10290c9269a5SDavid Hildenbrand uint64_t max_device_addr = MACHINE(spapr)->device_memory->base + 1030b0c14ec4SDavid Hildenbrand memory_region_size(&MACHINE(spapr)->device_memory->mr); 10313f5dabceSDavid Gibson uint32_t lrdr_capacity[] = { 10320c9269a5SDavid Hildenbrand cpu_to_be32(max_device_addr >> 32), 10330c9269a5SDavid Hildenbrand cpu_to_be32(max_device_addr & 0xffffffff), 10343f5dabceSDavid Gibson 0, cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE), 10353f5dabceSDavid Gibson cpu_to_be32(max_cpus / smp_threads), 10363f5dabceSDavid Gibson }; 1037da9f80fbSSerhii Popovych uint32_t maxdomains[] = { 1038da9f80fbSSerhii Popovych cpu_to_be32(4), 1039da9f80fbSSerhii Popovych cpu_to_be32(0), 1040da9f80fbSSerhii Popovych cpu_to_be32(0), 1041da9f80fbSSerhii Popovych cpu_to_be32(0), 10423908a24fSSerhii Popovych cpu_to_be32(nb_numa_nodes ? nb_numa_nodes : 1), 1043da9f80fbSSerhii Popovych }; 10443f5dabceSDavid Gibson 10453f5dabceSDavid Gibson _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas")); 10463f5dabceSDavid Gibson 10473f5dabceSDavid Gibson /* hypertas */ 10483f5dabceSDavid Gibson add_str(hypertas, "hcall-pft"); 10493f5dabceSDavid Gibson add_str(hypertas, "hcall-term"); 10503f5dabceSDavid Gibson add_str(hypertas, "hcall-dabr"); 10513f5dabceSDavid Gibson add_str(hypertas, "hcall-interrupt"); 10523f5dabceSDavid Gibson add_str(hypertas, "hcall-tce"); 10533f5dabceSDavid Gibson add_str(hypertas, "hcall-vio"); 10543f5dabceSDavid Gibson add_str(hypertas, "hcall-splpar"); 10553f5dabceSDavid Gibson add_str(hypertas, "hcall-bulk"); 10563f5dabceSDavid Gibson add_str(hypertas, "hcall-set-mode"); 10573f5dabceSDavid Gibson add_str(hypertas, "hcall-sprg0"); 10583f5dabceSDavid Gibson add_str(hypertas, "hcall-copy"); 10593f5dabceSDavid Gibson add_str(hypertas, "hcall-debug"); 1060c24ba3d0SLaurent Vivier add_str(hypertas, "hcall-vphn"); 10613f5dabceSDavid Gibson add_str(qemu_hypertas, "hcall-memop1"); 10623f5dabceSDavid Gibson 10633f5dabceSDavid Gibson if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { 10643f5dabceSDavid Gibson add_str(hypertas, "hcall-multi-tce"); 10653f5dabceSDavid Gibson } 106630f4b05bSDavid Gibson 106730f4b05bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { 106830f4b05bSDavid Gibson add_str(hypertas, "hcall-hpt-resize"); 106930f4b05bSDavid Gibson } 107030f4b05bSDavid Gibson 10713f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions", 10723f5dabceSDavid Gibson hypertas->str, hypertas->len)); 10733f5dabceSDavid Gibson g_string_free(hypertas, TRUE); 10743f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "qemu,hypertas-functions", 10753f5dabceSDavid Gibson qemu_hypertas->str, qemu_hypertas->len)); 10763f5dabceSDavid Gibson g_string_free(qemu_hypertas, TRUE); 10773f5dabceSDavid Gibson 10783f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,associativity-reference-points", 10793f5dabceSDavid Gibson refpoints, sizeof(refpoints))); 10803f5dabceSDavid Gibson 1081da9f80fbSSerhii Popovych _FDT(fdt_setprop(fdt, rtas, "ibm,max-associativity-domains", 1082da9f80fbSSerhii Popovych maxdomains, sizeof(maxdomains))); 1083da9f80fbSSerhii Popovych 10843f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-error-log-max", 10853f5dabceSDavid Gibson RTAS_ERROR_LOG_MAX)); 10863f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-event-scan-rate", 10873f5dabceSDavid Gibson RTAS_EVENT_SCAN_RATE)); 10883f5dabceSDavid Gibson 10894f441474SDavid Gibson g_assert(msi_nonbroken); 10903f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,change-msix-capable", NULL, 0)); 10913f5dabceSDavid Gibson 10923f5dabceSDavid Gibson /* 10933f5dabceSDavid Gibson * According to PAPR, rtas ibm,os-term does not guarantee a return 10943f5dabceSDavid Gibson * back to the guest cpu. 10953f5dabceSDavid Gibson * 10963f5dabceSDavid Gibson * While an additional ibm,extended-os-term property indicates 10973f5dabceSDavid Gibson * that rtas call return will always occur. Set this property. 10983f5dabceSDavid Gibson */ 10993f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,extended-os-term", NULL, 0)); 11003f5dabceSDavid Gibson 11013f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,lrdr-capacity", 11023f5dabceSDavid Gibson lrdr_capacity, sizeof(lrdr_capacity))); 11033f5dabceSDavid Gibson 11043f5dabceSDavid Gibson spapr_dt_rtas_tokens(fdt, rtas); 11053f5dabceSDavid Gibson } 11063f5dabceSDavid Gibson 1107db592b5bSCédric Le Goater /* 1108db592b5bSCédric Le Goater * Prepare ibm,arch-vec-5-platform-support, which indicates the MMU 1109db592b5bSCédric Le Goater * and the XIVE features that the guest may request and thus the valid 1110db592b5bSCédric Le Goater * values for bytes 23..26 of option vector 5: 1111db592b5bSCédric Le Goater */ 1112db592b5bSCédric Le Goater static void spapr_dt_ov5_platform_support(sPAPRMachineState *spapr, void *fdt, 1113db592b5bSCédric Le Goater int chosen) 11149fb4541fSSam Bobroff { 1115545d6e2bSSuraj Jitindar Singh PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); 1116545d6e2bSSuraj Jitindar Singh 1117f2b14e3aSCédric Le Goater char val[2 * 4] = { 11183ba3d0bcSCédric Le Goater 23, spapr->irq->ov5, /* Xive mode. */ 11199fb4541fSSam Bobroff 24, 0x00, /* Hash/Radix, filled in below. */ 11209fb4541fSSam Bobroff 25, 0x00, /* Hash options: Segment Tables == no, GTSE == no. */ 11219fb4541fSSam Bobroff 26, 0x40, /* Radix options: GTSE == yes. */ 11229fb4541fSSam Bobroff }; 11239fb4541fSSam Bobroff 11247abd43baSSuraj Jitindar Singh if (!ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0, 11257abd43baSSuraj Jitindar Singh first_ppc_cpu->compat_pvr)) { 1126db592b5bSCédric Le Goater /* 1127db592b5bSCédric Le Goater * If we're in a pre POWER9 compat mode then the guest should 1128db592b5bSCédric Le Goater * do hash and use the legacy interrupt mode 1129db592b5bSCédric Le Goater */ 1130db592b5bSCédric Le Goater val[1] = 0x00; /* XICS */ 11317abd43baSSuraj Jitindar Singh val[3] = 0x00; /* Hash */ 11327abd43baSSuraj Jitindar Singh } else if (kvm_enabled()) { 11339fb4541fSSam Bobroff if (kvmppc_has_cap_mmu_radix() && kvmppc_has_cap_mmu_hash_v3()) { 1134f2b14e3aSCédric Le Goater val[3] = 0x80; /* OV5_MMU_BOTH */ 11359fb4541fSSam Bobroff } else if (kvmppc_has_cap_mmu_radix()) { 1136f2b14e3aSCédric Le Goater val[3] = 0x40; /* OV5_MMU_RADIX_300 */ 11379fb4541fSSam Bobroff } else { 1138f2b14e3aSCédric Le Goater val[3] = 0x00; /* Hash */ 11399fb4541fSSam Bobroff } 11409fb4541fSSam Bobroff } else { 11417abd43baSSuraj Jitindar Singh /* V3 MMU supports both hash and radix in tcg (with dynamic switching) */ 1142f2b14e3aSCédric Le Goater val[3] = 0xC0; 1143545d6e2bSSuraj Jitindar Singh } 11449fb4541fSSam Bobroff _FDT(fdt_setprop(fdt, chosen, "ibm,arch-vec-5-platform-support", 11459fb4541fSSam Bobroff val, sizeof(val))); 11469fb4541fSSam Bobroff } 11479fb4541fSSam Bobroff 11487c866c6aSDavid Gibson static void spapr_dt_chosen(sPAPRMachineState *spapr, void *fdt) 11497c866c6aSDavid Gibson { 11507c866c6aSDavid Gibson MachineState *machine = MACHINE(spapr); 11517c866c6aSDavid Gibson int chosen; 11527c866c6aSDavid Gibson const char *boot_device = machine->boot_order; 11537c866c6aSDavid Gibson char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus); 11547c866c6aSDavid Gibson size_t cb = 0; 1155907aac2fSMark Cave-Ayland char *bootlist = get_boot_devices_list(&cb); 11567c866c6aSDavid Gibson 11577c866c6aSDavid Gibson _FDT(chosen = fdt_add_subnode(fdt, 0, "chosen")); 11587c866c6aSDavid Gibson 11597c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "bootargs", machine->kernel_cmdline)); 11607c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-start", 11617c866c6aSDavid Gibson spapr->initrd_base)); 11627c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-end", 11637c866c6aSDavid Gibson spapr->initrd_base + spapr->initrd_size)); 11647c866c6aSDavid Gibson 11657c866c6aSDavid Gibson if (spapr->kernel_size) { 11667c866c6aSDavid Gibson uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR), 11677c866c6aSDavid Gibson cpu_to_be64(spapr->kernel_size) }; 11687c866c6aSDavid Gibson 11697c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel", 11707c866c6aSDavid Gibson &kprop, sizeof(kprop))); 11717c866c6aSDavid Gibson if (spapr->kernel_le) { 11727c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel-le", NULL, 0)); 11737c866c6aSDavid Gibson } 11747c866c6aSDavid Gibson } 11757c866c6aSDavid Gibson if (boot_menu) { 11767c866c6aSDavid Gibson _FDT((fdt_setprop_cell(fdt, chosen, "qemu,boot-menu", boot_menu))); 11777c866c6aSDavid Gibson } 11787c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-width", graphic_width)); 11797c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-height", graphic_height)); 11807c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-depth", graphic_depth)); 11817c866c6aSDavid Gibson 11827c866c6aSDavid Gibson if (cb && bootlist) { 11837c866c6aSDavid Gibson int i; 11847c866c6aSDavid Gibson 11857c866c6aSDavid Gibson for (i = 0; i < cb; i++) { 11867c866c6aSDavid Gibson if (bootlist[i] == '\n') { 11877c866c6aSDavid Gibson bootlist[i] = ' '; 11887c866c6aSDavid Gibson } 11897c866c6aSDavid Gibson } 11907c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-list", bootlist)); 11917c866c6aSDavid Gibson } 11927c866c6aSDavid Gibson 11937c866c6aSDavid Gibson if (boot_device && strlen(boot_device)) { 11947c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-device", boot_device)); 11957c866c6aSDavid Gibson } 11967c866c6aSDavid Gibson 11977c866c6aSDavid Gibson if (!spapr->has_graphics && stdout_path) { 119890ee4e01SNikunj A Dadhania /* 119990ee4e01SNikunj A Dadhania * "linux,stdout-path" and "stdout" properties are deprecated by linux 120090ee4e01SNikunj A Dadhania * kernel. New platforms should only use the "stdout-path" property. Set 120190ee4e01SNikunj A Dadhania * the new property and continue using older property to remain 120290ee4e01SNikunj A Dadhania * compatible with the existing firmware. 120390ee4e01SNikunj A Dadhania */ 12047c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "linux,stdout-path", stdout_path)); 120590ee4e01SNikunj A Dadhania _FDT(fdt_setprop_string(fdt, chosen, "stdout-path", stdout_path)); 12067c866c6aSDavid Gibson } 12077c866c6aSDavid Gibson 1208db592b5bSCédric Le Goater spapr_dt_ov5_platform_support(spapr, fdt, chosen); 12099fb4541fSSam Bobroff 12107c866c6aSDavid Gibson g_free(stdout_path); 12117c866c6aSDavid Gibson g_free(bootlist); 12127c866c6aSDavid Gibson } 12137c866c6aSDavid Gibson 1214fca5f2dcSDavid Gibson static void spapr_dt_hypervisor(sPAPRMachineState *spapr, void *fdt) 1215fca5f2dcSDavid Gibson { 1216fca5f2dcSDavid Gibson /* The /hypervisor node isn't in PAPR - this is a hack to allow PR 1217fca5f2dcSDavid Gibson * KVM to work under pHyp with some guest co-operation */ 1218fca5f2dcSDavid Gibson int hypervisor; 1219fca5f2dcSDavid Gibson uint8_t hypercall[16]; 1220fca5f2dcSDavid Gibson 1221fca5f2dcSDavid Gibson _FDT(hypervisor = fdt_add_subnode(fdt, 0, "hypervisor")); 1222fca5f2dcSDavid Gibson /* indicate KVM hypercall interface */ 1223fca5f2dcSDavid Gibson _FDT(fdt_setprop_string(fdt, hypervisor, "compatible", "linux,kvm")); 1224fca5f2dcSDavid Gibson if (kvmppc_has_cap_fixup_hcalls()) { 1225fca5f2dcSDavid Gibson /* 1226fca5f2dcSDavid Gibson * Older KVM versions with older guest kernels were broken 1227fca5f2dcSDavid Gibson * with the magic page, don't allow the guest to map it. 1228fca5f2dcSDavid Gibson */ 1229fca5f2dcSDavid Gibson if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall, 1230fca5f2dcSDavid Gibson sizeof(hypercall))) { 1231fca5f2dcSDavid Gibson _FDT(fdt_setprop(fdt, hypervisor, "hcall-instructions", 1232fca5f2dcSDavid Gibson hypercall, sizeof(hypercall))); 1233fca5f2dcSDavid Gibson } 1234fca5f2dcSDavid Gibson } 1235fca5f2dcSDavid Gibson } 1236fca5f2dcSDavid Gibson 1237df269271SAlexey Kardashevskiy static void *spapr_build_fdt(sPAPRMachineState *spapr) 123853018216SPaolo Bonzini { 1239c86c1affSDaniel Henrique Barboza MachineState *machine = MACHINE(spapr); 12403c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 1241c20d332aSBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 12427c866c6aSDavid Gibson int ret; 124353018216SPaolo Bonzini void *fdt; 124453018216SPaolo Bonzini sPAPRPHBState *phb; 1245398a0bd5SDavid Gibson char *buf; 124653018216SPaolo Bonzini 1247398a0bd5SDavid Gibson fdt = g_malloc0(FDT_MAX_SIZE); 1248398a0bd5SDavid Gibson _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 124953018216SPaolo Bonzini 1250398a0bd5SDavid Gibson /* Root node */ 1251398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "device_type", "chrp")); 1252398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "model", "IBM pSeries (emulated by qemu)")); 1253398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "compatible", "qemu,pseries")); 1254398a0bd5SDavid Gibson 1255398a0bd5SDavid Gibson /* 1256398a0bd5SDavid Gibson * Add info to guest to indentify which host is it being run on 1257398a0bd5SDavid Gibson * and what is the uuid of the guest 1258398a0bd5SDavid Gibson */ 125927461d69SPrasad J Pandit if (spapr->host_model && !g_str_equal(spapr->host_model, "none")) { 126027461d69SPrasad J Pandit if (g_str_equal(spapr->host_model, "passthrough")) { 126127461d69SPrasad J Pandit /* -M host-model=passthrough */ 1262398a0bd5SDavid Gibson if (kvmppc_get_host_model(&buf)) { 1263398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-model", buf)); 1264398a0bd5SDavid Gibson g_free(buf); 1265398a0bd5SDavid Gibson } 126627461d69SPrasad J Pandit } else { 126727461d69SPrasad J Pandit /* -M host-model=<user-string> */ 126827461d69SPrasad J Pandit _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model)); 126927461d69SPrasad J Pandit } 127027461d69SPrasad J Pandit } 127127461d69SPrasad J Pandit 127227461d69SPrasad J Pandit if (spapr->host_serial && !g_str_equal(spapr->host_serial, "none")) { 127327461d69SPrasad J Pandit if (g_str_equal(spapr->host_serial, "passthrough")) { 127427461d69SPrasad J Pandit /* -M host-serial=passthrough */ 1275398a0bd5SDavid Gibson if (kvmppc_get_host_serial(&buf)) { 1276398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf)); 1277398a0bd5SDavid Gibson g_free(buf); 1278398a0bd5SDavid Gibson } 127927461d69SPrasad J Pandit } else { 128027461d69SPrasad J Pandit /* -M host-serial=<user-string> */ 128127461d69SPrasad J Pandit _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial)); 128227461d69SPrasad J Pandit } 128327461d69SPrasad J Pandit } 1284398a0bd5SDavid Gibson 1285398a0bd5SDavid Gibson buf = qemu_uuid_unparse_strdup(&qemu_uuid); 1286398a0bd5SDavid Gibson 1287398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "vm,uuid", buf)); 1288398a0bd5SDavid Gibson if (qemu_uuid_set) { 1289398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "system-id", buf)); 1290398a0bd5SDavid Gibson } 1291398a0bd5SDavid Gibson g_free(buf); 1292398a0bd5SDavid Gibson 1293398a0bd5SDavid Gibson if (qemu_get_vm_name()) { 1294398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "ibm,partition-name", 1295398a0bd5SDavid Gibson qemu_get_vm_name())); 1296398a0bd5SDavid Gibson } 1297398a0bd5SDavid Gibson 1298398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#address-cells", 2)); 1299398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2)); 130053018216SPaolo Bonzini 1301fc7e0765SDavid Gibson /* /interrupt controller */ 13023ba3d0bcSCédric Le Goater spapr->irq->dt_populate(spapr, spapr_max_server_number(spapr), fdt, 13035c7adcf4SGreg Kurz PHANDLE_INTC); 1304fc7e0765SDavid Gibson 1305e8f986fcSBharata B Rao ret = spapr_populate_memory(spapr, fdt); 1306e8f986fcSBharata B Rao if (ret < 0) { 1307ce9863b7SCédric Le Goater error_report("couldn't setup memory nodes in fdt"); 1308e8f986fcSBharata B Rao exit(1); 130953018216SPaolo Bonzini } 131053018216SPaolo Bonzini 1311bf5a6696SDavid Gibson /* /vdevice */ 1312bf5a6696SDavid Gibson spapr_dt_vdevice(spapr->vio_bus, fdt); 131353018216SPaolo Bonzini 13144d9392beSThomas Huth if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) { 13154d9392beSThomas Huth ret = spapr_rng_populate_dt(fdt); 13164d9392beSThomas Huth if (ret < 0) { 1317ce9863b7SCédric Le Goater error_report("could not set up rng device in the fdt"); 13184d9392beSThomas Huth exit(1); 13194d9392beSThomas Huth } 13204d9392beSThomas Huth } 13214d9392beSThomas Huth 132253018216SPaolo Bonzini QLIST_FOREACH(phb, &spapr->phbs, list) { 13235c7adcf4SGreg Kurz ret = spapr_populate_pci_dt(phb, PHANDLE_INTC, fdt, 13240a0a66cdSMichael Roth spapr->irq->nr_msis, NULL); 132553018216SPaolo Bonzini if (ret < 0) { 1326da34fed7SThomas Huth error_report("couldn't setup PCI devices in fdt"); 132753018216SPaolo Bonzini exit(1); 132853018216SPaolo Bonzini } 1329da34fed7SThomas Huth } 133053018216SPaolo Bonzini 13310da6f3feSBharata B Rao /* cpus */ 13320da6f3feSBharata B Rao spapr_populate_cpus_dt_node(fdt, spapr); 133353018216SPaolo Bonzini 1334c20d332aSBharata B Rao if (smc->dr_lmb_enabled) { 1335c20d332aSBharata B Rao _FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB)); 1336c20d332aSBharata B Rao } 1337c20d332aSBharata B Rao 1338c5514d0eSIgor Mammedov if (mc->has_hotpluggable_cpus) { 1339af81cf32SBharata B Rao int offset = fdt_path_offset(fdt, "/cpus"); 1340af81cf32SBharata B Rao ret = spapr_drc_populate_dt(fdt, offset, NULL, 1341af81cf32SBharata B Rao SPAPR_DR_CONNECTOR_TYPE_CPU); 1342af81cf32SBharata B Rao if (ret < 0) { 1343af81cf32SBharata B Rao error_report("Couldn't set up CPU DR device tree properties"); 1344af81cf32SBharata B Rao exit(1); 1345af81cf32SBharata B Rao } 1346af81cf32SBharata B Rao } 1347af81cf32SBharata B Rao 1348ffb1e275SDavid Gibson /* /event-sources */ 1349ffbb1705SMichael Roth spapr_dt_events(spapr, fdt); 1350ffb1e275SDavid Gibson 13513f5dabceSDavid Gibson /* /rtas */ 13523f5dabceSDavid Gibson spapr_dt_rtas(spapr, fdt); 13533f5dabceSDavid Gibson 13547c866c6aSDavid Gibson /* /chosen */ 13557c866c6aSDavid Gibson spapr_dt_chosen(spapr, fdt); 1356cf6e5223SDavid Gibson 1357fca5f2dcSDavid Gibson /* /hypervisor */ 1358fca5f2dcSDavid Gibson if (kvm_enabled()) { 1359fca5f2dcSDavid Gibson spapr_dt_hypervisor(spapr, fdt); 1360fca5f2dcSDavid Gibson } 1361fca5f2dcSDavid Gibson 1362cf6e5223SDavid Gibson /* Build memory reserve map */ 1363cf6e5223SDavid Gibson if (spapr->kernel_size) { 1364cf6e5223SDavid Gibson _FDT((fdt_add_mem_rsv(fdt, KERNEL_LOAD_ADDR, spapr->kernel_size))); 1365cf6e5223SDavid Gibson } 1366cf6e5223SDavid Gibson if (spapr->initrd_size) { 1367cf6e5223SDavid Gibson _FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base, spapr->initrd_size))); 1368cf6e5223SDavid Gibson } 1369cf6e5223SDavid Gibson 13706787d27bSMichael Roth /* ibm,client-architecture-support updates */ 13716787d27bSMichael Roth ret = spapr_dt_cas_updates(spapr, fdt, spapr->ov5_cas); 13726787d27bSMichael Roth if (ret < 0) { 13736787d27bSMichael Roth error_report("couldn't setup CAS properties fdt"); 13746787d27bSMichael Roth exit(1); 13756787d27bSMichael Roth } 13766787d27bSMichael Roth 13773998ccd0SNathan Fontenot if (smc->dr_phb_enabled) { 13783998ccd0SNathan Fontenot ret = spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_PHB); 13793998ccd0SNathan Fontenot if (ret < 0) { 13803998ccd0SNathan Fontenot error_report("Couldn't set up PHB DR device tree properties"); 13813998ccd0SNathan Fontenot exit(1); 13823998ccd0SNathan Fontenot } 13833998ccd0SNathan Fontenot } 13843998ccd0SNathan Fontenot 1385997b6cfcSDavid Gibson return fdt; 138653018216SPaolo Bonzini } 138753018216SPaolo Bonzini 138853018216SPaolo Bonzini static uint64_t translate_kernel_address(void *opaque, uint64_t addr) 138953018216SPaolo Bonzini { 139053018216SPaolo Bonzini return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR; 139153018216SPaolo Bonzini } 139253018216SPaolo Bonzini 13931d1be34dSDavid Gibson static void emulate_spapr_hypercall(PPCVirtualHypervisor *vhyp, 13941d1be34dSDavid Gibson PowerPCCPU *cpu) 139553018216SPaolo Bonzini { 139653018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 139753018216SPaolo Bonzini 13988d04fb55SJan Kiszka /* The TCG path should also be holding the BQL at this point */ 13998d04fb55SJan Kiszka g_assert(qemu_mutex_iothread_locked()); 14008d04fb55SJan Kiszka 140153018216SPaolo Bonzini if (msr_pr) { 140253018216SPaolo Bonzini hcall_dprintf("Hypercall made with MSR[PR]=1\n"); 140353018216SPaolo Bonzini env->gpr[3] = H_PRIVILEGE; 140453018216SPaolo Bonzini } else { 140553018216SPaolo Bonzini env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]); 140653018216SPaolo Bonzini } 140753018216SPaolo Bonzini } 140853018216SPaolo Bonzini 140900fd075eSBenjamin Herrenschmidt struct LPCRSyncState { 141000fd075eSBenjamin Herrenschmidt target_ulong value; 141100fd075eSBenjamin Herrenschmidt target_ulong mask; 141200fd075eSBenjamin Herrenschmidt }; 141300fd075eSBenjamin Herrenschmidt 141400fd075eSBenjamin Herrenschmidt static void do_lpcr_sync(CPUState *cs, run_on_cpu_data arg) 141500fd075eSBenjamin Herrenschmidt { 141600fd075eSBenjamin Herrenschmidt struct LPCRSyncState *s = arg.host_ptr; 141700fd075eSBenjamin Herrenschmidt PowerPCCPU *cpu = POWERPC_CPU(cs); 141800fd075eSBenjamin Herrenschmidt CPUPPCState *env = &cpu->env; 141900fd075eSBenjamin Herrenschmidt target_ulong lpcr; 142000fd075eSBenjamin Herrenschmidt 142100fd075eSBenjamin Herrenschmidt cpu_synchronize_state(cs); 142200fd075eSBenjamin Herrenschmidt lpcr = env->spr[SPR_LPCR]; 142300fd075eSBenjamin Herrenschmidt lpcr &= ~s->mask; 142400fd075eSBenjamin Herrenschmidt lpcr |= s->value; 142500fd075eSBenjamin Herrenschmidt ppc_store_lpcr(cpu, lpcr); 142600fd075eSBenjamin Herrenschmidt } 142700fd075eSBenjamin Herrenschmidt 142800fd075eSBenjamin Herrenschmidt void spapr_set_all_lpcrs(target_ulong value, target_ulong mask) 142900fd075eSBenjamin Herrenschmidt { 143000fd075eSBenjamin Herrenschmidt CPUState *cs; 143100fd075eSBenjamin Herrenschmidt struct LPCRSyncState s = { 143200fd075eSBenjamin Herrenschmidt .value = value, 143300fd075eSBenjamin Herrenschmidt .mask = mask 143400fd075eSBenjamin Herrenschmidt }; 143500fd075eSBenjamin Herrenschmidt CPU_FOREACH(cs) { 143600fd075eSBenjamin Herrenschmidt run_on_cpu(cs, do_lpcr_sync, RUN_ON_CPU_HOST_PTR(&s)); 143700fd075eSBenjamin Herrenschmidt } 143800fd075eSBenjamin Herrenschmidt } 143900fd075eSBenjamin Herrenschmidt 144079825f4dSBenjamin Herrenschmidt static void spapr_get_pate(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry) 14419861bb3eSSuraj Jitindar Singh { 14429861bb3eSSuraj Jitindar Singh sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); 14439861bb3eSSuraj Jitindar Singh 144479825f4dSBenjamin Herrenschmidt /* Copy PATE1:GR into PATE0:HR */ 144579825f4dSBenjamin Herrenschmidt entry->dw0 = spapr->patb_entry & PATE0_HR; 144679825f4dSBenjamin Herrenschmidt entry->dw1 = spapr->patb_entry; 14479861bb3eSSuraj Jitindar Singh } 14489861bb3eSSuraj Jitindar Singh 1449e6b8fd24SSamuel Mendoza-Jonas #define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2)) 1450e6b8fd24SSamuel Mendoza-Jonas #define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID) 1451e6b8fd24SSamuel Mendoza-Jonas #define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY) 1452e6b8fd24SSamuel Mendoza-Jonas #define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY)) 1453e6b8fd24SSamuel Mendoza-Jonas #define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY)) 1454e6b8fd24SSamuel Mendoza-Jonas 1455715c5407SDavid Gibson /* 1456715c5407SDavid Gibson * Get the fd to access the kernel htab, re-opening it if necessary 1457715c5407SDavid Gibson */ 1458715c5407SDavid Gibson static int get_htab_fd(sPAPRMachineState *spapr) 1459715c5407SDavid Gibson { 146014b0d748SGreg Kurz Error *local_err = NULL; 146114b0d748SGreg Kurz 1462715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1463715c5407SDavid Gibson return spapr->htab_fd; 1464715c5407SDavid Gibson } 1465715c5407SDavid Gibson 146614b0d748SGreg Kurz spapr->htab_fd = kvmppc_get_htab_fd(false, 0, &local_err); 1467715c5407SDavid Gibson if (spapr->htab_fd < 0) { 146814b0d748SGreg Kurz error_report_err(local_err); 1469715c5407SDavid Gibson } 1470715c5407SDavid Gibson 1471715c5407SDavid Gibson return spapr->htab_fd; 1472715c5407SDavid Gibson } 1473715c5407SDavid Gibson 1474b4db5413SSuraj Jitindar Singh void close_htab_fd(sPAPRMachineState *spapr) 1475715c5407SDavid Gibson { 1476715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1477715c5407SDavid Gibson close(spapr->htab_fd); 1478715c5407SDavid Gibson } 1479715c5407SDavid Gibson spapr->htab_fd = -1; 1480715c5407SDavid Gibson } 1481715c5407SDavid Gibson 1482e57ca75cSDavid Gibson static hwaddr spapr_hpt_mask(PPCVirtualHypervisor *vhyp) 1483e57ca75cSDavid Gibson { 1484e57ca75cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); 1485e57ca75cSDavid Gibson 1486e57ca75cSDavid Gibson return HTAB_SIZE(spapr) / HASH_PTEG_SIZE_64 - 1; 1487e57ca75cSDavid Gibson } 1488e57ca75cSDavid Gibson 14891ec26c75SGreg Kurz static target_ulong spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp) 14901ec26c75SGreg Kurz { 14911ec26c75SGreg Kurz sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); 14921ec26c75SGreg Kurz 14931ec26c75SGreg Kurz assert(kvm_enabled()); 14941ec26c75SGreg Kurz 14951ec26c75SGreg Kurz if (!spapr->htab) { 14961ec26c75SGreg Kurz return 0; 14971ec26c75SGreg Kurz } 14981ec26c75SGreg Kurz 14991ec26c75SGreg Kurz return (target_ulong)(uintptr_t)spapr->htab | (spapr->htab_shift - 18); 15001ec26c75SGreg Kurz } 15011ec26c75SGreg Kurz 1502e57ca75cSDavid Gibson static const ppc_hash_pte64_t *spapr_map_hptes(PPCVirtualHypervisor *vhyp, 1503e57ca75cSDavid Gibson hwaddr ptex, int n) 1504e57ca75cSDavid Gibson { 1505e57ca75cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); 1506e57ca75cSDavid Gibson hwaddr pte_offset = ptex * HASH_PTE_SIZE_64; 1507e57ca75cSDavid Gibson 1508e57ca75cSDavid Gibson if (!spapr->htab) { 1509e57ca75cSDavid Gibson /* 1510e57ca75cSDavid Gibson * HTAB is controlled by KVM. Fetch into temporary buffer 1511e57ca75cSDavid Gibson */ 1512e57ca75cSDavid Gibson ppc_hash_pte64_t *hptes = g_malloc(n * HASH_PTE_SIZE_64); 1513e57ca75cSDavid Gibson kvmppc_read_hptes(hptes, ptex, n); 1514e57ca75cSDavid Gibson return hptes; 1515e57ca75cSDavid Gibson } 1516e57ca75cSDavid Gibson 1517e57ca75cSDavid Gibson /* 1518e57ca75cSDavid Gibson * HTAB is controlled by QEMU. Just point to the internally 1519e57ca75cSDavid Gibson * accessible PTEG. 1520e57ca75cSDavid Gibson */ 1521e57ca75cSDavid Gibson return (const ppc_hash_pte64_t *)(spapr->htab + pte_offset); 1522e57ca75cSDavid Gibson } 1523e57ca75cSDavid Gibson 1524e57ca75cSDavid Gibson static void spapr_unmap_hptes(PPCVirtualHypervisor *vhyp, 1525e57ca75cSDavid Gibson const ppc_hash_pte64_t *hptes, 1526e57ca75cSDavid Gibson hwaddr ptex, int n) 1527e57ca75cSDavid Gibson { 1528e57ca75cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); 1529e57ca75cSDavid Gibson 1530e57ca75cSDavid Gibson if (!spapr->htab) { 1531e57ca75cSDavid Gibson g_free((void *)hptes); 1532e57ca75cSDavid Gibson } 1533e57ca75cSDavid Gibson 1534e57ca75cSDavid Gibson /* Nothing to do for qemu managed HPT */ 1535e57ca75cSDavid Gibson } 1536e57ca75cSDavid Gibson 1537e57ca75cSDavid Gibson static void spapr_store_hpte(PPCVirtualHypervisor *vhyp, hwaddr ptex, 1538e57ca75cSDavid Gibson uint64_t pte0, uint64_t pte1) 1539e57ca75cSDavid Gibson { 1540e57ca75cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); 1541e57ca75cSDavid Gibson hwaddr offset = ptex * HASH_PTE_SIZE_64; 1542e57ca75cSDavid Gibson 1543e57ca75cSDavid Gibson if (!spapr->htab) { 1544e57ca75cSDavid Gibson kvmppc_write_hpte(ptex, pte0, pte1); 1545e57ca75cSDavid Gibson } else { 15463054b0caSBenjamin Herrenschmidt if (pte0 & HPTE64_V_VALID) { 1547e57ca75cSDavid Gibson stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); 15483054b0caSBenjamin Herrenschmidt /* 15493054b0caSBenjamin Herrenschmidt * When setting valid, we write PTE1 first. This ensures 15503054b0caSBenjamin Herrenschmidt * proper synchronization with the reading code in 15513054b0caSBenjamin Herrenschmidt * ppc_hash64_pteg_search() 15523054b0caSBenjamin Herrenschmidt */ 15533054b0caSBenjamin Herrenschmidt smp_wmb(); 15543054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset, pte0); 15553054b0caSBenjamin Herrenschmidt } else { 15563054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset, pte0); 15573054b0caSBenjamin Herrenschmidt /* 15583054b0caSBenjamin Herrenschmidt * When clearing it we set PTE0 first. This ensures proper 15593054b0caSBenjamin Herrenschmidt * synchronization with the reading code in 15603054b0caSBenjamin Herrenschmidt * ppc_hash64_pteg_search() 15613054b0caSBenjamin Herrenschmidt */ 15623054b0caSBenjamin Herrenschmidt smp_wmb(); 15633054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); 15643054b0caSBenjamin Herrenschmidt } 1565e57ca75cSDavid Gibson } 1566e57ca75cSDavid Gibson } 1567e57ca75cSDavid Gibson 15680b0b8310SDavid Gibson int spapr_hpt_shift_for_ramsize(uint64_t ramsize) 15698dfe8e7fSDavid Gibson { 15708dfe8e7fSDavid Gibson int shift; 15718dfe8e7fSDavid Gibson 15728dfe8e7fSDavid Gibson /* We aim for a hash table of size 1/128 the size of RAM (rounded 15738dfe8e7fSDavid Gibson * up). The PAPR recommendation is actually 1/64 of RAM size, but 15748dfe8e7fSDavid Gibson * that's much more than is needed for Linux guests */ 15758dfe8e7fSDavid Gibson shift = ctz64(pow2ceil(ramsize)) - 7; 15768dfe8e7fSDavid Gibson shift = MAX(shift, 18); /* Minimum architected size */ 15778dfe8e7fSDavid Gibson shift = MIN(shift, 46); /* Maximum architected size */ 15788dfe8e7fSDavid Gibson return shift; 15798dfe8e7fSDavid Gibson } 15808dfe8e7fSDavid Gibson 158106ec79e8SBharata B Rao void spapr_free_hpt(sPAPRMachineState *spapr) 158206ec79e8SBharata B Rao { 158306ec79e8SBharata B Rao g_free(spapr->htab); 158406ec79e8SBharata B Rao spapr->htab = NULL; 158506ec79e8SBharata B Rao spapr->htab_shift = 0; 158606ec79e8SBharata B Rao close_htab_fd(spapr); 158706ec79e8SBharata B Rao } 158806ec79e8SBharata B Rao 15892772cf6bSDavid Gibson void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift, 1590c5f54f3eSDavid Gibson Error **errp) 159153018216SPaolo Bonzini { 1592c5f54f3eSDavid Gibson long rc; 159353018216SPaolo Bonzini 1594c5f54f3eSDavid Gibson /* Clean up any HPT info from a previous boot */ 159506ec79e8SBharata B Rao spapr_free_hpt(spapr); 159653018216SPaolo Bonzini 1597c5f54f3eSDavid Gibson rc = kvmppc_reset_htab(shift); 1598c5f54f3eSDavid Gibson if (rc < 0) { 1599c5f54f3eSDavid Gibson /* kernel-side HPT needed, but couldn't allocate one */ 1600c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1601c5f54f3eSDavid Gibson "Failed to allocate KVM HPT of order %d (try smaller maxmem?)", 1602c5f54f3eSDavid Gibson shift); 1603c5f54f3eSDavid Gibson /* This is almost certainly fatal, but if the caller really 1604c5f54f3eSDavid Gibson * wants to carry on with shift == 0, it's welcome to try */ 1605c5f54f3eSDavid Gibson } else if (rc > 0) { 1606c5f54f3eSDavid Gibson /* kernel-side HPT allocated */ 1607c5f54f3eSDavid Gibson if (rc != shift) { 1608c5f54f3eSDavid Gibson error_setg(errp, 1609c5f54f3eSDavid Gibson "Requested order %d HPT, but kernel allocated order %ld (try smaller maxmem?)", 1610c5f54f3eSDavid Gibson shift, rc); 16117735fedaSBharata B Rao } 16127735fedaSBharata B Rao 161353018216SPaolo Bonzini spapr->htab_shift = shift; 1614c18ad9a5SDavid Gibson spapr->htab = NULL; 1615b817772aSBharata B Rao } else { 1616c5f54f3eSDavid Gibson /* kernel-side HPT not needed, allocate in userspace instead */ 1617c5f54f3eSDavid Gibson size_t size = 1ULL << shift; 1618c5f54f3eSDavid Gibson int i; 161901a57972SSamuel Mendoza-Jonas 1620c5f54f3eSDavid Gibson spapr->htab = qemu_memalign(size, size); 1621c5f54f3eSDavid Gibson if (!spapr->htab) { 1622c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1623c5f54f3eSDavid Gibson "Could not allocate HPT of order %d", shift); 1624c5f54f3eSDavid Gibson return; 1625b817772aSBharata B Rao } 1626b817772aSBharata B Rao 1627c5f54f3eSDavid Gibson memset(spapr->htab, 0, size); 1628c5f54f3eSDavid Gibson spapr->htab_shift = shift; 1629b817772aSBharata B Rao 1630c5f54f3eSDavid Gibson for (i = 0; i < size / HASH_PTE_SIZE_64; i++) { 1631c5f54f3eSDavid Gibson DIRTY_HPTE(HPTE(spapr->htab, i)); 16327735fedaSBharata B Rao } 163353018216SPaolo Bonzini } 1634ee4d9eccSSuraj Jitindar Singh /* We're setting up a hash table, so that means we're not radix */ 163500fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(0, LPCR_HR | LPCR_UPRT); 163653018216SPaolo Bonzini } 163753018216SPaolo Bonzini 1638b4db5413SSuraj Jitindar Singh void spapr_setup_hpt_and_vrma(sPAPRMachineState *spapr) 1639b4db5413SSuraj Jitindar Singh { 16402772cf6bSDavid Gibson int hpt_shift; 16412772cf6bSDavid Gibson 16422772cf6bSDavid Gibson if ((spapr->resize_hpt == SPAPR_RESIZE_HPT_DISABLED) 16432772cf6bSDavid Gibson || (spapr->cas_reboot 16442772cf6bSDavid Gibson && !spapr_ovec_test(spapr->ov5_cas, OV5_HPT_RESIZE))) { 16452772cf6bSDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(MACHINE(spapr)->maxram_size); 16462772cf6bSDavid Gibson } else { 1647768a20f3SDavid Gibson uint64_t current_ram_size; 1648768a20f3SDavid Gibson 1649768a20f3SDavid Gibson current_ram_size = MACHINE(spapr)->ram_size + get_plugged_memory_size(); 1650768a20f3SDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(current_ram_size); 16512772cf6bSDavid Gibson } 16522772cf6bSDavid Gibson spapr_reallocate_hpt(spapr, hpt_shift, &error_fatal); 16532772cf6bSDavid Gibson 1654b4db5413SSuraj Jitindar Singh if (spapr->vrma_adjust) { 1655c86c1affSDaniel Henrique Barboza spapr->rma_size = kvmppc_rma_size(spapr_node0_size(MACHINE(spapr)), 1656b4db5413SSuraj Jitindar Singh spapr->htab_shift); 1657b4db5413SSuraj Jitindar Singh } 1658b4db5413SSuraj Jitindar Singh } 1659b4db5413SSuraj Jitindar Singh 166082512483SGreg Kurz static int spapr_reset_drcs(Object *child, void *opaque) 166182512483SGreg Kurz { 166282512483SGreg Kurz sPAPRDRConnector *drc = 166382512483SGreg Kurz (sPAPRDRConnector *) object_dynamic_cast(child, 166482512483SGreg Kurz TYPE_SPAPR_DR_CONNECTOR); 166582512483SGreg Kurz 166682512483SGreg Kurz if (drc) { 166782512483SGreg Kurz spapr_drc_reset(drc); 166882512483SGreg Kurz } 166982512483SGreg Kurz 167082512483SGreg Kurz return 0; 167182512483SGreg Kurz } 167282512483SGreg Kurz 1673bcb5ce08SDavid Gibson static void spapr_machine_reset(void) 167453018216SPaolo Bonzini { 1675c5f54f3eSDavid Gibson MachineState *machine = MACHINE(qdev_get_machine()); 1676c5f54f3eSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 1677182735efSAndreas Färber PowerPCCPU *first_ppc_cpu; 1678b7d1f77aSBenjamin Herrenschmidt uint32_t rtas_limit; 1679cae172abSDavid Gibson hwaddr rtas_addr, fdt_addr; 1680997b6cfcSDavid Gibson void *fdt; 1681997b6cfcSDavid Gibson int rc; 1682259186a7SAndreas Färber 16839f6edd06SDavid Gibson spapr_caps_apply(spapr); 168433face6bSDavid Gibson 16851481fe5fSLaurent Vivier first_ppc_cpu = POWERPC_CPU(first_cpu); 16861481fe5fSLaurent Vivier if (kvm_enabled() && kvmppc_has_cap_mmu_radix() && 1687ad99d04cSDavid Gibson ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, 16881481fe5fSLaurent Vivier spapr->max_compat_pvr)) { 168979825f4dSBenjamin Herrenschmidt /* 169079825f4dSBenjamin Herrenschmidt * If using KVM with radix mode available, VCPUs can be started 1691b4db5413SSuraj Jitindar Singh * without a HPT because KVM will start them in radix mode. 169279825f4dSBenjamin Herrenschmidt * Set the GR bit in PATE so that we know there is no HPT. 169379825f4dSBenjamin Herrenschmidt */ 169479825f4dSBenjamin Herrenschmidt spapr->patb_entry = PATE1_GR; 169500fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(LPCR_HR | LPCR_UPRT, LPCR_HR | LPCR_UPRT); 1696b4db5413SSuraj Jitindar Singh } else { 1697b4db5413SSuraj Jitindar Singh spapr_setup_hpt_and_vrma(spapr); 1698c5f54f3eSDavid Gibson } 169953018216SPaolo Bonzini 170079825f4dSBenjamin Herrenschmidt /* 170179825f4dSBenjamin Herrenschmidt * If this reset wasn't generated by CAS, we should reset our 170279825f4dSBenjamin Herrenschmidt * negotiated options and start from scratch 170379825f4dSBenjamin Herrenschmidt */ 17049012a53fSGreg Kurz if (!spapr->cas_reboot) { 17059012a53fSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas); 17069012a53fSGreg Kurz spapr->ov5_cas = spapr_ovec_new(); 17079012a53fSGreg Kurz 17089012a53fSGreg Kurz ppc_set_compat(first_ppc_cpu, spapr->max_compat_pvr, &error_fatal); 17099012a53fSGreg Kurz } 17109012a53fSGreg Kurz 171182cffa2eSCédric Le Goater if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { 171282cffa2eSCédric Le Goater spapr_irq_msi_reset(spapr); 171382cffa2eSCédric Le Goater } 171482cffa2eSCédric Le Goater 171553018216SPaolo Bonzini qemu_devices_reset(); 171682512483SGreg Kurz 1717b2e22477SCédric Le Goater /* 1718b2e22477SCédric Le Goater * This is fixing some of the default configuration of the XIVE 1719b2e22477SCédric Le Goater * devices. To be called after the reset of the machine devices. 1720b2e22477SCédric Le Goater */ 1721b2e22477SCédric Le Goater spapr_irq_reset(spapr, &error_fatal); 1722b2e22477SCédric Le Goater 172323ff81bdSGreg Kurz /* 172423ff81bdSGreg Kurz * There is no CAS under qtest. Simulate one to please the code that 172523ff81bdSGreg Kurz * depends on spapr->ov5_cas. This is especially needed to test device 172623ff81bdSGreg Kurz * unplug, so we do that before resetting the DRCs. 172723ff81bdSGreg Kurz */ 172823ff81bdSGreg Kurz if (qtest_enabled()) { 172923ff81bdSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas); 173023ff81bdSGreg Kurz spapr->ov5_cas = spapr_ovec_clone(spapr->ov5); 173123ff81bdSGreg Kurz } 173223ff81bdSGreg Kurz 173382512483SGreg Kurz /* DRC reset may cause a device to be unplugged. This will cause troubles 173482512483SGreg Kurz * if this device is used by another device (eg, a running vhost backend 173582512483SGreg Kurz * will crash QEMU if the DIMM holding the vring goes away). To avoid such 173682512483SGreg Kurz * situations, we reset DRCs after all devices have been reset. 173782512483SGreg Kurz */ 173882512483SGreg Kurz object_child_foreach_recursive(object_get_root(), spapr_reset_drcs, NULL); 173982512483SGreg Kurz 174056258174SDaniel Henrique Barboza spapr_clear_pending_events(spapr); 174153018216SPaolo Bonzini 1742b7d1f77aSBenjamin Herrenschmidt /* 1743b7d1f77aSBenjamin Herrenschmidt * We place the device tree and RTAS just below either the top of the RMA, 1744df269271SAlexey Kardashevskiy * or just below 2GB, whichever is lower, so that it can be 1745b7d1f77aSBenjamin Herrenschmidt * processed with 32-bit real mode code if necessary 1746b7d1f77aSBenjamin Herrenschmidt */ 1747b7d1f77aSBenjamin Herrenschmidt rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR); 1748cae172abSDavid Gibson rtas_addr = rtas_limit - RTAS_MAX_SIZE; 1749cae172abSDavid Gibson fdt_addr = rtas_addr - FDT_MAX_SIZE; 1750b7d1f77aSBenjamin Herrenschmidt 1751df269271SAlexey Kardashevskiy fdt = spapr_build_fdt(spapr); 175253018216SPaolo Bonzini 17532cac78c1SDavid Gibson spapr_load_rtas(spapr, fdt, rtas_addr); 1754b7d1f77aSBenjamin Herrenschmidt 1755997b6cfcSDavid Gibson rc = fdt_pack(fdt); 1756997b6cfcSDavid Gibson 1757997b6cfcSDavid Gibson /* Should only fail if we've built a corrupted tree */ 1758997b6cfcSDavid Gibson assert(rc == 0); 1759997b6cfcSDavid Gibson 1760997b6cfcSDavid Gibson if (fdt_totalsize(fdt) > FDT_MAX_SIZE) { 1761997b6cfcSDavid Gibson error_report("FDT too big ! 0x%x bytes (max is 0x%x)", 1762997b6cfcSDavid Gibson fdt_totalsize(fdt), FDT_MAX_SIZE); 1763997b6cfcSDavid Gibson exit(1); 1764997b6cfcSDavid Gibson } 1765997b6cfcSDavid Gibson 1766997b6cfcSDavid Gibson /* Load the fdt */ 1767997b6cfcSDavid Gibson qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 1768cae172abSDavid Gibson cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); 1769fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob); 1770fea35ca4SAlexey Kardashevskiy spapr->fdt_size = fdt_totalsize(fdt); 1771fea35ca4SAlexey Kardashevskiy spapr->fdt_initial_size = spapr->fdt_size; 1772fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = fdt; 1773997b6cfcSDavid Gibson 177453018216SPaolo Bonzini /* Set up the entry state */ 177584369f63SDavid Gibson spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT, fdt_addr); 1776182735efSAndreas Färber first_ppc_cpu->env.gpr[5] = 0; 177753018216SPaolo Bonzini 17786787d27bSMichael Roth spapr->cas_reboot = false; 177953018216SPaolo Bonzini } 178053018216SPaolo Bonzini 178128e02042SDavid Gibson static void spapr_create_nvram(sPAPRMachineState *spapr) 178253018216SPaolo Bonzini { 17832ff3de68SMarkus Armbruster DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); 17843978b863SPaolo Bonzini DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); 178553018216SPaolo Bonzini 17863978b863SPaolo Bonzini if (dinfo) { 17876231a6daSMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo), 17886231a6daSMarkus Armbruster &error_fatal); 178953018216SPaolo Bonzini } 179053018216SPaolo Bonzini 179153018216SPaolo Bonzini qdev_init_nofail(dev); 179253018216SPaolo Bonzini 179353018216SPaolo Bonzini spapr->nvram = (struct sPAPRNVRAM *)dev; 179453018216SPaolo Bonzini } 179553018216SPaolo Bonzini 179628e02042SDavid Gibson static void spapr_rtc_create(sPAPRMachineState *spapr) 179728df36a1SDavid Gibson { 1798f6d4dca8SThomas Huth object_initialize_child(OBJECT(spapr), "rtc", 1799f6d4dca8SThomas Huth &spapr->rtc, sizeof(spapr->rtc), TYPE_SPAPR_RTC, 1800f6d4dca8SThomas Huth &error_fatal, NULL); 1801147ff807SCédric Le Goater object_property_set_bool(OBJECT(&spapr->rtc), true, "realized", 1802147ff807SCédric Le Goater &error_fatal); 1803147ff807SCédric Le Goater object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc), 1804147ff807SCédric Le Goater "date", &error_fatal); 180528df36a1SDavid Gibson } 180628df36a1SDavid Gibson 180753018216SPaolo Bonzini /* Returns whether we want to use VGA or not */ 180814c6a894SDavid Gibson static bool spapr_vga_init(PCIBus *pci_bus, Error **errp) 180953018216SPaolo Bonzini { 181053018216SPaolo Bonzini switch (vga_interface_type) { 181153018216SPaolo Bonzini case VGA_NONE: 18127effdaa3SMark Wu return false; 18137effdaa3SMark Wu case VGA_DEVICE: 18147effdaa3SMark Wu return true; 181553018216SPaolo Bonzini case VGA_STD: 1816b798c190SBenjamin Herrenschmidt case VGA_VIRTIO: 18176e66d0c6SThomas Huth case VGA_CIRRUS: 181853018216SPaolo Bonzini return pci_vga_init(pci_bus) != NULL; 181953018216SPaolo Bonzini default: 182014c6a894SDavid Gibson error_setg(errp, 182114c6a894SDavid Gibson "Unsupported VGA mode, only -vga std or -vga virtio is supported"); 182214c6a894SDavid Gibson return false; 182353018216SPaolo Bonzini } 182453018216SPaolo Bonzini } 182553018216SPaolo Bonzini 18264e5fe368SSuraj Jitindar Singh static int spapr_pre_load(void *opaque) 18274e5fe368SSuraj Jitindar Singh { 18284e5fe368SSuraj Jitindar Singh int rc; 18294e5fe368SSuraj Jitindar Singh 18304e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_load(opaque); 18314e5fe368SSuraj Jitindar Singh if (rc) { 18324e5fe368SSuraj Jitindar Singh return rc; 18334e5fe368SSuraj Jitindar Singh } 18344e5fe368SSuraj Jitindar Singh 18354e5fe368SSuraj Jitindar Singh return 0; 18364e5fe368SSuraj Jitindar Singh } 18374e5fe368SSuraj Jitindar Singh 1838880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id) 1839880ae7deSDavid Gibson { 184028e02042SDavid Gibson sPAPRMachineState *spapr = (sPAPRMachineState *)opaque; 1841880ae7deSDavid Gibson int err = 0; 1842880ae7deSDavid Gibson 1843be85537dSDavid Gibson err = spapr_caps_post_migration(spapr); 1844be85537dSDavid Gibson if (err) { 1845be85537dSDavid Gibson return err; 1846be85537dSDavid Gibson } 1847be85537dSDavid Gibson 1848e502202cSCédric Le Goater /* 1849e502202cSCédric Le Goater * In earlier versions, there was no separate qdev for the PAPR 1850880ae7deSDavid Gibson * RTC, so the RTC offset was stored directly in sPAPREnvironment. 1851880ae7deSDavid Gibson * So when migrating from those versions, poke the incoming offset 1852e502202cSCédric Le Goater * value into the RTC device 1853e502202cSCédric Le Goater */ 1854880ae7deSDavid Gibson if (version_id < 3) { 1855147ff807SCédric Le Goater err = spapr_rtc_import_offset(&spapr->rtc, spapr->rtc_offset); 1856e502202cSCédric Le Goater if (err) { 1857e502202cSCédric Le Goater return err; 1858e502202cSCédric Le Goater } 1859880ae7deSDavid Gibson } 1860880ae7deSDavid Gibson 18610c86b2dfSLaurent Vivier if (kvm_enabled() && spapr->patb_entry) { 1862d39c90f5SBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(first_cpu); 186379825f4dSBenjamin Herrenschmidt bool radix = !!(spapr->patb_entry & PATE1_GR); 1864d39c90f5SBharata B Rao bool gtse = !!(cpu->env.spr[SPR_LPCR] & LPCR_GTSE); 1865d39c90f5SBharata B Rao 186600fd075eSBenjamin Herrenschmidt /* 186700fd075eSBenjamin Herrenschmidt * Update LPCR:HR and UPRT as they may not be set properly in 186800fd075eSBenjamin Herrenschmidt * the stream 186900fd075eSBenjamin Herrenschmidt */ 187000fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(radix ? (LPCR_HR | LPCR_UPRT) : 0, 187100fd075eSBenjamin Herrenschmidt LPCR_HR | LPCR_UPRT); 187200fd075eSBenjamin Herrenschmidt 1873d39c90f5SBharata B Rao err = kvmppc_configure_v3_mmu(cpu, radix, gtse, spapr->patb_entry); 1874d39c90f5SBharata B Rao if (err) { 1875d39c90f5SBharata B Rao error_report("Process table config unsupported by the host"); 1876d39c90f5SBharata B Rao return -EINVAL; 1877d39c90f5SBharata B Rao } 1878d39c90f5SBharata B Rao } 1879d39c90f5SBharata B Rao 18801c53b06cSCédric Le Goater err = spapr_irq_post_load(spapr, version_id); 18811c53b06cSCédric Le Goater if (err) { 18821c53b06cSCédric Le Goater return err; 18831c53b06cSCédric Le Goater } 18841c53b06cSCédric Le Goater 1885880ae7deSDavid Gibson return err; 1886880ae7deSDavid Gibson } 1887880ae7deSDavid Gibson 18884e5fe368SSuraj Jitindar Singh static int spapr_pre_save(void *opaque) 18894e5fe368SSuraj Jitindar Singh { 18904e5fe368SSuraj Jitindar Singh int rc; 18914e5fe368SSuraj Jitindar Singh 18924e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_save(opaque); 18934e5fe368SSuraj Jitindar Singh if (rc) { 18944e5fe368SSuraj Jitindar Singh return rc; 18954e5fe368SSuraj Jitindar Singh } 18964e5fe368SSuraj Jitindar Singh 18974e5fe368SSuraj Jitindar Singh return 0; 18984e5fe368SSuraj Jitindar Singh } 18994e5fe368SSuraj Jitindar Singh 1900880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id) 1901880ae7deSDavid Gibson { 1902880ae7deSDavid Gibson return version_id < 3; 1903880ae7deSDavid Gibson } 1904880ae7deSDavid Gibson 1905fd38804bSDaniel Henrique Barboza static bool spapr_pending_events_needed(void *opaque) 1906fd38804bSDaniel Henrique Barboza { 1907fd38804bSDaniel Henrique Barboza sPAPRMachineState *spapr = (sPAPRMachineState *)opaque; 1908fd38804bSDaniel Henrique Barboza return !QTAILQ_EMPTY(&spapr->pending_events); 1909fd38804bSDaniel Henrique Barboza } 1910fd38804bSDaniel Henrique Barboza 1911fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_event_entry = { 1912fd38804bSDaniel Henrique Barboza .name = "spapr_event_log_entry", 1913fd38804bSDaniel Henrique Barboza .version_id = 1, 1914fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1915fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 19165341258eSDavid Gibson VMSTATE_UINT32(summary, sPAPREventLogEntry), 19175341258eSDavid Gibson VMSTATE_UINT32(extended_length, sPAPREventLogEntry), 1918fd38804bSDaniel Henrique Barboza VMSTATE_VBUFFER_ALLOC_UINT32(extended_log, sPAPREventLogEntry, 0, 19195341258eSDavid Gibson NULL, extended_length), 1920fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1921fd38804bSDaniel Henrique Barboza }, 1922fd38804bSDaniel Henrique Barboza }; 1923fd38804bSDaniel Henrique Barboza 1924fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_pending_events = { 1925fd38804bSDaniel Henrique Barboza .name = "spapr_pending_events", 1926fd38804bSDaniel Henrique Barboza .version_id = 1, 1927fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1928fd38804bSDaniel Henrique Barboza .needed = spapr_pending_events_needed, 1929fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 1930fd38804bSDaniel Henrique Barboza VMSTATE_QTAILQ_V(pending_events, sPAPRMachineState, 1, 1931fd38804bSDaniel Henrique Barboza vmstate_spapr_event_entry, sPAPREventLogEntry, next), 1932fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1933fd38804bSDaniel Henrique Barboza }, 1934fd38804bSDaniel Henrique Barboza }; 1935fd38804bSDaniel Henrique Barboza 193662ef3760SMichael Roth static bool spapr_ov5_cas_needed(void *opaque) 193762ef3760SMichael Roth { 193862ef3760SMichael Roth sPAPRMachineState *spapr = opaque; 193962ef3760SMichael Roth sPAPROptionVector *ov5_mask = spapr_ovec_new(); 194062ef3760SMichael Roth sPAPROptionVector *ov5_legacy = spapr_ovec_new(); 194162ef3760SMichael Roth sPAPROptionVector *ov5_removed = spapr_ovec_new(); 194262ef3760SMichael Roth bool cas_needed; 194362ef3760SMichael Roth 194462ef3760SMichael Roth /* Prior to the introduction of sPAPROptionVector, we had two option 194562ef3760SMichael Roth * vectors we dealt with: OV5_FORM1_AFFINITY, and OV5_DRCONF_MEMORY. 194662ef3760SMichael Roth * Both of these options encode machine topology into the device-tree 194762ef3760SMichael Roth * in such a way that the now-booted OS should still be able to interact 194862ef3760SMichael Roth * appropriately with QEMU regardless of what options were actually 194962ef3760SMichael Roth * negotiatied on the source side. 195062ef3760SMichael Roth * 195162ef3760SMichael Roth * As such, we can avoid migrating the CAS-negotiated options if these 195262ef3760SMichael Roth * are the only options available on the current machine/platform. 195362ef3760SMichael Roth * Since these are the only options available for pseries-2.7 and 195462ef3760SMichael Roth * earlier, this allows us to maintain old->new/new->old migration 195562ef3760SMichael Roth * compatibility. 195662ef3760SMichael Roth * 195762ef3760SMichael Roth * For QEMU 2.8+, there are additional CAS-negotiatable options available 195862ef3760SMichael Roth * via default pseries-2.8 machines and explicit command-line parameters. 195962ef3760SMichael Roth * Some of these options, like OV5_HP_EVT, *do* require QEMU to be aware 196062ef3760SMichael Roth * of the actual CAS-negotiated values to continue working properly. For 196162ef3760SMichael Roth * example, availability of memory unplug depends on knowing whether 196262ef3760SMichael Roth * OV5_HP_EVT was negotiated via CAS. 196362ef3760SMichael Roth * 196462ef3760SMichael Roth * Thus, for any cases where the set of available CAS-negotiatable 196562ef3760SMichael Roth * options extends beyond OV5_FORM1_AFFINITY and OV5_DRCONF_MEMORY, we 1966aef19c04SGreg Kurz * include the CAS-negotiated options in the migration stream, unless 1967aef19c04SGreg Kurz * if they affect boot time behaviour only. 196862ef3760SMichael Roth */ 196962ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_FORM1_AFFINITY); 197062ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_DRCONF_MEMORY); 1971aef19c04SGreg Kurz spapr_ovec_set(ov5_mask, OV5_DRMEM_V2); 197262ef3760SMichael Roth 197362ef3760SMichael Roth /* spapr_ovec_diff returns true if bits were removed. we avoid using 197462ef3760SMichael Roth * the mask itself since in the future it's possible "legacy" bits may be 197562ef3760SMichael Roth * removed via machine options, which could generate a false positive 197662ef3760SMichael Roth * that breaks migration. 197762ef3760SMichael Roth */ 197862ef3760SMichael Roth spapr_ovec_intersect(ov5_legacy, spapr->ov5, ov5_mask); 197962ef3760SMichael Roth cas_needed = spapr_ovec_diff(ov5_removed, spapr->ov5, ov5_legacy); 198062ef3760SMichael Roth 198162ef3760SMichael Roth spapr_ovec_cleanup(ov5_mask); 198262ef3760SMichael Roth spapr_ovec_cleanup(ov5_legacy); 198362ef3760SMichael Roth spapr_ovec_cleanup(ov5_removed); 198462ef3760SMichael Roth 198562ef3760SMichael Roth return cas_needed; 198662ef3760SMichael Roth } 198762ef3760SMichael Roth 198862ef3760SMichael Roth static const VMStateDescription vmstate_spapr_ov5_cas = { 198962ef3760SMichael Roth .name = "spapr_option_vector_ov5_cas", 199062ef3760SMichael Roth .version_id = 1, 199162ef3760SMichael Roth .minimum_version_id = 1, 199262ef3760SMichael Roth .needed = spapr_ov5_cas_needed, 199362ef3760SMichael Roth .fields = (VMStateField[]) { 199462ef3760SMichael Roth VMSTATE_STRUCT_POINTER_V(ov5_cas, sPAPRMachineState, 1, 199562ef3760SMichael Roth vmstate_spapr_ovec, sPAPROptionVector), 199662ef3760SMichael Roth VMSTATE_END_OF_LIST() 199762ef3760SMichael Roth }, 199862ef3760SMichael Roth }; 199962ef3760SMichael Roth 20009861bb3eSSuraj Jitindar Singh static bool spapr_patb_entry_needed(void *opaque) 20019861bb3eSSuraj Jitindar Singh { 20029861bb3eSSuraj Jitindar Singh sPAPRMachineState *spapr = opaque; 20039861bb3eSSuraj Jitindar Singh 20049861bb3eSSuraj Jitindar Singh return !!spapr->patb_entry; 20059861bb3eSSuraj Jitindar Singh } 20069861bb3eSSuraj Jitindar Singh 20079861bb3eSSuraj Jitindar Singh static const VMStateDescription vmstate_spapr_patb_entry = { 20089861bb3eSSuraj Jitindar Singh .name = "spapr_patb_entry", 20099861bb3eSSuraj Jitindar Singh .version_id = 1, 20109861bb3eSSuraj Jitindar Singh .minimum_version_id = 1, 20119861bb3eSSuraj Jitindar Singh .needed = spapr_patb_entry_needed, 20129861bb3eSSuraj Jitindar Singh .fields = (VMStateField[]) { 20139861bb3eSSuraj Jitindar Singh VMSTATE_UINT64(patb_entry, sPAPRMachineState), 20149861bb3eSSuraj Jitindar Singh VMSTATE_END_OF_LIST() 20159861bb3eSSuraj Jitindar Singh }, 20169861bb3eSSuraj Jitindar Singh }; 20179861bb3eSSuraj Jitindar Singh 201882cffa2eSCédric Le Goater static bool spapr_irq_map_needed(void *opaque) 201982cffa2eSCédric Le Goater { 202082cffa2eSCédric Le Goater sPAPRMachineState *spapr = opaque; 202182cffa2eSCédric Le Goater 202282cffa2eSCédric Le Goater return spapr->irq_map && !bitmap_empty(spapr->irq_map, spapr->irq_map_nr); 202382cffa2eSCédric Le Goater } 202482cffa2eSCédric Le Goater 202582cffa2eSCédric Le Goater static const VMStateDescription vmstate_spapr_irq_map = { 202682cffa2eSCédric Le Goater .name = "spapr_irq_map", 202782cffa2eSCédric Le Goater .version_id = 1, 202882cffa2eSCédric Le Goater .minimum_version_id = 1, 202982cffa2eSCédric Le Goater .needed = spapr_irq_map_needed, 203082cffa2eSCédric Le Goater .fields = (VMStateField[]) { 203182cffa2eSCédric Le Goater VMSTATE_BITMAP(irq_map, sPAPRMachineState, 0, irq_map_nr), 203282cffa2eSCédric Le Goater VMSTATE_END_OF_LIST() 203382cffa2eSCédric Le Goater }, 203482cffa2eSCédric Le Goater }; 203582cffa2eSCédric Le Goater 2036fea35ca4SAlexey Kardashevskiy static bool spapr_dtb_needed(void *opaque) 2037fea35ca4SAlexey Kardashevskiy { 2038fea35ca4SAlexey Kardashevskiy sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(opaque); 2039fea35ca4SAlexey Kardashevskiy 2040fea35ca4SAlexey Kardashevskiy return smc->update_dt_enabled; 2041fea35ca4SAlexey Kardashevskiy } 2042fea35ca4SAlexey Kardashevskiy 2043fea35ca4SAlexey Kardashevskiy static int spapr_dtb_pre_load(void *opaque) 2044fea35ca4SAlexey Kardashevskiy { 2045fea35ca4SAlexey Kardashevskiy sPAPRMachineState *spapr = (sPAPRMachineState *)opaque; 2046fea35ca4SAlexey Kardashevskiy 2047fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob); 2048fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = NULL; 2049fea35ca4SAlexey Kardashevskiy spapr->fdt_size = 0; 2050fea35ca4SAlexey Kardashevskiy 2051fea35ca4SAlexey Kardashevskiy return 0; 2052fea35ca4SAlexey Kardashevskiy } 2053fea35ca4SAlexey Kardashevskiy 2054fea35ca4SAlexey Kardashevskiy static const VMStateDescription vmstate_spapr_dtb = { 2055fea35ca4SAlexey Kardashevskiy .name = "spapr_dtb", 2056fea35ca4SAlexey Kardashevskiy .version_id = 1, 2057fea35ca4SAlexey Kardashevskiy .minimum_version_id = 1, 2058fea35ca4SAlexey Kardashevskiy .needed = spapr_dtb_needed, 2059fea35ca4SAlexey Kardashevskiy .pre_load = spapr_dtb_pre_load, 2060fea35ca4SAlexey Kardashevskiy .fields = (VMStateField[]) { 2061fea35ca4SAlexey Kardashevskiy VMSTATE_UINT32(fdt_initial_size, sPAPRMachineState), 2062fea35ca4SAlexey Kardashevskiy VMSTATE_UINT32(fdt_size, sPAPRMachineState), 2063fea35ca4SAlexey Kardashevskiy VMSTATE_VBUFFER_ALLOC_UINT32(fdt_blob, sPAPRMachineState, 0, NULL, 2064fea35ca4SAlexey Kardashevskiy fdt_size), 2065fea35ca4SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 2066fea35ca4SAlexey Kardashevskiy }, 2067fea35ca4SAlexey Kardashevskiy }; 2068fea35ca4SAlexey Kardashevskiy 20694be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = { 20704be21d56SDavid Gibson .name = "spapr", 2071880ae7deSDavid Gibson .version_id = 3, 20724be21d56SDavid Gibson .minimum_version_id = 1, 20734e5fe368SSuraj Jitindar Singh .pre_load = spapr_pre_load, 2074880ae7deSDavid Gibson .post_load = spapr_post_load, 20754e5fe368SSuraj Jitindar Singh .pre_save = spapr_pre_save, 20764be21d56SDavid Gibson .fields = (VMStateField[]) { 2077880ae7deSDavid Gibson /* used to be @next_irq */ 2078880ae7deSDavid Gibson VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4), 20794be21d56SDavid Gibson 20804be21d56SDavid Gibson /* RTC offset */ 208128e02042SDavid Gibson VMSTATE_UINT64_TEST(rtc_offset, sPAPRMachineState, version_before_3), 2082880ae7deSDavid Gibson 208328e02042SDavid Gibson VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2), 20844be21d56SDavid Gibson VMSTATE_END_OF_LIST() 20854be21d56SDavid Gibson }, 208662ef3760SMichael Roth .subsections = (const VMStateDescription*[]) { 208762ef3760SMichael Roth &vmstate_spapr_ov5_cas, 20889861bb3eSSuraj Jitindar Singh &vmstate_spapr_patb_entry, 2089fd38804bSDaniel Henrique Barboza &vmstate_spapr_pending_events, 20904e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_htm, 20914e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_vsx, 20924e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_dfp, 20938f38eaf8SSuraj Jitindar Singh &vmstate_spapr_cap_cfpc, 209409114fd8SSuraj Jitindar Singh &vmstate_spapr_cap_sbbc, 20954be8d4e7SSuraj Jitindar Singh &vmstate_spapr_cap_ibs, 209682cffa2eSCédric Le Goater &vmstate_spapr_irq_map, 2097b9a477b7SSuraj Jitindar Singh &vmstate_spapr_cap_nested_kvm_hv, 2098fea35ca4SAlexey Kardashevskiy &vmstate_spapr_dtb, 2099c982f5cfSSuraj Jitindar Singh &vmstate_spapr_cap_large_decr, 21008ff43ee4SSuraj Jitindar Singh &vmstate_spapr_cap_ccf_assist, 210162ef3760SMichael Roth NULL 210262ef3760SMichael Roth } 21034be21d56SDavid Gibson }; 21044be21d56SDavid Gibson 21054be21d56SDavid Gibson static int htab_save_setup(QEMUFile *f, void *opaque) 21064be21d56SDavid Gibson { 210728e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 21084be21d56SDavid Gibson 21094be21d56SDavid Gibson /* "Iteration" header */ 21103a384297SBharata B Rao if (!spapr->htab_shift) { 21113a384297SBharata B Rao qemu_put_be32(f, -1); 21123a384297SBharata B Rao } else { 21134be21d56SDavid Gibson qemu_put_be32(f, spapr->htab_shift); 21143a384297SBharata B Rao } 21154be21d56SDavid Gibson 2116e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 2117e68cb8b4SAlexey Kardashevskiy spapr->htab_save_index = 0; 2118e68cb8b4SAlexey Kardashevskiy spapr->htab_first_pass = true; 2119e68cb8b4SAlexey Kardashevskiy } else { 21203a384297SBharata B Rao if (spapr->htab_shift) { 2121e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 21224be21d56SDavid Gibson } 21233a384297SBharata B Rao } 21244be21d56SDavid Gibson 2125e68cb8b4SAlexey Kardashevskiy 2126e68cb8b4SAlexey Kardashevskiy return 0; 2127e68cb8b4SAlexey Kardashevskiy } 21284be21d56SDavid Gibson 2129332f7721SGreg Kurz static void htab_save_chunk(QEMUFile *f, sPAPRMachineState *spapr, 2130332f7721SGreg Kurz int chunkstart, int n_valid, int n_invalid) 2131332f7721SGreg Kurz { 2132332f7721SGreg Kurz qemu_put_be32(f, chunkstart); 2133332f7721SGreg Kurz qemu_put_be16(f, n_valid); 2134332f7721SGreg Kurz qemu_put_be16(f, n_invalid); 2135332f7721SGreg Kurz qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 2136332f7721SGreg Kurz HASH_PTE_SIZE_64 * n_valid); 2137332f7721SGreg Kurz } 2138332f7721SGreg Kurz 2139332f7721SGreg Kurz static void htab_save_end_marker(QEMUFile *f) 2140332f7721SGreg Kurz { 2141332f7721SGreg Kurz qemu_put_be32(f, 0); 2142332f7721SGreg Kurz qemu_put_be16(f, 0); 2143332f7721SGreg Kurz qemu_put_be16(f, 0); 2144332f7721SGreg Kurz } 2145332f7721SGreg Kurz 214628e02042SDavid Gibson static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr, 21474be21d56SDavid Gibson int64_t max_ns) 21484be21d56SDavid Gibson { 2149378bc217SDavid Gibson bool has_timeout = max_ns != -1; 21504be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 21514be21d56SDavid Gibson int index = spapr->htab_save_index; 2152bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 21534be21d56SDavid Gibson 21544be21d56SDavid Gibson assert(spapr->htab_first_pass); 21554be21d56SDavid Gibson 21564be21d56SDavid Gibson do { 21574be21d56SDavid Gibson int chunkstart; 21584be21d56SDavid Gibson 21594be21d56SDavid Gibson /* Consume invalid HPTEs */ 21604be21d56SDavid Gibson while ((index < htabslots) 21614be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 21624be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 216324ec2863SMarc-André Lureau index++; 21644be21d56SDavid Gibson } 21654be21d56SDavid Gibson 21664be21d56SDavid Gibson /* Consume valid HPTEs */ 21674be21d56SDavid Gibson chunkstart = index; 2168338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 21694be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 21704be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 217124ec2863SMarc-André Lureau index++; 21724be21d56SDavid Gibson } 21734be21d56SDavid Gibson 21744be21d56SDavid Gibson if (index > chunkstart) { 21754be21d56SDavid Gibson int n_valid = index - chunkstart; 21764be21d56SDavid Gibson 2177332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, 0); 21784be21d56SDavid Gibson 2179378bc217SDavid Gibson if (has_timeout && 2180378bc217SDavid Gibson (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 21814be21d56SDavid Gibson break; 21824be21d56SDavid Gibson } 21834be21d56SDavid Gibson } 21844be21d56SDavid Gibson } while ((index < htabslots) && !qemu_file_rate_limit(f)); 21854be21d56SDavid Gibson 21864be21d56SDavid Gibson if (index >= htabslots) { 21874be21d56SDavid Gibson assert(index == htabslots); 21884be21d56SDavid Gibson index = 0; 21894be21d56SDavid Gibson spapr->htab_first_pass = false; 21904be21d56SDavid Gibson } 21914be21d56SDavid Gibson spapr->htab_save_index = index; 21924be21d56SDavid Gibson } 21934be21d56SDavid Gibson 219428e02042SDavid Gibson static int htab_save_later_pass(QEMUFile *f, sPAPRMachineState *spapr, 21954be21d56SDavid Gibson int64_t max_ns) 21964be21d56SDavid Gibson { 21974be21d56SDavid Gibson bool final = max_ns < 0; 21984be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 21994be21d56SDavid Gibson int examined = 0, sent = 0; 22004be21d56SDavid Gibson int index = spapr->htab_save_index; 2201bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 22024be21d56SDavid Gibson 22034be21d56SDavid Gibson assert(!spapr->htab_first_pass); 22044be21d56SDavid Gibson 22054be21d56SDavid Gibson do { 22064be21d56SDavid Gibson int chunkstart, invalidstart; 22074be21d56SDavid Gibson 22084be21d56SDavid Gibson /* Consume non-dirty HPTEs */ 22094be21d56SDavid Gibson while ((index < htabslots) 22104be21d56SDavid Gibson && !HPTE_DIRTY(HPTE(spapr->htab, index))) { 22114be21d56SDavid Gibson index++; 22124be21d56SDavid Gibson examined++; 22134be21d56SDavid Gibson } 22144be21d56SDavid Gibson 22154be21d56SDavid Gibson chunkstart = index; 22164be21d56SDavid Gibson /* Consume valid dirty HPTEs */ 2217338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 22184be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 22194be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 22204be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 22214be21d56SDavid Gibson index++; 22224be21d56SDavid Gibson examined++; 22234be21d56SDavid Gibson } 22244be21d56SDavid Gibson 22254be21d56SDavid Gibson invalidstart = index; 22264be21d56SDavid Gibson /* Consume invalid dirty HPTEs */ 2227338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - invalidstart < USHRT_MAX) 22284be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 22294be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 22304be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 22314be21d56SDavid Gibson index++; 22324be21d56SDavid Gibson examined++; 22334be21d56SDavid Gibson } 22344be21d56SDavid Gibson 22354be21d56SDavid Gibson if (index > chunkstart) { 22364be21d56SDavid Gibson int n_valid = invalidstart - chunkstart; 22374be21d56SDavid Gibson int n_invalid = index - invalidstart; 22384be21d56SDavid Gibson 2239332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, n_invalid); 22404be21d56SDavid Gibson sent += index - chunkstart; 22414be21d56SDavid Gibson 2242bc72ad67SAlex Bligh if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 22434be21d56SDavid Gibson break; 22444be21d56SDavid Gibson } 22454be21d56SDavid Gibson } 22464be21d56SDavid Gibson 22474be21d56SDavid Gibson if (examined >= htabslots) { 22484be21d56SDavid Gibson break; 22494be21d56SDavid Gibson } 22504be21d56SDavid Gibson 22514be21d56SDavid Gibson if (index >= htabslots) { 22524be21d56SDavid Gibson assert(index == htabslots); 22534be21d56SDavid Gibson index = 0; 22544be21d56SDavid Gibson } 22554be21d56SDavid Gibson } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final)); 22564be21d56SDavid Gibson 22574be21d56SDavid Gibson if (index >= htabslots) { 22584be21d56SDavid Gibson assert(index == htabslots); 22594be21d56SDavid Gibson index = 0; 22604be21d56SDavid Gibson } 22614be21d56SDavid Gibson 22624be21d56SDavid Gibson spapr->htab_save_index = index; 22634be21d56SDavid Gibson 2264e68cb8b4SAlexey Kardashevskiy return (examined >= htabslots) && (sent == 0) ? 1 : 0; 22654be21d56SDavid Gibson } 22664be21d56SDavid Gibson 2267e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS 5000000 /* 5 ms */ 2268e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE 2048 2269e68cb8b4SAlexey Kardashevskiy 22704be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque) 22714be21d56SDavid Gibson { 227228e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 2273715c5407SDavid Gibson int fd; 2274e68cb8b4SAlexey Kardashevskiy int rc = 0; 22754be21d56SDavid Gibson 22764be21d56SDavid Gibson /* Iteration header */ 22773a384297SBharata B Rao if (!spapr->htab_shift) { 22783a384297SBharata B Rao qemu_put_be32(f, -1); 2279e8cd4247SLaurent Vivier return 1; 22803a384297SBharata B Rao } else { 22814be21d56SDavid Gibson qemu_put_be32(f, 0); 22823a384297SBharata B Rao } 22834be21d56SDavid Gibson 2284e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2285e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2286e68cb8b4SAlexey Kardashevskiy 2287715c5407SDavid Gibson fd = get_htab_fd(spapr); 2288715c5407SDavid Gibson if (fd < 0) { 2289715c5407SDavid Gibson return fd; 229001a57972SSamuel Mendoza-Jonas } 229101a57972SSamuel Mendoza-Jonas 2292715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); 2293e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2294e68cb8b4SAlexey Kardashevskiy return rc; 2295e68cb8b4SAlexey Kardashevskiy } 2296e68cb8b4SAlexey Kardashevskiy } else if (spapr->htab_first_pass) { 22974be21d56SDavid Gibson htab_save_first_pass(f, spapr, MAX_ITERATION_NS); 22984be21d56SDavid Gibson } else { 2299e68cb8b4SAlexey Kardashevskiy rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS); 23004be21d56SDavid Gibson } 23014be21d56SDavid Gibson 2302332f7721SGreg Kurz htab_save_end_marker(f); 23034be21d56SDavid Gibson 2304e68cb8b4SAlexey Kardashevskiy return rc; 23054be21d56SDavid Gibson } 23064be21d56SDavid Gibson 23074be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque) 23084be21d56SDavid Gibson { 230928e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 2310715c5407SDavid Gibson int fd; 23114be21d56SDavid Gibson 23124be21d56SDavid Gibson /* Iteration header */ 23133a384297SBharata B Rao if (!spapr->htab_shift) { 23143a384297SBharata B Rao qemu_put_be32(f, -1); 23153a384297SBharata B Rao return 0; 23163a384297SBharata B Rao } else { 23174be21d56SDavid Gibson qemu_put_be32(f, 0); 23183a384297SBharata B Rao } 23194be21d56SDavid Gibson 2320e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2321e68cb8b4SAlexey Kardashevskiy int rc; 2322e68cb8b4SAlexey Kardashevskiy 2323e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2324e68cb8b4SAlexey Kardashevskiy 2325715c5407SDavid Gibson fd = get_htab_fd(spapr); 2326715c5407SDavid Gibson if (fd < 0) { 2327715c5407SDavid Gibson return fd; 232801a57972SSamuel Mendoza-Jonas } 232901a57972SSamuel Mendoza-Jonas 2330715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1); 2331e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2332e68cb8b4SAlexey Kardashevskiy return rc; 2333e68cb8b4SAlexey Kardashevskiy } 2334e68cb8b4SAlexey Kardashevskiy } else { 2335378bc217SDavid Gibson if (spapr->htab_first_pass) { 2336378bc217SDavid Gibson htab_save_first_pass(f, spapr, -1); 2337378bc217SDavid Gibson } 23384be21d56SDavid Gibson htab_save_later_pass(f, spapr, -1); 2339e68cb8b4SAlexey Kardashevskiy } 23404be21d56SDavid Gibson 23414be21d56SDavid Gibson /* End marker */ 2342332f7721SGreg Kurz htab_save_end_marker(f); 23434be21d56SDavid Gibson 23444be21d56SDavid Gibson return 0; 23454be21d56SDavid Gibson } 23464be21d56SDavid Gibson 23474be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id) 23484be21d56SDavid Gibson { 234928e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 23504be21d56SDavid Gibson uint32_t section_hdr; 2351e68cb8b4SAlexey Kardashevskiy int fd = -1; 235214b0d748SGreg Kurz Error *local_err = NULL; 23534be21d56SDavid Gibson 23544be21d56SDavid Gibson if (version_id < 1 || version_id > 1) { 235598a5d100SDavid Gibson error_report("htab_load() bad version"); 23564be21d56SDavid Gibson return -EINVAL; 23574be21d56SDavid Gibson } 23584be21d56SDavid Gibson 23594be21d56SDavid Gibson section_hdr = qemu_get_be32(f); 23604be21d56SDavid Gibson 23613a384297SBharata B Rao if (section_hdr == -1) { 23623a384297SBharata B Rao spapr_free_hpt(spapr); 23633a384297SBharata B Rao return 0; 23643a384297SBharata B Rao } 23653a384297SBharata B Rao 23664be21d56SDavid Gibson if (section_hdr) { 2367c5f54f3eSDavid Gibson /* First section gives the htab size */ 2368c5f54f3eSDavid Gibson spapr_reallocate_hpt(spapr, section_hdr, &local_err); 2369c5f54f3eSDavid Gibson if (local_err) { 2370c5f54f3eSDavid Gibson error_report_err(local_err); 23714be21d56SDavid Gibson return -EINVAL; 23724be21d56SDavid Gibson } 23734be21d56SDavid Gibson return 0; 23744be21d56SDavid Gibson } 23754be21d56SDavid Gibson 2376e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2377e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2378e68cb8b4SAlexey Kardashevskiy 237914b0d748SGreg Kurz fd = kvmppc_get_htab_fd(true, 0, &local_err); 2380e68cb8b4SAlexey Kardashevskiy if (fd < 0) { 238114b0d748SGreg Kurz error_report_err(local_err); 238282be8e73SGreg Kurz return fd; 2383e68cb8b4SAlexey Kardashevskiy } 2384e68cb8b4SAlexey Kardashevskiy } 2385e68cb8b4SAlexey Kardashevskiy 23864be21d56SDavid Gibson while (true) { 23874be21d56SDavid Gibson uint32_t index; 23884be21d56SDavid Gibson uint16_t n_valid, n_invalid; 23894be21d56SDavid Gibson 23904be21d56SDavid Gibson index = qemu_get_be32(f); 23914be21d56SDavid Gibson n_valid = qemu_get_be16(f); 23924be21d56SDavid Gibson n_invalid = qemu_get_be16(f); 23934be21d56SDavid Gibson 23944be21d56SDavid Gibson if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) { 23954be21d56SDavid Gibson /* End of Stream */ 23964be21d56SDavid Gibson break; 23974be21d56SDavid Gibson } 23984be21d56SDavid Gibson 2399e68cb8b4SAlexey Kardashevskiy if ((index + n_valid + n_invalid) > 24004be21d56SDavid Gibson (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) { 24014be21d56SDavid Gibson /* Bad index in stream */ 240298a5d100SDavid Gibson error_report( 240398a5d100SDavid Gibson "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)", 240498a5d100SDavid Gibson index, n_valid, n_invalid, spapr->htab_shift); 24054be21d56SDavid Gibson return -EINVAL; 24064be21d56SDavid Gibson } 24074be21d56SDavid Gibson 2408e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 24094be21d56SDavid Gibson if (n_valid) { 24104be21d56SDavid Gibson qemu_get_buffer(f, HPTE(spapr->htab, index), 24114be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 24124be21d56SDavid Gibson } 24134be21d56SDavid Gibson if (n_invalid) { 24144be21d56SDavid Gibson memset(HPTE(spapr->htab, index + n_valid), 0, 24154be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_invalid); 24164be21d56SDavid Gibson } 2417e68cb8b4SAlexey Kardashevskiy } else { 2418e68cb8b4SAlexey Kardashevskiy int rc; 2419e68cb8b4SAlexey Kardashevskiy 2420e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2421e68cb8b4SAlexey Kardashevskiy 2422e68cb8b4SAlexey Kardashevskiy rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid); 2423e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2424e68cb8b4SAlexey Kardashevskiy return rc; 2425e68cb8b4SAlexey Kardashevskiy } 2426e68cb8b4SAlexey Kardashevskiy } 2427e68cb8b4SAlexey Kardashevskiy } 2428e68cb8b4SAlexey Kardashevskiy 2429e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2430e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2431e68cb8b4SAlexey Kardashevskiy close(fd); 24324be21d56SDavid Gibson } 24334be21d56SDavid Gibson 24344be21d56SDavid Gibson return 0; 24354be21d56SDavid Gibson } 24364be21d56SDavid Gibson 243770f794fcSJuan Quintela static void htab_save_cleanup(void *opaque) 2438c573fc03SThomas Huth { 2439c573fc03SThomas Huth sPAPRMachineState *spapr = opaque; 2440c573fc03SThomas Huth 2441c573fc03SThomas Huth close_htab_fd(spapr); 2442c573fc03SThomas Huth } 2443c573fc03SThomas Huth 24444be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = { 24459907e842SJuan Quintela .save_setup = htab_save_setup, 24464be21d56SDavid Gibson .save_live_iterate = htab_save_iterate, 2447a3e06c3dSDr. David Alan Gilbert .save_live_complete_precopy = htab_save_complete, 244870f794fcSJuan Quintela .save_cleanup = htab_save_cleanup, 24494be21d56SDavid Gibson .load_state = htab_load, 24504be21d56SDavid Gibson }; 24514be21d56SDavid Gibson 24525b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device, 24535b2128d2SAlexander Graf Error **errp) 24545b2128d2SAlexander Graf { 2455c86c1affSDaniel Henrique Barboza MachineState *machine = MACHINE(opaque); 24565b2128d2SAlexander Graf machine->boot_order = g_strdup(boot_device); 24575b2128d2SAlexander Graf } 24585b2128d2SAlexander Graf 2459224245bfSDavid Gibson static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr) 2460224245bfSDavid Gibson { 2461224245bfSDavid Gibson MachineState *machine = MACHINE(spapr); 2462224245bfSDavid Gibson uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 2463e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 2464224245bfSDavid Gibson int i; 2465224245bfSDavid Gibson 2466224245bfSDavid Gibson for (i = 0; i < nr_lmbs; i++) { 2467224245bfSDavid Gibson uint64_t addr; 2468224245bfSDavid Gibson 2469b0c14ec4SDavid Hildenbrand addr = i * lmb_size + machine->device_memory->base; 24706caf3ac6SDavid Gibson spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_LMB, 2471224245bfSDavid Gibson addr / lmb_size); 2472224245bfSDavid Gibson } 2473224245bfSDavid Gibson } 2474224245bfSDavid Gibson 2475224245bfSDavid Gibson /* 2476224245bfSDavid Gibson * If RAM size, maxmem size and individual node mem sizes aren't aligned 2477224245bfSDavid Gibson * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest 2478224245bfSDavid Gibson * since we can't support such unaligned sizes with DRCONF_MEMORY. 2479224245bfSDavid Gibson */ 24807c150d6fSDavid Gibson static void spapr_validate_node_memory(MachineState *machine, Error **errp) 2481224245bfSDavid Gibson { 2482224245bfSDavid Gibson int i; 2483224245bfSDavid Gibson 24847c150d6fSDavid Gibson if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) { 24857c150d6fSDavid Gibson error_setg(errp, "Memory size 0x" RAM_ADDR_FMT 2486ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 24877c150d6fSDavid Gibson machine->ram_size, 2488d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 24897c150d6fSDavid Gibson return; 24907c150d6fSDavid Gibson } 24917c150d6fSDavid Gibson 24927c150d6fSDavid Gibson if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) { 24937c150d6fSDavid Gibson error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT 2494ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 24957c150d6fSDavid Gibson machine->ram_size, 2496d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 24977c150d6fSDavid Gibson return; 2498224245bfSDavid Gibson } 2499224245bfSDavid Gibson 2500224245bfSDavid Gibson for (i = 0; i < nb_numa_nodes; i++) { 2501224245bfSDavid Gibson if (numa_info[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) { 25027c150d6fSDavid Gibson error_setg(errp, 25037c150d6fSDavid Gibson "Node %d memory size 0x%" PRIx64 2504ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 25057c150d6fSDavid Gibson i, numa_info[i].node_mem, 2506d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 25077c150d6fSDavid Gibson return; 2508224245bfSDavid Gibson } 2509224245bfSDavid Gibson } 2510224245bfSDavid Gibson } 2511224245bfSDavid Gibson 2512535455fdSIgor Mammedov /* find cpu slot in machine->possible_cpus by core_id */ 2513535455fdSIgor Mammedov static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx) 2514535455fdSIgor Mammedov { 2515535455fdSIgor Mammedov int index = id / smp_threads; 2516535455fdSIgor Mammedov 2517535455fdSIgor Mammedov if (index >= ms->possible_cpus->len) { 2518535455fdSIgor Mammedov return NULL; 2519535455fdSIgor Mammedov } 2520535455fdSIgor Mammedov if (idx) { 2521535455fdSIgor Mammedov *idx = index; 2522535455fdSIgor Mammedov } 2523535455fdSIgor Mammedov return &ms->possible_cpus->cpus[index]; 2524535455fdSIgor Mammedov } 2525535455fdSIgor Mammedov 2526fa98fbfcSSam Bobroff static void spapr_set_vsmt_mode(sPAPRMachineState *spapr, Error **errp) 2527fa98fbfcSSam Bobroff { 2528fa98fbfcSSam Bobroff Error *local_err = NULL; 2529fa98fbfcSSam Bobroff bool vsmt_user = !!spapr->vsmt; 2530fa98fbfcSSam Bobroff int kvm_smt = kvmppc_smt_threads(); 2531fa98fbfcSSam Bobroff int ret; 2532fa98fbfcSSam Bobroff 2533fa98fbfcSSam Bobroff if (!kvm_enabled() && (smp_threads > 1)) { 2534fa98fbfcSSam Bobroff error_setg(&local_err, "TCG cannot support more than 1 thread/core " 2535fa98fbfcSSam Bobroff "on a pseries machine"); 2536fa98fbfcSSam Bobroff goto out; 2537fa98fbfcSSam Bobroff } 2538fa98fbfcSSam Bobroff if (!is_power_of_2(smp_threads)) { 2539fa98fbfcSSam Bobroff error_setg(&local_err, "Cannot support %d threads/core on a pseries " 2540fa98fbfcSSam Bobroff "machine because it must be a power of 2", smp_threads); 2541fa98fbfcSSam Bobroff goto out; 2542fa98fbfcSSam Bobroff } 2543fa98fbfcSSam Bobroff 2544fa98fbfcSSam Bobroff /* Detemine the VSMT mode to use: */ 2545fa98fbfcSSam Bobroff if (vsmt_user) { 2546fa98fbfcSSam Bobroff if (spapr->vsmt < smp_threads) { 2547fa98fbfcSSam Bobroff error_setg(&local_err, "Cannot support VSMT mode %d" 2548fa98fbfcSSam Bobroff " because it must be >= threads/core (%d)", 2549fa98fbfcSSam Bobroff spapr->vsmt, smp_threads); 2550fa98fbfcSSam Bobroff goto out; 2551fa98fbfcSSam Bobroff } 2552fa98fbfcSSam Bobroff /* In this case, spapr->vsmt has been set by the command line */ 2553fa98fbfcSSam Bobroff } else { 25548904e5a7SDavid Gibson /* 25558904e5a7SDavid Gibson * Default VSMT value is tricky, because we need it to be as 25568904e5a7SDavid Gibson * consistent as possible (for migration), but this requires 25578904e5a7SDavid Gibson * changing it for at least some existing cases. We pick 8 as 25588904e5a7SDavid Gibson * the value that we'd get with KVM on POWER8, the 25598904e5a7SDavid Gibson * overwhelmingly common case in production systems. 25608904e5a7SDavid Gibson */ 25614ad64cbdSLaurent Vivier spapr->vsmt = MAX(8, smp_threads); 2562fa98fbfcSSam Bobroff } 2563fa98fbfcSSam Bobroff 2564fa98fbfcSSam Bobroff /* KVM: If necessary, set the SMT mode: */ 2565fa98fbfcSSam Bobroff if (kvm_enabled() && (spapr->vsmt != kvm_smt)) { 2566fa98fbfcSSam Bobroff ret = kvmppc_set_smt_threads(spapr->vsmt); 2567fa98fbfcSSam Bobroff if (ret) { 25681f20f2e0SDavid Gibson /* Looks like KVM isn't able to change VSMT mode */ 2569fa98fbfcSSam Bobroff error_setg(&local_err, 2570fa98fbfcSSam Bobroff "Failed to set KVM's VSMT mode to %d (errno %d)", 2571fa98fbfcSSam Bobroff spapr->vsmt, ret); 25721f20f2e0SDavid Gibson /* We can live with that if the default one is big enough 25731f20f2e0SDavid Gibson * for the number of threads, and a submultiple of the one 25741f20f2e0SDavid Gibson * we want. In this case we'll waste some vcpu ids, but 25751f20f2e0SDavid Gibson * behaviour will be correct */ 25761f20f2e0SDavid Gibson if ((kvm_smt >= smp_threads) && ((spapr->vsmt % kvm_smt) == 0)) { 25771f20f2e0SDavid Gibson warn_report_err(local_err); 25781f20f2e0SDavid Gibson local_err = NULL; 25791f20f2e0SDavid Gibson goto out; 25801f20f2e0SDavid Gibson } else { 2581fa98fbfcSSam Bobroff if (!vsmt_user) { 25821f20f2e0SDavid Gibson error_append_hint(&local_err, 25831f20f2e0SDavid Gibson "On PPC, a VM with %d threads/core" 25841f20f2e0SDavid Gibson " on a host with %d threads/core" 25851f20f2e0SDavid Gibson " requires the use of VSMT mode %d.\n", 2586fa98fbfcSSam Bobroff smp_threads, kvm_smt, spapr->vsmt); 2587fa98fbfcSSam Bobroff } 2588fa98fbfcSSam Bobroff kvmppc_hint_smt_possible(&local_err); 2589fa98fbfcSSam Bobroff goto out; 2590fa98fbfcSSam Bobroff } 2591fa98fbfcSSam Bobroff } 25921f20f2e0SDavid Gibson } 2593fa98fbfcSSam Bobroff /* else TCG: nothing to do currently */ 2594fa98fbfcSSam Bobroff out: 2595fa98fbfcSSam Bobroff error_propagate(errp, local_err); 2596fa98fbfcSSam Bobroff } 2597fa98fbfcSSam Bobroff 25981a5008fcSGreg Kurz static void spapr_init_cpus(sPAPRMachineState *spapr) 25991a5008fcSGreg Kurz { 26001a5008fcSGreg Kurz MachineState *machine = MACHINE(spapr); 26011a5008fcSGreg Kurz MachineClass *mc = MACHINE_GET_CLASS(machine); 26021a5008fcSGreg Kurz sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 26031a5008fcSGreg Kurz const char *type = spapr_get_cpu_core_type(machine->cpu_type); 26041a5008fcSGreg Kurz const CPUArchIdList *possible_cpus; 26051a5008fcSGreg Kurz int boot_cores_nr = smp_cpus / smp_threads; 26061a5008fcSGreg Kurz int i; 26071a5008fcSGreg Kurz 26081a5008fcSGreg Kurz possible_cpus = mc->possible_cpu_arch_ids(machine); 26091a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 26101a5008fcSGreg Kurz if (smp_cpus % smp_threads) { 26111a5008fcSGreg Kurz error_report("smp_cpus (%u) must be multiple of threads (%u)", 26121a5008fcSGreg Kurz smp_cpus, smp_threads); 26131a5008fcSGreg Kurz exit(1); 26141a5008fcSGreg Kurz } 26151a5008fcSGreg Kurz if (max_cpus % smp_threads) { 26161a5008fcSGreg Kurz error_report("max_cpus (%u) must be multiple of threads (%u)", 26171a5008fcSGreg Kurz max_cpus, smp_threads); 26181a5008fcSGreg Kurz exit(1); 26191a5008fcSGreg Kurz } 26201a5008fcSGreg Kurz } else { 26211a5008fcSGreg Kurz if (max_cpus != smp_cpus) { 26221a5008fcSGreg Kurz error_report("This machine version does not support CPU hotplug"); 26231a5008fcSGreg Kurz exit(1); 26241a5008fcSGreg Kurz } 26251a5008fcSGreg Kurz boot_cores_nr = possible_cpus->len; 26261a5008fcSGreg Kurz } 26271a5008fcSGreg Kurz 26281a5008fcSGreg Kurz if (smc->pre_2_10_has_unused_icps) { 26291a5008fcSGreg Kurz int i; 26301a5008fcSGreg Kurz 26311a518e76SCédric Le Goater for (i = 0; i < spapr_max_server_number(spapr); i++) { 26321a5008fcSGreg Kurz /* Dummy entries get deregistered when real ICPState objects 26331a5008fcSGreg Kurz * are registered during CPU core hotplug. 26341a5008fcSGreg Kurz */ 26351a5008fcSGreg Kurz pre_2_10_vmstate_register_dummy_icp(i); 26361a5008fcSGreg Kurz } 26371a5008fcSGreg Kurz } 26381a5008fcSGreg Kurz 26391a5008fcSGreg Kurz for (i = 0; i < possible_cpus->len; i++) { 26401a5008fcSGreg Kurz int core_id = i * smp_threads; 26411a5008fcSGreg Kurz 26421a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 26431a5008fcSGreg Kurz spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU, 26441a5008fcSGreg Kurz spapr_vcpu_id(spapr, core_id)); 26451a5008fcSGreg Kurz } 26461a5008fcSGreg Kurz 26471a5008fcSGreg Kurz if (i < boot_cores_nr) { 26481a5008fcSGreg Kurz Object *core = object_new(type); 26491a5008fcSGreg Kurz int nr_threads = smp_threads; 26501a5008fcSGreg Kurz 26511a5008fcSGreg Kurz /* Handle the partially filled core for older machine types */ 26521a5008fcSGreg Kurz if ((i + 1) * smp_threads >= smp_cpus) { 26531a5008fcSGreg Kurz nr_threads = smp_cpus - i * smp_threads; 26541a5008fcSGreg Kurz } 26551a5008fcSGreg Kurz 26561a5008fcSGreg Kurz object_property_set_int(core, nr_threads, "nr-threads", 26571a5008fcSGreg Kurz &error_fatal); 26581a5008fcSGreg Kurz object_property_set_int(core, core_id, CPU_CORE_PROP_CORE_ID, 26591a5008fcSGreg Kurz &error_fatal); 26601a5008fcSGreg Kurz object_property_set_bool(core, true, "realized", &error_fatal); 2661ecda255eSSam Bobroff 2662ecda255eSSam Bobroff object_unref(core); 26631a5008fcSGreg Kurz } 26641a5008fcSGreg Kurz } 26651a5008fcSGreg Kurz } 26661a5008fcSGreg Kurz 2667999c9cafSGreg Kurz static PCIHostState *spapr_create_default_phb(void) 2668999c9cafSGreg Kurz { 2669999c9cafSGreg Kurz DeviceState *dev; 2670999c9cafSGreg Kurz 2671999c9cafSGreg Kurz dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE); 2672999c9cafSGreg Kurz qdev_prop_set_uint32(dev, "index", 0); 2673999c9cafSGreg Kurz qdev_init_nofail(dev); 2674999c9cafSGreg Kurz 2675999c9cafSGreg Kurz return PCI_HOST_BRIDGE(dev); 2676999c9cafSGreg Kurz } 2677999c9cafSGreg Kurz 267853018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */ 2679bcb5ce08SDavid Gibson static void spapr_machine_init(MachineState *machine) 268053018216SPaolo Bonzini { 268128e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 2682224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 26833ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 26843ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 268553018216SPaolo Bonzini PCIHostState *phb; 268653018216SPaolo Bonzini int i; 268753018216SPaolo Bonzini MemoryRegion *sysmem = get_system_memory(); 268853018216SPaolo Bonzini MemoryRegion *ram = g_new(MemoryRegion, 1); 2689c86c1affSDaniel Henrique Barboza hwaddr node0_size = spapr_node0_size(machine); 2690b7d1f77aSBenjamin Herrenschmidt long load_limit, fw_size; 269153018216SPaolo Bonzini char *filename; 269230f4b05bSDavid Gibson Error *resize_hpt_err = NULL; 269353018216SPaolo Bonzini 2694226419d6SMichael S. Tsirkin msi_nonbroken = true; 269553018216SPaolo Bonzini 269653018216SPaolo Bonzini QLIST_INIT(&spapr->phbs); 26970cffce56SDavid Gibson QTAILQ_INIT(&spapr->pending_dimm_unplugs); 269853018216SPaolo Bonzini 26999f6edd06SDavid Gibson /* Determine capabilities to run with */ 27009f6edd06SDavid Gibson spapr_caps_init(spapr); 27019f6edd06SDavid Gibson 270230f4b05bSDavid Gibson kvmppc_check_papr_resize_hpt(&resize_hpt_err); 270330f4b05bSDavid Gibson if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) { 270430f4b05bSDavid Gibson /* 270530f4b05bSDavid Gibson * If the user explicitly requested a mode we should either 270630f4b05bSDavid Gibson * supply it, or fail completely (which we do below). But if 270730f4b05bSDavid Gibson * it's not set explicitly, we reset our mode to something 270830f4b05bSDavid Gibson * that works 270930f4b05bSDavid Gibson */ 271030f4b05bSDavid Gibson if (resize_hpt_err) { 271130f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 271230f4b05bSDavid Gibson error_free(resize_hpt_err); 271330f4b05bSDavid Gibson resize_hpt_err = NULL; 271430f4b05bSDavid Gibson } else { 271530f4b05bSDavid Gibson spapr->resize_hpt = smc->resize_hpt_default; 271630f4b05bSDavid Gibson } 271730f4b05bSDavid Gibson } 271830f4b05bSDavid Gibson 271930f4b05bSDavid Gibson assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT); 272030f4b05bSDavid Gibson 272130f4b05bSDavid Gibson if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && resize_hpt_err) { 272230f4b05bSDavid Gibson /* 272330f4b05bSDavid Gibson * User requested HPT resize, but this host can't supply it. Bail out 272430f4b05bSDavid Gibson */ 272530f4b05bSDavid Gibson error_report_err(resize_hpt_err); 272630f4b05bSDavid Gibson exit(1); 272730f4b05bSDavid Gibson } 272830f4b05bSDavid Gibson 2729c4177479SAlexey Kardashevskiy spapr->rma_size = node0_size; 273053018216SPaolo Bonzini 273153018216SPaolo Bonzini /* With KVM, we don't actually know whether KVM supports an 273253018216SPaolo Bonzini * unbounded RMA (PR KVM) or is limited by the hash table size 273353018216SPaolo Bonzini * (HV KVM using VRMA), so we always assume the latter 273453018216SPaolo Bonzini * 273553018216SPaolo Bonzini * In that case, we also limit the initial allocations for RTAS 273653018216SPaolo Bonzini * etc... to 256M since we have no way to know what the VRMA size 273753018216SPaolo Bonzini * is going to be as it depends on the size of the hash table 2738090052aaSDavid Gibson * which isn't determined yet. 273953018216SPaolo Bonzini */ 274053018216SPaolo Bonzini if (kvm_enabled()) { 274153018216SPaolo Bonzini spapr->vrma_adjust = 1; 274253018216SPaolo Bonzini spapr->rma_size = MIN(spapr->rma_size, 0x10000000); 274353018216SPaolo Bonzini } 2744912acdf4SBenjamin Herrenschmidt 2745090052aaSDavid Gibson /* Actually we don't support unbounded RMA anymore since we added 2746090052aaSDavid Gibson * proper emulation of HV mode. The max we can get is 16G which 2747090052aaSDavid Gibson * also happens to be what we configure for PAPR mode so make sure 2748090052aaSDavid Gibson * we don't do anything bigger than that 2749912acdf4SBenjamin Herrenschmidt */ 2750912acdf4SBenjamin Herrenschmidt spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull); 275153018216SPaolo Bonzini 2752c4177479SAlexey Kardashevskiy if (spapr->rma_size > node0_size) { 2753d54e4d76SDavid Gibson error_report("Numa node 0 has to span the RMA (%#08"HWADDR_PRIx")", 2754c4177479SAlexey Kardashevskiy spapr->rma_size); 2755c4177479SAlexey Kardashevskiy exit(1); 2756c4177479SAlexey Kardashevskiy } 2757c4177479SAlexey Kardashevskiy 2758b7d1f77aSBenjamin Herrenschmidt /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */ 2759b7d1f77aSBenjamin Herrenschmidt load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; 276053018216SPaolo Bonzini 2761482969d6SCédric Le Goater /* 2762482969d6SCédric Le Goater * VSMT must be set in order to be able to compute VCPU ids, ie to 27631a518e76SCédric Le Goater * call spapr_max_server_number() or spapr_vcpu_id(). 2764482969d6SCédric Le Goater */ 2765482969d6SCédric Le Goater spapr_set_vsmt_mode(spapr, &error_fatal); 2766482969d6SCédric Le Goater 27677b565160SDavid Gibson /* Set up Interrupt Controller before we create the VCPUs */ 2768fab397d8SCédric Le Goater spapr_irq_init(spapr, &error_fatal); 27697b565160SDavid Gibson 2770dc1b5eeeSGreg Kurz /* Set up containers for ibm,client-architecture-support negotiated options 2771dc1b5eeeSGreg Kurz */ 2772facdb8b6SMichael Roth spapr->ov5 = spapr_ovec_new(); 2773facdb8b6SMichael Roth spapr->ov5_cas = spapr_ovec_new(); 2774facdb8b6SMichael Roth 2775224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2776facdb8b6SMichael Roth spapr_ovec_set(spapr->ov5, OV5_DRCONF_MEMORY); 27777c150d6fSDavid Gibson spapr_validate_node_memory(machine, &error_fatal); 2778224245bfSDavid Gibson } 2779224245bfSDavid Gibson 2780417ece33SMichael Roth spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY); 2781417ece33SMichael Roth 2782ffbb1705SMichael Roth /* advertise support for dedicated HP event source to guests */ 2783ffbb1705SMichael Roth if (spapr->use_hotplug_event_source) { 2784ffbb1705SMichael Roth spapr_ovec_set(spapr->ov5, OV5_HP_EVT); 2785ffbb1705SMichael Roth } 2786ffbb1705SMichael Roth 27872772cf6bSDavid Gibson /* advertise support for HPT resizing */ 27882772cf6bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { 27892772cf6bSDavid Gibson spapr_ovec_set(spapr->ov5, OV5_HPT_RESIZE); 27902772cf6bSDavid Gibson } 27912772cf6bSDavid Gibson 2792a324d6f1SBharata B Rao /* advertise support for ibm,dyamic-memory-v2 */ 2793a324d6f1SBharata B Rao spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2); 2794a324d6f1SBharata B Rao 2795db592b5bSCédric Le Goater /* advertise XIVE on POWER9 machines */ 279613db0cd9SCédric Le Goater if (spapr->irq->ov5 & (SPAPR_OV5_XIVE_EXPLOIT | SPAPR_OV5_XIVE_BOTH)) { 2797db592b5bSCédric Le Goater if (ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 2798db592b5bSCédric Le Goater 0, spapr->max_compat_pvr)) { 2799db592b5bSCédric Le Goater spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT); 280013db0cd9SCédric Le Goater } else if (spapr->irq->ov5 & SPAPR_OV5_XIVE_EXPLOIT) { 2801db592b5bSCédric Le Goater error_report("XIVE-only machines require a POWER9 CPU"); 2802db592b5bSCédric Le Goater exit(1); 2803db592b5bSCédric Le Goater } 2804db592b5bSCédric Le Goater } 2805db592b5bSCédric Le Goater 280653018216SPaolo Bonzini /* init CPUs */ 28070c86d0fdSDavid Gibson spapr_init_cpus(spapr); 280853018216SPaolo Bonzini 28090550b120SGreg Kurz if ((!kvm_enabled() || kvmppc_has_cap_mmu_radix()) && 2810ad99d04cSDavid Gibson ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, 28110550b120SGreg Kurz spapr->max_compat_pvr)) { 28120550b120SGreg Kurz /* KVM and TCG always allow GTSE with radix... */ 28130550b120SGreg Kurz spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE); 28140550b120SGreg Kurz } 28150550b120SGreg Kurz /* ... but not with hash (currently). */ 28160550b120SGreg Kurz 2817026bfd89SDavid Gibson if (kvm_enabled()) { 2818026bfd89SDavid Gibson /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ 2819026bfd89SDavid Gibson kvmppc_enable_logical_ci_hcalls(); 2820ef9971ddSAlexey Kardashevskiy kvmppc_enable_set_mode_hcall(); 28215145ad4fSNathan Whitehorn 28225145ad4fSNathan Whitehorn /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */ 28235145ad4fSNathan Whitehorn kvmppc_enable_clear_ref_mod_hcalls(); 2824026bfd89SDavid Gibson } 2825026bfd89SDavid Gibson 282653018216SPaolo Bonzini /* allocate RAM */ 2827f92f5da1SAlexey Kardashevskiy memory_region_allocate_system_memory(ram, NULL, "ppc_spapr.ram", 2828fb164994SDavid Gibson machine->ram_size); 2829f92f5da1SAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, ram); 283053018216SPaolo Bonzini 2831b0c14ec4SDavid Hildenbrand /* always allocate the device memory information */ 2832b0c14ec4SDavid Hildenbrand machine->device_memory = g_malloc0(sizeof(*machine->device_memory)); 2833b0c14ec4SDavid Hildenbrand 28344a1c9cf0SBharata B Rao /* initialize hotplug memory address space */ 28354a1c9cf0SBharata B Rao if (machine->ram_size < machine->maxram_size) { 28360c9269a5SDavid Hildenbrand ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size; 283771c9a3ddSBharata B Rao /* 283871c9a3ddSBharata B Rao * Limit the number of hotpluggable memory slots to half the number 283971c9a3ddSBharata B Rao * slots that KVM supports, leaving the other half for PCI and other 284071c9a3ddSBharata B Rao * devices. However ensure that number of slots doesn't drop below 32. 284171c9a3ddSBharata B Rao */ 284271c9a3ddSBharata B Rao int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 : 284371c9a3ddSBharata B Rao SPAPR_MAX_RAM_SLOTS; 28444a1c9cf0SBharata B Rao 284571c9a3ddSBharata B Rao if (max_memslots < SPAPR_MAX_RAM_SLOTS) { 284671c9a3ddSBharata B Rao max_memslots = SPAPR_MAX_RAM_SLOTS; 284771c9a3ddSBharata B Rao } 284871c9a3ddSBharata B Rao if (machine->ram_slots > max_memslots) { 2849d54e4d76SDavid Gibson error_report("Specified number of memory slots %" 2850d54e4d76SDavid Gibson PRIu64" exceeds max supported %d", 285171c9a3ddSBharata B Rao machine->ram_slots, max_memslots); 2852d54e4d76SDavid Gibson exit(1); 28534a1c9cf0SBharata B Rao } 28544a1c9cf0SBharata B Rao 2855b0c14ec4SDavid Hildenbrand machine->device_memory->base = ROUND_UP(machine->ram_size, 28560c9269a5SDavid Hildenbrand SPAPR_DEVICE_MEM_ALIGN); 2857b0c14ec4SDavid Hildenbrand memory_region_init(&machine->device_memory->mr, OBJECT(spapr), 28580c9269a5SDavid Hildenbrand "device-memory", device_mem_size); 2859b0c14ec4SDavid Hildenbrand memory_region_add_subregion(sysmem, machine->device_memory->base, 2860b0c14ec4SDavid Hildenbrand &machine->device_memory->mr); 28614a1c9cf0SBharata B Rao } 28624a1c9cf0SBharata B Rao 2863224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2864224245bfSDavid Gibson spapr_create_lmb_dr_connectors(spapr); 2865224245bfSDavid Gibson } 2866224245bfSDavid Gibson 286753018216SPaolo Bonzini filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin"); 28684c56440dSStefan Weil if (!filename) { 2869730fce59SThomas Huth error_report("Could not find LPAR rtas '%s'", "spapr-rtas.bin"); 28704c56440dSStefan Weil exit(1); 28714c56440dSStefan Weil } 2872b7d1f77aSBenjamin Herrenschmidt spapr->rtas_size = get_image_size(filename); 28738afc22a2SZhou Jie if (spapr->rtas_size < 0) { 28748afc22a2SZhou Jie error_report("Could not get size of LPAR rtas '%s'", filename); 28758afc22a2SZhou Jie exit(1); 28768afc22a2SZhou Jie } 2877b7d1f77aSBenjamin Herrenschmidt spapr->rtas_blob = g_malloc(spapr->rtas_size); 2878b7d1f77aSBenjamin Herrenschmidt if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) { 2879730fce59SThomas Huth error_report("Could not load LPAR rtas '%s'", filename); 288053018216SPaolo Bonzini exit(1); 288153018216SPaolo Bonzini } 288253018216SPaolo Bonzini if (spapr->rtas_size > RTAS_MAX_SIZE) { 2883730fce59SThomas Huth error_report("RTAS too big ! 0x%zx bytes (max is 0x%x)", 28842f285bddSPeter Maydell (size_t)spapr->rtas_size, RTAS_MAX_SIZE); 288553018216SPaolo Bonzini exit(1); 288653018216SPaolo Bonzini } 288753018216SPaolo Bonzini g_free(filename); 288853018216SPaolo Bonzini 2889ffbb1705SMichael Roth /* Set up RTAS event infrastructure */ 289053018216SPaolo Bonzini spapr_events_init(spapr); 289153018216SPaolo Bonzini 289212f42174SDavid Gibson /* Set up the RTC RTAS interfaces */ 289328df36a1SDavid Gibson spapr_rtc_create(spapr); 289412f42174SDavid Gibson 289553018216SPaolo Bonzini /* Set up VIO bus */ 289653018216SPaolo Bonzini spapr->vio_bus = spapr_vio_bus_init(); 289753018216SPaolo Bonzini 2898b8846a4dSPeter Maydell for (i = 0; i < serial_max_hds(); i++) { 28999bca0edbSPeter Maydell if (serial_hd(i)) { 29009bca0edbSPeter Maydell spapr_vty_create(spapr->vio_bus, serial_hd(i)); 290153018216SPaolo Bonzini } 290253018216SPaolo Bonzini } 290353018216SPaolo Bonzini 290453018216SPaolo Bonzini /* We always have at least the nvram device on VIO */ 290553018216SPaolo Bonzini spapr_create_nvram(spapr); 290653018216SPaolo Bonzini 2907962b6c36SMichael Roth /* 2908962b6c36SMichael Roth * Setup hotplug / dynamic-reconfiguration connectors. top-level 2909962b6c36SMichael Roth * connectors (described in root DT node's "ibm,drc-types" property) 2910962b6c36SMichael Roth * are pre-initialized here. additional child connectors (such as 2911962b6c36SMichael Roth * connectors for a PHBs PCI slots) are added as needed during their 2912962b6c36SMichael Roth * parent's realization. 2913962b6c36SMichael Roth */ 2914962b6c36SMichael Roth if (smc->dr_phb_enabled) { 2915962b6c36SMichael Roth for (i = 0; i < SPAPR_MAX_PHBS; i++) { 2916962b6c36SMichael Roth spapr_dr_connector_new(OBJECT(machine), TYPE_SPAPR_DRC_PHB, i); 2917962b6c36SMichael Roth } 2918962b6c36SMichael Roth } 2919962b6c36SMichael Roth 292053018216SPaolo Bonzini /* Set up PCI */ 292153018216SPaolo Bonzini spapr_pci_rtas_init(); 292253018216SPaolo Bonzini 2923999c9cafSGreg Kurz phb = spapr_create_default_phb(); 292453018216SPaolo Bonzini 292553018216SPaolo Bonzini for (i = 0; i < nb_nics; i++) { 292653018216SPaolo Bonzini NICInfo *nd = &nd_table[i]; 292753018216SPaolo Bonzini 292853018216SPaolo Bonzini if (!nd->model) { 29293c3a4e7aSThomas Huth nd->model = g_strdup("spapr-vlan"); 293053018216SPaolo Bonzini } 293153018216SPaolo Bonzini 29323c3a4e7aSThomas Huth if (g_str_equal(nd->model, "spapr-vlan") || 29333c3a4e7aSThomas Huth g_str_equal(nd->model, "ibmveth")) { 293453018216SPaolo Bonzini spapr_vlan_create(spapr->vio_bus, nd); 293553018216SPaolo Bonzini } else { 293629b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL); 293753018216SPaolo Bonzini } 293853018216SPaolo Bonzini } 293953018216SPaolo Bonzini 294053018216SPaolo Bonzini for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { 294153018216SPaolo Bonzini spapr_vscsi_create(spapr->vio_bus); 294253018216SPaolo Bonzini } 294353018216SPaolo Bonzini 294453018216SPaolo Bonzini /* Graphics */ 294514c6a894SDavid Gibson if (spapr_vga_init(phb->bus, &error_fatal)) { 294653018216SPaolo Bonzini spapr->has_graphics = true; 2947c6e76503SPaolo Bonzini machine->usb |= defaults_enabled() && !machine->usb_disabled; 294853018216SPaolo Bonzini } 294953018216SPaolo Bonzini 29504ee9ced9SMarcel Apfelbaum if (machine->usb) { 295157040d45SThomas Huth if (smc->use_ohci_by_default) { 295253018216SPaolo Bonzini pci_create_simple(phb->bus, -1, "pci-ohci"); 295357040d45SThomas Huth } else { 295457040d45SThomas Huth pci_create_simple(phb->bus, -1, "nec-usb-xhci"); 295557040d45SThomas Huth } 2956c86580b8SMarkus Armbruster 295753018216SPaolo Bonzini if (spapr->has_graphics) { 2958c86580b8SMarkus Armbruster USBBus *usb_bus = usb_bus_find(-1); 2959c86580b8SMarkus Armbruster 2960c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-kbd"); 2961c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-mouse"); 296253018216SPaolo Bonzini } 296353018216SPaolo Bonzini } 296453018216SPaolo Bonzini 2965ab3dd749SPhilippe Mathieu-Daudé if (spapr->rma_size < (MIN_RMA_SLOF * MiB)) { 2966d54e4d76SDavid Gibson error_report( 2967d54e4d76SDavid Gibson "pSeries SLOF firmware requires >= %ldM guest RMA (Real Mode Area memory)", 2968d54e4d76SDavid Gibson MIN_RMA_SLOF); 296953018216SPaolo Bonzini exit(1); 297053018216SPaolo Bonzini } 297153018216SPaolo Bonzini 297253018216SPaolo Bonzini if (kernel_filename) { 297353018216SPaolo Bonzini uint64_t lowaddr = 0; 297453018216SPaolo Bonzini 29754366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL, 29764366e1dbSLiam Merwick translate_kernel_address, NULL, 29774366e1dbSLiam Merwick NULL, &lowaddr, NULL, 1, 2978a19f7fb0SDavid Gibson PPC_ELF_MACHINE, 0, 0); 2979a19f7fb0SDavid Gibson if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) { 29804366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL, 2981a19f7fb0SDavid Gibson translate_kernel_address, NULL, NULL, 2982a19f7fb0SDavid Gibson &lowaddr, NULL, 0, PPC_ELF_MACHINE, 29837ef295eaSPeter Crosthwaite 0, 0); 2984a19f7fb0SDavid Gibson spapr->kernel_le = spapr->kernel_size > 0; 298516457e7fSBenjamin Herrenschmidt } 2986a19f7fb0SDavid Gibson if (spapr->kernel_size < 0) { 2987a19f7fb0SDavid Gibson error_report("error loading %s: %s", kernel_filename, 2988a19f7fb0SDavid Gibson load_elf_strerror(spapr->kernel_size)); 298953018216SPaolo Bonzini exit(1); 299053018216SPaolo Bonzini } 299153018216SPaolo Bonzini 299253018216SPaolo Bonzini /* load initrd */ 299353018216SPaolo Bonzini if (initrd_filename) { 299453018216SPaolo Bonzini /* Try to locate the initrd in the gap between the kernel 299553018216SPaolo Bonzini * and the firmware. Add a bit of space just in case 299653018216SPaolo Bonzini */ 2997a19f7fb0SDavid Gibson spapr->initrd_base = (KERNEL_LOAD_ADDR + spapr->kernel_size 2998a19f7fb0SDavid Gibson + 0x1ffff) & ~0xffff; 2999a19f7fb0SDavid Gibson spapr->initrd_size = load_image_targphys(initrd_filename, 3000a19f7fb0SDavid Gibson spapr->initrd_base, 3001a19f7fb0SDavid Gibson load_limit 3002a19f7fb0SDavid Gibson - spapr->initrd_base); 3003a19f7fb0SDavid Gibson if (spapr->initrd_size < 0) { 3004d54e4d76SDavid Gibson error_report("could not load initial ram disk '%s'", 300553018216SPaolo Bonzini initrd_filename); 300653018216SPaolo Bonzini exit(1); 300753018216SPaolo Bonzini } 300853018216SPaolo Bonzini } 300953018216SPaolo Bonzini } 301053018216SPaolo Bonzini 30118e7ea787SAndreas Färber if (bios_name == NULL) { 30128e7ea787SAndreas Färber bios_name = FW_FILE_NAME; 30138e7ea787SAndreas Färber } 30148e7ea787SAndreas Färber filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 30154c56440dSStefan Weil if (!filename) { 301668fea5a0SThomas Huth error_report("Could not find LPAR firmware '%s'", bios_name); 30174c56440dSStefan Weil exit(1); 30184c56440dSStefan Weil } 301953018216SPaolo Bonzini fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); 302068fea5a0SThomas Huth if (fw_size <= 0) { 302168fea5a0SThomas Huth error_report("Could not load LPAR firmware '%s'", filename); 302253018216SPaolo Bonzini exit(1); 302353018216SPaolo Bonzini } 302453018216SPaolo Bonzini g_free(filename); 302553018216SPaolo Bonzini 302628e02042SDavid Gibson /* FIXME: Should register things through the MachineState's qdev 302728e02042SDavid Gibson * interface, this is a legacy from the sPAPREnvironment structure 302828e02042SDavid Gibson * which predated MachineState but had a similar function */ 30294be21d56SDavid Gibson vmstate_register(NULL, 0, &vmstate_spapr, spapr); 30304be21d56SDavid Gibson register_savevm_live(NULL, "spapr/htab", -1, 1, 30314be21d56SDavid Gibson &savevm_htab_handlers, spapr); 30324be21d56SDavid Gibson 3033bb2bdd81SGreg Kurz qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine), 3034bb2bdd81SGreg Kurz &error_fatal); 3035bb2bdd81SGreg Kurz 30365b2128d2SAlexander Graf qemu_register_boot_set(spapr_boot_set, spapr); 303742043e4fSLaurent Vivier 303842043e4fSLaurent Vivier if (kvm_enabled()) { 30393dc410aeSAlexey Kardashevskiy /* to stop and start vmclock */ 304042043e4fSLaurent Vivier qemu_add_vm_change_state_handler(cpu_ppc_clock_vm_state_change, 304142043e4fSLaurent Vivier &spapr->tb); 30423dc410aeSAlexey Kardashevskiy 30433dc410aeSAlexey Kardashevskiy kvmppc_spapr_enable_inkernel_multitce(); 304442043e4fSLaurent Vivier } 304553018216SPaolo Bonzini } 304653018216SPaolo Bonzini 3047dc0ca80eSEric Auger static int spapr_kvm_type(MachineState *machine, const char *vm_type) 3048135a129aSAneesh Kumar K.V { 3049135a129aSAneesh Kumar K.V if (!vm_type) { 3050135a129aSAneesh Kumar K.V return 0; 3051135a129aSAneesh Kumar K.V } 3052135a129aSAneesh Kumar K.V 3053135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "HV")) { 3054135a129aSAneesh Kumar K.V return 1; 3055135a129aSAneesh Kumar K.V } 3056135a129aSAneesh Kumar K.V 3057135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "PR")) { 3058135a129aSAneesh Kumar K.V return 2; 3059135a129aSAneesh Kumar K.V } 3060135a129aSAneesh Kumar K.V 3061135a129aSAneesh Kumar K.V error_report("Unknown kvm-type specified '%s'", vm_type); 3062135a129aSAneesh Kumar K.V exit(1); 3063135a129aSAneesh Kumar K.V } 3064135a129aSAneesh Kumar K.V 306571461b0fSAlexey Kardashevskiy /* 3066627b84f4SGonglei * Implementation of an interface to adjust firmware path 306771461b0fSAlexey Kardashevskiy * for the bootindex property handling. 306871461b0fSAlexey Kardashevskiy */ 306971461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, 307071461b0fSAlexey Kardashevskiy DeviceState *dev) 307171461b0fSAlexey Kardashevskiy { 307271461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \ 307371461b0fSAlexey Kardashevskiy ((type *)object_dynamic_cast(OBJECT(obj), (name))) 307471461b0fSAlexey Kardashevskiy SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); 307571461b0fSAlexey Kardashevskiy sPAPRPHBState *phb = CAST(sPAPRPHBState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); 3076c4e13492SFelipe Franciosi VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON); 307771461b0fSAlexey Kardashevskiy 307871461b0fSAlexey Kardashevskiy if (d) { 307971461b0fSAlexey Kardashevskiy void *spapr = CAST(void, bus->parent, "spapr-vscsi"); 308071461b0fSAlexey Kardashevskiy VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); 308171461b0fSAlexey Kardashevskiy USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); 308271461b0fSAlexey Kardashevskiy 308371461b0fSAlexey Kardashevskiy if (spapr) { 308471461b0fSAlexey Kardashevskiy /* 308571461b0fSAlexey Kardashevskiy * Replace "channel@0/disk@0,0" with "disk@8000000000000000": 30861ac24c91SThomas Huth * In the top 16 bits of the 64-bit LUN, we use SRP luns of the form 30871ac24c91SThomas Huth * 0x8000 | (target << 8) | (bus << 5) | lun 30881ac24c91SThomas Huth * (see the "Logical unit addressing format" table in SAM5) 308971461b0fSAlexey Kardashevskiy */ 30901ac24c91SThomas Huth unsigned id = 0x8000 | (d->id << 8) | (d->channel << 5) | d->lun; 309171461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 309271461b0fSAlexey Kardashevskiy (uint64_t)id << 48); 309371461b0fSAlexey Kardashevskiy } else if (virtio) { 309471461b0fSAlexey Kardashevskiy /* 309571461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (target << 8) | lun 309671461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 309771461b0fSAlexey Kardashevskiy * Note: the quote above is from SLOF and it is wrong, 309871461b0fSAlexey Kardashevskiy * the actual binding is: 309971461b0fSAlexey Kardashevskiy * swap 0100 or 10 << or 20 << ( target lun-id -- srplun ) 310071461b0fSAlexey Kardashevskiy */ 310171461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (d->id << 16) | d->lun; 3102bac658d1SThomas Huth if (d->lun >= 256) { 3103bac658d1SThomas Huth /* Use the LUN "flat space addressing method" */ 3104bac658d1SThomas Huth id |= 0x4000; 3105bac658d1SThomas Huth } 310671461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 310771461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 310871461b0fSAlexey Kardashevskiy } else if (usb) { 310971461b0fSAlexey Kardashevskiy /* 311071461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (usb-port << 16) | lun 311171461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 311271461b0fSAlexey Kardashevskiy */ 311371461b0fSAlexey Kardashevskiy unsigned usb_port = atoi(usb->port->path); 311471461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (usb_port << 16) | d->lun; 311571461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 311671461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 311771461b0fSAlexey Kardashevskiy } 311871461b0fSAlexey Kardashevskiy } 311971461b0fSAlexey Kardashevskiy 3120b99260ebSThomas Huth /* 3121b99260ebSThomas Huth * SLOF probes the USB devices, and if it recognizes that the device is a 3122b99260ebSThomas Huth * storage device, it changes its name to "storage" instead of "usb-host", 3123b99260ebSThomas Huth * and additionally adds a child node for the SCSI LUN, so the correct 3124b99260ebSThomas Huth * boot path in SLOF is something like .../storage@1/disk@xxx" instead. 3125b99260ebSThomas Huth */ 3126b99260ebSThomas Huth if (strcmp("usb-host", qdev_fw_name(dev)) == 0) { 3127b99260ebSThomas Huth USBDevice *usbdev = CAST(USBDevice, dev, TYPE_USB_DEVICE); 3128b99260ebSThomas Huth if (usb_host_dev_is_scsi_storage(usbdev)) { 3129b99260ebSThomas Huth return g_strdup_printf("storage@%s/disk", usbdev->port->path); 3130b99260ebSThomas Huth } 3131b99260ebSThomas Huth } 3132b99260ebSThomas Huth 313371461b0fSAlexey Kardashevskiy if (phb) { 313471461b0fSAlexey Kardashevskiy /* Replace "pci" with "pci@800000020000000" */ 313571461b0fSAlexey Kardashevskiy return g_strdup_printf("pci@%"PRIX64, phb->buid); 313671461b0fSAlexey Kardashevskiy } 313771461b0fSAlexey Kardashevskiy 3138c4e13492SFelipe Franciosi if (vsc) { 3139c4e13492SFelipe Franciosi /* Same logic as virtio above */ 3140c4e13492SFelipe Franciosi unsigned id = 0x1000000 | (vsc->target << 16) | vsc->lun; 3141c4e13492SFelipe Franciosi return g_strdup_printf("disk@%"PRIX64, (uint64_t)id << 32); 3142c4e13492SFelipe Franciosi } 3143c4e13492SFelipe Franciosi 31444871dd4cSThomas Huth if (g_str_equal("pci-bridge", qdev_fw_name(dev))) { 31454871dd4cSThomas Huth /* SLOF uses "pci" instead of "pci-bridge" for PCI bridges */ 31464871dd4cSThomas Huth PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); 31474871dd4cSThomas Huth return g_strdup_printf("pci@%x", PCI_SLOT(pcidev->devfn)); 31484871dd4cSThomas Huth } 31494871dd4cSThomas Huth 315071461b0fSAlexey Kardashevskiy return NULL; 315171461b0fSAlexey Kardashevskiy } 315271461b0fSAlexey Kardashevskiy 315323825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp) 315423825581SEduardo Habkost { 315528e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 315623825581SEduardo Habkost 315728e02042SDavid Gibson return g_strdup(spapr->kvm_type); 315823825581SEduardo Habkost } 315923825581SEduardo Habkost 316023825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp) 316123825581SEduardo Habkost { 316228e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 316323825581SEduardo Habkost 316428e02042SDavid Gibson g_free(spapr->kvm_type); 316528e02042SDavid Gibson spapr->kvm_type = g_strdup(value); 316623825581SEduardo Habkost } 316723825581SEduardo Habkost 3168f6229214SMichael Roth static bool spapr_get_modern_hotplug_events(Object *obj, Error **errp) 3169f6229214SMichael Roth { 3170f6229214SMichael Roth sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 3171f6229214SMichael Roth 3172f6229214SMichael Roth return spapr->use_hotplug_event_source; 3173f6229214SMichael Roth } 3174f6229214SMichael Roth 3175f6229214SMichael Roth static void spapr_set_modern_hotplug_events(Object *obj, bool value, 3176f6229214SMichael Roth Error **errp) 3177f6229214SMichael Roth { 3178f6229214SMichael Roth sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 3179f6229214SMichael Roth 3180f6229214SMichael Roth spapr->use_hotplug_event_source = value; 3181f6229214SMichael Roth } 3182f6229214SMichael Roth 3183fcad0d21SAlexey Kardashevskiy static bool spapr_get_msix_emulation(Object *obj, Error **errp) 3184fcad0d21SAlexey Kardashevskiy { 3185fcad0d21SAlexey Kardashevskiy return true; 3186fcad0d21SAlexey Kardashevskiy } 3187fcad0d21SAlexey Kardashevskiy 318830f4b05bSDavid Gibson static char *spapr_get_resize_hpt(Object *obj, Error **errp) 318930f4b05bSDavid Gibson { 319030f4b05bSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 319130f4b05bSDavid Gibson 319230f4b05bSDavid Gibson switch (spapr->resize_hpt) { 319330f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DEFAULT: 319430f4b05bSDavid Gibson return g_strdup("default"); 319530f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DISABLED: 319630f4b05bSDavid Gibson return g_strdup("disabled"); 319730f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_ENABLED: 319830f4b05bSDavid Gibson return g_strdup("enabled"); 319930f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_REQUIRED: 320030f4b05bSDavid Gibson return g_strdup("required"); 320130f4b05bSDavid Gibson } 320230f4b05bSDavid Gibson g_assert_not_reached(); 320330f4b05bSDavid Gibson } 320430f4b05bSDavid Gibson 320530f4b05bSDavid Gibson static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp) 320630f4b05bSDavid Gibson { 320730f4b05bSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 320830f4b05bSDavid Gibson 320930f4b05bSDavid Gibson if (strcmp(value, "default") == 0) { 321030f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DEFAULT; 321130f4b05bSDavid Gibson } else if (strcmp(value, "disabled") == 0) { 321230f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 321330f4b05bSDavid Gibson } else if (strcmp(value, "enabled") == 0) { 321430f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_ENABLED; 321530f4b05bSDavid Gibson } else if (strcmp(value, "required") == 0) { 321630f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_REQUIRED; 321730f4b05bSDavid Gibson } else { 321830f4b05bSDavid Gibson error_setg(errp, "Bad value for \"resize-hpt\" property"); 321930f4b05bSDavid Gibson } 322030f4b05bSDavid Gibson } 322130f4b05bSDavid Gibson 3222fa98fbfcSSam Bobroff static void spapr_get_vsmt(Object *obj, Visitor *v, const char *name, 3223fa98fbfcSSam Bobroff void *opaque, Error **errp) 3224fa98fbfcSSam Bobroff { 3225fa98fbfcSSam Bobroff visit_type_uint32(v, name, (uint32_t *)opaque, errp); 3226fa98fbfcSSam Bobroff } 3227fa98fbfcSSam Bobroff 3228fa98fbfcSSam Bobroff static void spapr_set_vsmt(Object *obj, Visitor *v, const char *name, 3229fa98fbfcSSam Bobroff void *opaque, Error **errp) 3230fa98fbfcSSam Bobroff { 3231fa98fbfcSSam Bobroff visit_type_uint32(v, name, (uint32_t *)opaque, errp); 3232fa98fbfcSSam Bobroff } 3233fa98fbfcSSam Bobroff 32343ba3d0bcSCédric Le Goater static char *spapr_get_ic_mode(Object *obj, Error **errp) 32353ba3d0bcSCédric Le Goater { 32363ba3d0bcSCédric Le Goater sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 32373ba3d0bcSCédric Le Goater 32383ba3d0bcSCédric Le Goater if (spapr->irq == &spapr_irq_xics_legacy) { 32393ba3d0bcSCédric Le Goater return g_strdup("legacy"); 32403ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xics) { 32413ba3d0bcSCédric Le Goater return g_strdup("xics"); 32423ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xive) { 32433ba3d0bcSCédric Le Goater return g_strdup("xive"); 324413db0cd9SCédric Le Goater } else if (spapr->irq == &spapr_irq_dual) { 324513db0cd9SCédric Le Goater return g_strdup("dual"); 32463ba3d0bcSCédric Le Goater } 32473ba3d0bcSCédric Le Goater g_assert_not_reached(); 32483ba3d0bcSCédric Le Goater } 32493ba3d0bcSCédric Le Goater 32503ba3d0bcSCédric Le Goater static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp) 32513ba3d0bcSCédric Le Goater { 32523ba3d0bcSCédric Le Goater sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 32533ba3d0bcSCédric Le Goater 325421df5e4fSGreg Kurz if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { 325521df5e4fSGreg Kurz error_setg(errp, "This machine only uses the legacy XICS backend, don't pass ic-mode"); 325621df5e4fSGreg Kurz return; 325721df5e4fSGreg Kurz } 325821df5e4fSGreg Kurz 32593ba3d0bcSCédric Le Goater /* The legacy IRQ backend can not be set */ 32603ba3d0bcSCédric Le Goater if (strcmp(value, "xics") == 0) { 32613ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xics; 32623ba3d0bcSCédric Le Goater } else if (strcmp(value, "xive") == 0) { 32633ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xive; 326413db0cd9SCédric Le Goater } else if (strcmp(value, "dual") == 0) { 326513db0cd9SCédric Le Goater spapr->irq = &spapr_irq_dual; 32663ba3d0bcSCédric Le Goater } else { 32673ba3d0bcSCédric Le Goater error_setg(errp, "Bad value for \"ic-mode\" property"); 32683ba3d0bcSCédric Le Goater } 32693ba3d0bcSCédric Le Goater } 32703ba3d0bcSCédric Le Goater 327127461d69SPrasad J Pandit static char *spapr_get_host_model(Object *obj, Error **errp) 327227461d69SPrasad J Pandit { 327327461d69SPrasad J Pandit sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 327427461d69SPrasad J Pandit 327527461d69SPrasad J Pandit return g_strdup(spapr->host_model); 327627461d69SPrasad J Pandit } 327727461d69SPrasad J Pandit 327827461d69SPrasad J Pandit static void spapr_set_host_model(Object *obj, const char *value, Error **errp) 327927461d69SPrasad J Pandit { 328027461d69SPrasad J Pandit sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 328127461d69SPrasad J Pandit 328227461d69SPrasad J Pandit g_free(spapr->host_model); 328327461d69SPrasad J Pandit spapr->host_model = g_strdup(value); 328427461d69SPrasad J Pandit } 328527461d69SPrasad J Pandit 328627461d69SPrasad J Pandit static char *spapr_get_host_serial(Object *obj, Error **errp) 328727461d69SPrasad J Pandit { 328827461d69SPrasad J Pandit sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 328927461d69SPrasad J Pandit 329027461d69SPrasad J Pandit return g_strdup(spapr->host_serial); 329127461d69SPrasad J Pandit } 329227461d69SPrasad J Pandit 329327461d69SPrasad J Pandit static void spapr_set_host_serial(Object *obj, const char *value, Error **errp) 329427461d69SPrasad J Pandit { 329527461d69SPrasad J Pandit sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 329627461d69SPrasad J Pandit 329727461d69SPrasad J Pandit g_free(spapr->host_serial); 329827461d69SPrasad J Pandit spapr->host_serial = g_strdup(value); 329927461d69SPrasad J Pandit } 330027461d69SPrasad J Pandit 3301bcb5ce08SDavid Gibson static void spapr_instance_init(Object *obj) 330223825581SEduardo Habkost { 3303715c5407SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 33043ba3d0bcSCédric Le Goater sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 3305715c5407SDavid Gibson 3306715c5407SDavid Gibson spapr->htab_fd = -1; 3307f6229214SMichael Roth spapr->use_hotplug_event_source = true; 330823825581SEduardo Habkost object_property_add_str(obj, "kvm-type", 330923825581SEduardo Habkost spapr_get_kvm_type, spapr_set_kvm_type, NULL); 331049d2e648SMarcel Apfelbaum object_property_set_description(obj, "kvm-type", 331149d2e648SMarcel Apfelbaum "Specifies the KVM virtualization mode (HV, PR)", 331249d2e648SMarcel Apfelbaum NULL); 3313f6229214SMichael Roth object_property_add_bool(obj, "modern-hotplug-events", 3314f6229214SMichael Roth spapr_get_modern_hotplug_events, 3315f6229214SMichael Roth spapr_set_modern_hotplug_events, 3316f6229214SMichael Roth NULL); 3317f6229214SMichael Roth object_property_set_description(obj, "modern-hotplug-events", 3318f6229214SMichael Roth "Use dedicated hotplug event mechanism in" 3319f6229214SMichael Roth " place of standard EPOW events when possible" 3320f6229214SMichael Roth " (required for memory hot-unplug support)", 3321f6229214SMichael Roth NULL); 33227843c0d6SDavid Gibson ppc_compat_add_property(obj, "max-cpu-compat", &spapr->max_compat_pvr, 33237843c0d6SDavid Gibson "Maximum permitted CPU compatibility mode", 33247843c0d6SDavid Gibson &error_fatal); 332530f4b05bSDavid Gibson 332630f4b05bSDavid Gibson object_property_add_str(obj, "resize-hpt", 332730f4b05bSDavid Gibson spapr_get_resize_hpt, spapr_set_resize_hpt, NULL); 332830f4b05bSDavid Gibson object_property_set_description(obj, "resize-hpt", 332930f4b05bSDavid Gibson "Resizing of the Hash Page Table (enabled, disabled, required)", 333030f4b05bSDavid Gibson NULL); 3331fa98fbfcSSam Bobroff object_property_add(obj, "vsmt", "uint32", spapr_get_vsmt, 3332fa98fbfcSSam Bobroff spapr_set_vsmt, NULL, &spapr->vsmt, &error_abort); 3333fa98fbfcSSam Bobroff object_property_set_description(obj, "vsmt", 3334fa98fbfcSSam Bobroff "Virtual SMT: KVM behaves as if this were" 3335fa98fbfcSSam Bobroff " the host's SMT mode", &error_abort); 3336fcad0d21SAlexey Kardashevskiy object_property_add_bool(obj, "vfio-no-msix-emulation", 3337fcad0d21SAlexey Kardashevskiy spapr_get_msix_emulation, NULL, NULL); 33383ba3d0bcSCédric Le Goater 33393ba3d0bcSCédric Le Goater /* The machine class defines the default interrupt controller mode */ 33403ba3d0bcSCédric Le Goater spapr->irq = smc->irq; 33413ba3d0bcSCédric Le Goater object_property_add_str(obj, "ic-mode", spapr_get_ic_mode, 33423ba3d0bcSCédric Le Goater spapr_set_ic_mode, NULL); 33433ba3d0bcSCédric Le Goater object_property_set_description(obj, "ic-mode", 334413db0cd9SCédric Le Goater "Specifies the interrupt controller mode (xics, xive, dual)", 33453ba3d0bcSCédric Le Goater NULL); 334627461d69SPrasad J Pandit 334727461d69SPrasad J Pandit object_property_add_str(obj, "host-model", 334827461d69SPrasad J Pandit spapr_get_host_model, spapr_set_host_model, 334927461d69SPrasad J Pandit &error_abort); 335027461d69SPrasad J Pandit object_property_set_description(obj, "host-model", 335127461d69SPrasad J Pandit "Set host's model-id to use - none|passthrough|string", &error_abort); 335227461d69SPrasad J Pandit object_property_add_str(obj, "host-serial", 335327461d69SPrasad J Pandit spapr_get_host_serial, spapr_set_host_serial, 335427461d69SPrasad J Pandit &error_abort); 335527461d69SPrasad J Pandit object_property_set_description(obj, "host-serial", 335627461d69SPrasad J Pandit "Set host's system-id to use - none|passthrough|string", &error_abort); 335723825581SEduardo Habkost } 335823825581SEduardo Habkost 335987bbdd9cSDavid Gibson static void spapr_machine_finalizefn(Object *obj) 336087bbdd9cSDavid Gibson { 336187bbdd9cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 336287bbdd9cSDavid Gibson 336387bbdd9cSDavid Gibson g_free(spapr->kvm_type); 336487bbdd9cSDavid Gibson } 336587bbdd9cSDavid Gibson 33661c7ad77eSNicholas Piggin void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg) 336734316482SAlexey Kardashevskiy { 336834316482SAlexey Kardashevskiy cpu_synchronize_state(cs); 336934316482SAlexey Kardashevskiy ppc_cpu_do_system_reset(cs); 337034316482SAlexey Kardashevskiy } 337134316482SAlexey Kardashevskiy 337234316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) 337334316482SAlexey Kardashevskiy { 337434316482SAlexey Kardashevskiy CPUState *cs; 337534316482SAlexey Kardashevskiy 337634316482SAlexey Kardashevskiy CPU_FOREACH(cs) { 33771c7ad77eSNicholas Piggin async_run_on_cpu(cs, spapr_do_system_reset_on_cpu, RUN_ON_CPU_NULL); 337834316482SAlexey Kardashevskiy } 337934316482SAlexey Kardashevskiy } 338034316482SAlexey Kardashevskiy 338162d38c9bSGreg Kurz int spapr_lmb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr, 338262d38c9bSGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 338362d38c9bSGreg Kurz { 338462d38c9bSGreg Kurz uint64_t addr; 338562d38c9bSGreg Kurz uint32_t node; 338662d38c9bSGreg Kurz 338762d38c9bSGreg Kurz addr = spapr_drc_index(drc) * SPAPR_MEMORY_BLOCK_SIZE; 338862d38c9bSGreg Kurz node = object_property_get_uint(OBJECT(drc->dev), PC_DIMM_NODE_PROP, 338962d38c9bSGreg Kurz &error_abort); 339062d38c9bSGreg Kurz *fdt_start_offset = spapr_populate_memory_node(fdt, node, addr, 339162d38c9bSGreg Kurz SPAPR_MEMORY_BLOCK_SIZE); 339262d38c9bSGreg Kurz return 0; 339362d38c9bSGreg Kurz } 339462d38c9bSGreg Kurz 339579b78a6bSMichael Roth static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, 339662d38c9bSGreg Kurz bool dedicated_hp_event_source, Error **errp) 3397c20d332aSBharata B Rao { 3398c20d332aSBharata B Rao sPAPRDRConnector *drc; 3399c20d332aSBharata B Rao uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; 340062d38c9bSGreg Kurz int i; 340179b78a6bSMichael Roth uint64_t addr = addr_start; 340294fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 3403160bb678SGreg Kurz Error *local_err = NULL; 3404c20d332aSBharata B Rao 3405c20d332aSBharata B Rao for (i = 0; i < nr_lmbs; i++) { 3406fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 3407c20d332aSBharata B Rao addr / SPAPR_MEMORY_BLOCK_SIZE); 3408c20d332aSBharata B Rao g_assert(drc); 3409c20d332aSBharata B Rao 341009d876ceSGreg Kurz spapr_drc_attach(drc, dev, &local_err); 3411160bb678SGreg Kurz if (local_err) { 3412160bb678SGreg Kurz while (addr > addr_start) { 3413160bb678SGreg Kurz addr -= SPAPR_MEMORY_BLOCK_SIZE; 3414160bb678SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 3415160bb678SGreg Kurz addr / SPAPR_MEMORY_BLOCK_SIZE); 3416a8dc47fdSDavid Gibson spapr_drc_detach(drc); 3417160bb678SGreg Kurz } 3418160bb678SGreg Kurz error_propagate(errp, local_err); 3419160bb678SGreg Kurz return; 3420160bb678SGreg Kurz } 342194fd9cbaSLaurent Vivier if (!hotplugged) { 342294fd9cbaSLaurent Vivier spapr_drc_reset(drc); 342394fd9cbaSLaurent Vivier } 3424c20d332aSBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE; 3425c20d332aSBharata B Rao } 34265dd5238cSJianjun Duan /* send hotplug notification to the 34275dd5238cSJianjun Duan * guest only in case of hotplugged memory 34285dd5238cSJianjun Duan */ 342994fd9cbaSLaurent Vivier if (hotplugged) { 343079b78a6bSMichael Roth if (dedicated_hp_event_source) { 3431fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 343279b78a6bSMichael Roth addr_start / SPAPR_MEMORY_BLOCK_SIZE); 343379b78a6bSMichael Roth spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 343479b78a6bSMichael Roth nr_lmbs, 34350b55aa91SDavid Gibson spapr_drc_index(drc)); 343679b78a6bSMichael Roth } else { 343779b78a6bSMichael Roth spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, 343879b78a6bSMichael Roth nr_lmbs); 343979b78a6bSMichael Roth } 3440c20d332aSBharata B Rao } 34415dd5238cSJianjun Duan } 3442c20d332aSBharata B Rao 3443c20d332aSBharata B Rao static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 344481985f3bSDavid Hildenbrand Error **errp) 3445c20d332aSBharata B Rao { 3446c20d332aSBharata B Rao Error *local_err = NULL; 3447c20d332aSBharata B Rao sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev); 3448c20d332aSBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 3449b0e62443SDavid Hildenbrand uint64_t size, addr; 345004790978SThomas Huth 3451946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dev), &error_abort); 3452df587133SThomas Huth 3453fd3416f5SDavid Hildenbrand pc_dimm_plug(dimm, MACHINE(ms), &local_err); 3454c20d332aSBharata B Rao if (local_err) { 3455c20d332aSBharata B Rao goto out; 3456c20d332aSBharata B Rao } 3457c20d332aSBharata B Rao 34589ed442b8SMarc-André Lureau addr = object_property_get_uint(OBJECT(dimm), 34599ed442b8SMarc-André Lureau PC_DIMM_ADDR_PROP, &local_err); 3460c20d332aSBharata B Rao if (local_err) { 3461160bb678SGreg Kurz goto out_unplug; 3462c20d332aSBharata B Rao } 3463c20d332aSBharata B Rao 346462d38c9bSGreg Kurz spapr_add_lmbs(dev, addr, size, spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), 3465160bb678SGreg Kurz &local_err); 3466160bb678SGreg Kurz if (local_err) { 3467160bb678SGreg Kurz goto out_unplug; 3468160bb678SGreg Kurz } 3469c20d332aSBharata B Rao 3470160bb678SGreg Kurz return; 3471160bb678SGreg Kurz 3472160bb678SGreg Kurz out_unplug: 3473fd3416f5SDavid Hildenbrand pc_dimm_unplug(dimm, MACHINE(ms)); 3474c20d332aSBharata B Rao out: 3475c20d332aSBharata B Rao error_propagate(errp, local_err); 3476c20d332aSBharata B Rao } 3477c20d332aSBharata B Rao 3478c871bc70SLaurent Vivier static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3479c871bc70SLaurent Vivier Error **errp) 3480c871bc70SLaurent Vivier { 34814e8a01bdSDavid Hildenbrand const sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev); 3482123eec65SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3483c871bc70SLaurent Vivier PCDIMMDevice *dimm = PC_DIMM(dev); 34848f1ffe5bSDavid Hildenbrand Error *local_err = NULL; 348504790978SThomas Huth uint64_t size; 3486123eec65SDavid Gibson Object *memdev; 3487123eec65SDavid Gibson hwaddr pagesize; 3488c871bc70SLaurent Vivier 34894e8a01bdSDavid Hildenbrand if (!smc->dr_lmb_enabled) { 34904e8a01bdSDavid Hildenbrand error_setg(errp, "Memory hotplug not supported for this machine"); 34914e8a01bdSDavid Hildenbrand return; 34924e8a01bdSDavid Hildenbrand } 34934e8a01bdSDavid Hildenbrand 3494946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &local_err); 3495946d6154SDavid Hildenbrand if (local_err) { 3496946d6154SDavid Hildenbrand error_propagate(errp, local_err); 349704790978SThomas Huth return; 349804790978SThomas Huth } 349904790978SThomas Huth 3500c871bc70SLaurent Vivier if (size % SPAPR_MEMORY_BLOCK_SIZE) { 3501c871bc70SLaurent Vivier error_setg(errp, "Hotplugged memory size must be a multiple of " 3502ab3dd749SPhilippe Mathieu-Daudé "%" PRIu64 " MB", SPAPR_MEMORY_BLOCK_SIZE / MiB); 3503c871bc70SLaurent Vivier return; 3504c871bc70SLaurent Vivier } 3505c871bc70SLaurent Vivier 3506123eec65SDavid Gibson memdev = object_property_get_link(OBJECT(dimm), PC_DIMM_MEMDEV_PROP, 3507123eec65SDavid Gibson &error_abort); 3508123eec65SDavid Gibson pagesize = host_memory_backend_pagesize(MEMORY_BACKEND(memdev)); 35098f1ffe5bSDavid Hildenbrand spapr_check_pagesize(spapr, pagesize, &local_err); 35108f1ffe5bSDavid Hildenbrand if (local_err) { 35118f1ffe5bSDavid Hildenbrand error_propagate(errp, local_err); 35128f1ffe5bSDavid Hildenbrand return; 35138f1ffe5bSDavid Hildenbrand } 35148f1ffe5bSDavid Hildenbrand 3515fd3416f5SDavid Hildenbrand pc_dimm_pre_plug(dimm, MACHINE(hotplug_dev), NULL, errp); 3516c871bc70SLaurent Vivier } 3517c871bc70SLaurent Vivier 35180cffce56SDavid Gibson struct sPAPRDIMMState { 35190cffce56SDavid Gibson PCDIMMDevice *dimm; 3520cf632463SBharata B Rao uint32_t nr_lmbs; 35210cffce56SDavid Gibson QTAILQ_ENTRY(sPAPRDIMMState) next; 35220cffce56SDavid Gibson }; 35230cffce56SDavid Gibson 35240cffce56SDavid Gibson static sPAPRDIMMState *spapr_pending_dimm_unplugs_find(sPAPRMachineState *s, 35250cffce56SDavid Gibson PCDIMMDevice *dimm) 35260cffce56SDavid Gibson { 35270cffce56SDavid Gibson sPAPRDIMMState *dimm_state = NULL; 35280cffce56SDavid Gibson 35290cffce56SDavid Gibson QTAILQ_FOREACH(dimm_state, &s->pending_dimm_unplugs, next) { 35300cffce56SDavid Gibson if (dimm_state->dimm == dimm) { 35310cffce56SDavid Gibson break; 35320cffce56SDavid Gibson } 35330cffce56SDavid Gibson } 35340cffce56SDavid Gibson return dimm_state; 35350cffce56SDavid Gibson } 35360cffce56SDavid Gibson 35378d5981c4SBharata B Rao static sPAPRDIMMState *spapr_pending_dimm_unplugs_add(sPAPRMachineState *spapr, 35388d5981c4SBharata B Rao uint32_t nr_lmbs, 35398d5981c4SBharata B Rao PCDIMMDevice *dimm) 35400cffce56SDavid Gibson { 35418d5981c4SBharata B Rao sPAPRDIMMState *ds = NULL; 35428d5981c4SBharata B Rao 35438d5981c4SBharata B Rao /* 35448d5981c4SBharata B Rao * If this request is for a DIMM whose removal had failed earlier 35458d5981c4SBharata B Rao * (due to guest's refusal to remove the LMBs), we would have this 35468d5981c4SBharata B Rao * dimm already in the pending_dimm_unplugs list. In that 35478d5981c4SBharata B Rao * case don't add again. 35488d5981c4SBharata B Rao */ 35498d5981c4SBharata B Rao ds = spapr_pending_dimm_unplugs_find(spapr, dimm); 35508d5981c4SBharata B Rao if (!ds) { 35518d5981c4SBharata B Rao ds = g_malloc0(sizeof(sPAPRDIMMState)); 35528d5981c4SBharata B Rao ds->nr_lmbs = nr_lmbs; 35538d5981c4SBharata B Rao ds->dimm = dimm; 35548d5981c4SBharata B Rao QTAILQ_INSERT_HEAD(&spapr->pending_dimm_unplugs, ds, next); 35558d5981c4SBharata B Rao } 35568d5981c4SBharata B Rao return ds; 35570cffce56SDavid Gibson } 35580cffce56SDavid Gibson 35590cffce56SDavid Gibson static void spapr_pending_dimm_unplugs_remove(sPAPRMachineState *spapr, 35600cffce56SDavid Gibson sPAPRDIMMState *dimm_state) 35610cffce56SDavid Gibson { 35620cffce56SDavid Gibson QTAILQ_REMOVE(&spapr->pending_dimm_unplugs, dimm_state, next); 35630cffce56SDavid Gibson g_free(dimm_state); 35640cffce56SDavid Gibson } 3565cf632463SBharata B Rao 356616ee9980SDaniel Henrique Barboza static sPAPRDIMMState *spapr_recover_pending_dimm_state(sPAPRMachineState *ms, 356716ee9980SDaniel Henrique Barboza PCDIMMDevice *dimm) 356816ee9980SDaniel Henrique Barboza { 356916ee9980SDaniel Henrique Barboza sPAPRDRConnector *drc; 3570946d6154SDavid Hildenbrand uint64_t size = memory_device_get_region_size(MEMORY_DEVICE(dimm), 3571946d6154SDavid Hildenbrand &error_abort); 357216ee9980SDaniel Henrique Barboza uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 357316ee9980SDaniel Henrique Barboza uint32_t avail_lmbs = 0; 357416ee9980SDaniel Henrique Barboza uint64_t addr_start, addr; 357516ee9980SDaniel Henrique Barboza int i; 357616ee9980SDaniel Henrique Barboza 357716ee9980SDaniel Henrique Barboza addr_start = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, 357816ee9980SDaniel Henrique Barboza &error_abort); 357916ee9980SDaniel Henrique Barboza 358016ee9980SDaniel Henrique Barboza addr = addr_start; 358116ee9980SDaniel Henrique Barboza for (i = 0; i < nr_lmbs; i++) { 3582fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 358316ee9980SDaniel Henrique Barboza addr / SPAPR_MEMORY_BLOCK_SIZE); 358416ee9980SDaniel Henrique Barboza g_assert(drc); 3585454b580aSDavid Gibson if (drc->dev) { 358616ee9980SDaniel Henrique Barboza avail_lmbs++; 358716ee9980SDaniel Henrique Barboza } 358816ee9980SDaniel Henrique Barboza addr += SPAPR_MEMORY_BLOCK_SIZE; 358916ee9980SDaniel Henrique Barboza } 359016ee9980SDaniel Henrique Barboza 35918d5981c4SBharata B Rao return spapr_pending_dimm_unplugs_add(ms, avail_lmbs, dimm); 359216ee9980SDaniel Henrique Barboza } 359316ee9980SDaniel Henrique Barboza 359431834723SDaniel Henrique Barboza /* Callback to be called during DRC release. */ 359531834723SDaniel Henrique Barboza void spapr_lmb_release(DeviceState *dev) 3596cf632463SBharata B Rao { 35973ec71474SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 35983ec71474SDavid Hildenbrand sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl); 35990cffce56SDavid Gibson sPAPRDIMMState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); 3600cf632463SBharata B Rao 360116ee9980SDaniel Henrique Barboza /* This information will get lost if a migration occurs 360216ee9980SDaniel Henrique Barboza * during the unplug process. In this case recover it. */ 360316ee9980SDaniel Henrique Barboza if (ds == NULL) { 360416ee9980SDaniel Henrique Barboza ds = spapr_recover_pending_dimm_state(spapr, PC_DIMM(dev)); 36058d5981c4SBharata B Rao g_assert(ds); 3606454b580aSDavid Gibson /* The DRC being examined by the caller at least must be counted */ 3607454b580aSDavid Gibson g_assert(ds->nr_lmbs); 360816ee9980SDaniel Henrique Barboza } 3609454b580aSDavid Gibson 3610454b580aSDavid Gibson if (--ds->nr_lmbs) { 3611cf632463SBharata B Rao return; 3612cf632463SBharata B Rao } 3613cf632463SBharata B Rao 3614cf632463SBharata B Rao /* 3615cf632463SBharata B Rao * Now that all the LMBs have been removed by the guest, call the 36163ec71474SDavid Hildenbrand * unplug handler chain. This can never fail. 3617cf632463SBharata B Rao */ 36183ec71474SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 361907578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 36203ec71474SDavid Hildenbrand } 36213ec71474SDavid Hildenbrand 36223ec71474SDavid Hildenbrand static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 36233ec71474SDavid Hildenbrand { 36243ec71474SDavid Hildenbrand sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 36253ec71474SDavid Hildenbrand sPAPRDIMMState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); 36263ec71474SDavid Hildenbrand 3627fd3416f5SDavid Hildenbrand pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev)); 362807578b0aSDavid Hildenbrand object_property_set_bool(OBJECT(dev), false, "realized", NULL); 36292a129767SDaniel Henrique Barboza spapr_pending_dimm_unplugs_remove(spapr, ds); 3630cf632463SBharata B Rao } 3631cf632463SBharata B Rao 3632cf632463SBharata B Rao static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, 3633cf632463SBharata B Rao DeviceState *dev, Error **errp) 3634cf632463SBharata B Rao { 36350cffce56SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3636cf632463SBharata B Rao Error *local_err = NULL; 3637cf632463SBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 363804790978SThomas Huth uint32_t nr_lmbs; 363904790978SThomas Huth uint64_t size, addr_start, addr; 36400cffce56SDavid Gibson int i; 36410cffce56SDavid Gibson sPAPRDRConnector *drc; 364204790978SThomas Huth 3643946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &error_abort); 364404790978SThomas Huth nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 364504790978SThomas Huth 36469ed442b8SMarc-André Lureau addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, 36470cffce56SDavid Gibson &local_err); 3648cf632463SBharata B Rao if (local_err) { 3649cf632463SBharata B Rao goto out; 3650cf632463SBharata B Rao } 3651cf632463SBharata B Rao 36522a129767SDaniel Henrique Barboza /* 36532a129767SDaniel Henrique Barboza * An existing pending dimm state for this DIMM means that there is an 36542a129767SDaniel Henrique Barboza * unplug operation in progress, waiting for the spapr_lmb_release 36552a129767SDaniel Henrique Barboza * callback to complete the job (BQL can't cover that far). In this case, 36562a129767SDaniel Henrique Barboza * bail out to avoid detaching DRCs that were already released. 36572a129767SDaniel Henrique Barboza */ 36582a129767SDaniel Henrique Barboza if (spapr_pending_dimm_unplugs_find(spapr, dimm)) { 36592a129767SDaniel Henrique Barboza error_setg(&local_err, 36602a129767SDaniel Henrique Barboza "Memory unplug already in progress for device %s", 36612a129767SDaniel Henrique Barboza dev->id); 36622a129767SDaniel Henrique Barboza goto out; 36632a129767SDaniel Henrique Barboza } 36642a129767SDaniel Henrique Barboza 36658d5981c4SBharata B Rao spapr_pending_dimm_unplugs_add(spapr, nr_lmbs, dimm); 36660cffce56SDavid Gibson 36670cffce56SDavid Gibson addr = addr_start; 36680cffce56SDavid Gibson for (i = 0; i < nr_lmbs; i++) { 3669fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 36700cffce56SDavid Gibson addr / SPAPR_MEMORY_BLOCK_SIZE); 36710cffce56SDavid Gibson g_assert(drc); 36720cffce56SDavid Gibson 3673a8dc47fdSDavid Gibson spapr_drc_detach(drc); 36740cffce56SDavid Gibson addr += SPAPR_MEMORY_BLOCK_SIZE; 36750cffce56SDavid Gibson } 36760cffce56SDavid Gibson 3677fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 36780cffce56SDavid Gibson addr_start / SPAPR_MEMORY_BLOCK_SIZE); 36790cffce56SDavid Gibson spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 36800b55aa91SDavid Gibson nr_lmbs, spapr_drc_index(drc)); 3681cf632463SBharata B Rao out: 3682cf632463SBharata B Rao error_propagate(errp, local_err); 3683cf632463SBharata B Rao } 3684cf632463SBharata B Rao 3685765d1bddSDavid Gibson /* Callback to be called during DRC release. */ 3686765d1bddSDavid Gibson void spapr_core_release(DeviceState *dev) 3687ff9006ddSIgor Mammedov { 3688a4261be1SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3689a4261be1SDavid Hildenbrand 3690a4261be1SDavid Hildenbrand /* Call the unplug handler chain. This can never fail. */ 3691a4261be1SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 369207578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 3693a4261be1SDavid Hildenbrand } 3694a4261be1SDavid Hildenbrand 3695a4261be1SDavid Hildenbrand static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 3696a4261be1SDavid Hildenbrand { 3697a4261be1SDavid Hildenbrand MachineState *ms = MACHINE(hotplug_dev); 369846f7afa3SGreg Kurz sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms); 3699ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3700535455fdSIgor Mammedov CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL); 3701ff9006ddSIgor Mammedov 370246f7afa3SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 370346f7afa3SGreg Kurz sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); 370446f7afa3SGreg Kurz int i; 370546f7afa3SGreg Kurz 370646f7afa3SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 370794ad93bdSGreg Kurz CPUState *cs = CPU(sc->threads[i]); 370846f7afa3SGreg Kurz 370946f7afa3SGreg Kurz pre_2_10_vmstate_register_dummy_icp(cs->cpu_index); 371046f7afa3SGreg Kurz } 371146f7afa3SGreg Kurz } 371246f7afa3SGreg Kurz 371307572c06SGreg Kurz assert(core_slot); 3714535455fdSIgor Mammedov core_slot->cpu = NULL; 371507578b0aSDavid Hildenbrand object_property_set_bool(OBJECT(dev), false, "realized", NULL); 3716ff9006ddSIgor Mammedov } 3717ff9006ddSIgor Mammedov 3718115debf2SIgor Mammedov static 3719115debf2SIgor Mammedov void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, 3720ff9006ddSIgor Mammedov Error **errp) 3721ff9006ddSIgor Mammedov { 372272194664SGreg Kurz sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3723535455fdSIgor Mammedov int index; 3724535455fdSIgor Mammedov sPAPRDRConnector *drc; 3725535455fdSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3726ff9006ddSIgor Mammedov 3727535455fdSIgor Mammedov if (!spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index)) { 3728535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 3729535455fdSIgor Mammedov cc->core_id); 3730535455fdSIgor Mammedov return; 3731535455fdSIgor Mammedov } 3732ff9006ddSIgor Mammedov if (index == 0) { 3733ff9006ddSIgor Mammedov error_setg(errp, "Boot CPU core may not be unplugged"); 3734ff9006ddSIgor Mammedov return; 3735ff9006ddSIgor Mammedov } 3736ff9006ddSIgor Mammedov 37375d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 37385d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 3739ff9006ddSIgor Mammedov g_assert(drc); 3740ff9006ddSIgor Mammedov 3741a8dc47fdSDavid Gibson spapr_drc_detach(drc); 3742ff9006ddSIgor Mammedov 3743ff9006ddSIgor Mammedov spapr_hotplug_req_remove_by_index(drc); 3744ff9006ddSIgor Mammedov } 3745ff9006ddSIgor Mammedov 3746345b12b9SGreg Kurz int spapr_core_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr, 3747345b12b9SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 3748345b12b9SGreg Kurz { 3749345b12b9SGreg Kurz sPAPRCPUCore *core = SPAPR_CPU_CORE(drc->dev); 3750345b12b9SGreg Kurz CPUState *cs = CPU(core->threads[0]); 3751345b12b9SGreg Kurz PowerPCCPU *cpu = POWERPC_CPU(cs); 3752345b12b9SGreg Kurz DeviceClass *dc = DEVICE_GET_CLASS(cs); 3753345b12b9SGreg Kurz int id = spapr_get_vcpu_id(cpu); 3754345b12b9SGreg Kurz char *nodename; 3755345b12b9SGreg Kurz int offset; 3756345b12b9SGreg Kurz 3757345b12b9SGreg Kurz nodename = g_strdup_printf("%s@%x", dc->fw_name, id); 3758345b12b9SGreg Kurz offset = fdt_add_subnode(fdt, 0, nodename); 3759345b12b9SGreg Kurz g_free(nodename); 3760345b12b9SGreg Kurz 3761345b12b9SGreg Kurz spapr_populate_cpu_dt(cs, fdt, offset, spapr); 3762345b12b9SGreg Kurz 3763345b12b9SGreg Kurz *fdt_start_offset = offset; 3764345b12b9SGreg Kurz return 0; 3765345b12b9SGreg Kurz } 3766345b12b9SGreg Kurz 3767ff9006ddSIgor Mammedov static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3768ff9006ddSIgor Mammedov Error **errp) 3769ff9006ddSIgor Mammedov { 3770ff9006ddSIgor Mammedov sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3771ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(spapr); 377246f7afa3SGreg Kurz sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 3773ff9006ddSIgor Mammedov sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev)); 3774ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3775345b12b9SGreg Kurz CPUState *cs; 3776ff9006ddSIgor Mammedov sPAPRDRConnector *drc; 3777ff9006ddSIgor Mammedov Error *local_err = NULL; 3778535455fdSIgor Mammedov CPUArchId *core_slot; 3779535455fdSIgor Mammedov int index; 378094fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 3781ff9006ddSIgor Mammedov 3782535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 3783535455fdSIgor Mammedov if (!core_slot) { 3784535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 3785535455fdSIgor Mammedov cc->core_id); 3786535455fdSIgor Mammedov return; 3787535455fdSIgor Mammedov } 37885d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 37895d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 3790ff9006ddSIgor Mammedov 3791c5514d0eSIgor Mammedov g_assert(drc || !mc->has_hotpluggable_cpus); 3792ff9006ddSIgor Mammedov 3793e49c63d5SGreg Kurz if (drc) { 379409d876ceSGreg Kurz spapr_drc_attach(drc, dev, &local_err); 3795ff9006ddSIgor Mammedov if (local_err) { 3796ff9006ddSIgor Mammedov error_propagate(errp, local_err); 3797ff9006ddSIgor Mammedov return; 3798ff9006ddSIgor Mammedov } 3799ff9006ddSIgor Mammedov 380094fd9cbaSLaurent Vivier if (hotplugged) { 3801ff9006ddSIgor Mammedov /* 380294fd9cbaSLaurent Vivier * Send hotplug notification interrupt to the guest only 380394fd9cbaSLaurent Vivier * in case of hotplugged CPUs. 3804ff9006ddSIgor Mammedov */ 3805ff9006ddSIgor Mammedov spapr_hotplug_req_add_by_index(drc); 380694fd9cbaSLaurent Vivier } else { 380794fd9cbaSLaurent Vivier spapr_drc_reset(drc); 3808ff9006ddSIgor Mammedov } 380994fd9cbaSLaurent Vivier } 381094fd9cbaSLaurent Vivier 3811535455fdSIgor Mammedov core_slot->cpu = OBJECT(dev); 381246f7afa3SGreg Kurz 381346f7afa3SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 381446f7afa3SGreg Kurz int i; 381546f7afa3SGreg Kurz 381646f7afa3SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 3817bc877283SGreg Kurz cs = CPU(core->threads[i]); 381846f7afa3SGreg Kurz pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index); 381946f7afa3SGreg Kurz } 382046f7afa3SGreg Kurz } 3821ff9006ddSIgor Mammedov } 3822ff9006ddSIgor Mammedov 3823ff9006ddSIgor Mammedov static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3824ff9006ddSIgor Mammedov Error **errp) 3825ff9006ddSIgor Mammedov { 3826ff9006ddSIgor Mammedov MachineState *machine = MACHINE(OBJECT(hotplug_dev)); 3827ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); 3828ff9006ddSIgor Mammedov Error *local_err = NULL; 3829ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 38302e9c10ebSIgor Mammedov const char *base_core_type = spapr_get_cpu_core_type(machine->cpu_type); 3831ff9006ddSIgor Mammedov const char *type = object_get_typename(OBJECT(dev)); 3832535455fdSIgor Mammedov CPUArchId *core_slot; 3833535455fdSIgor Mammedov int index; 3834ff9006ddSIgor Mammedov 3835c5514d0eSIgor Mammedov if (dev->hotplugged && !mc->has_hotpluggable_cpus) { 3836ff9006ddSIgor Mammedov error_setg(&local_err, "CPU hotplug not supported for this machine"); 3837ff9006ddSIgor Mammedov goto out; 3838ff9006ddSIgor Mammedov } 3839ff9006ddSIgor Mammedov 3840ff9006ddSIgor Mammedov if (strcmp(base_core_type, type)) { 3841ff9006ddSIgor Mammedov error_setg(&local_err, "CPU core type should be %s", base_core_type); 3842ff9006ddSIgor Mammedov goto out; 3843ff9006ddSIgor Mammedov } 3844ff9006ddSIgor Mammedov 3845ff9006ddSIgor Mammedov if (cc->core_id % smp_threads) { 3846ff9006ddSIgor Mammedov error_setg(&local_err, "invalid core id %d", cc->core_id); 3847ff9006ddSIgor Mammedov goto out; 3848ff9006ddSIgor Mammedov } 3849ff9006ddSIgor Mammedov 3850459264efSDavid Gibson /* 3851459264efSDavid Gibson * In general we should have homogeneous threads-per-core, but old 3852459264efSDavid Gibson * (pre hotplug support) machine types allow the last core to have 3853459264efSDavid Gibson * reduced threads as a compatibility hack for when we allowed 3854459264efSDavid Gibson * total vcpus not a multiple of threads-per-core. 3855459264efSDavid Gibson */ 3856459264efSDavid Gibson if (mc->has_hotpluggable_cpus && (cc->nr_threads != smp_threads)) { 3857df8658deSGreg Kurz error_setg(&local_err, "invalid nr-threads %d, must be %d", 38588149e299SDavid Gibson cc->nr_threads, smp_threads); 3859df8658deSGreg Kurz goto out; 38608149e299SDavid Gibson } 38618149e299SDavid Gibson 3862535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 3863535455fdSIgor Mammedov if (!core_slot) { 3864ff9006ddSIgor Mammedov error_setg(&local_err, "core id %d out of range", cc->core_id); 3865ff9006ddSIgor Mammedov goto out; 3866ff9006ddSIgor Mammedov } 3867ff9006ddSIgor Mammedov 3868535455fdSIgor Mammedov if (core_slot->cpu) { 3869ff9006ddSIgor Mammedov error_setg(&local_err, "core %d already populated", cc->core_id); 3870ff9006ddSIgor Mammedov goto out; 3871ff9006ddSIgor Mammedov } 3872ff9006ddSIgor Mammedov 3873a0ceb640SIgor Mammedov numa_cpu_pre_plug(core_slot, dev, &local_err); 38740b8497f0SIgor Mammedov 3875ff9006ddSIgor Mammedov out: 3876ff9006ddSIgor Mammedov error_propagate(errp, local_err); 3877ff9006ddSIgor Mammedov } 3878ff9006ddSIgor Mammedov 3879bb2bdd81SGreg Kurz int spapr_phb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr, 3880bb2bdd81SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 3881bb2bdd81SGreg Kurz { 3882bb2bdd81SGreg Kurz sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(drc->dev); 3883bb2bdd81SGreg Kurz int intc_phandle; 3884bb2bdd81SGreg Kurz 3885bb2bdd81SGreg Kurz intc_phandle = spapr_irq_get_phandle(spapr, spapr->fdt_blob, errp); 3886bb2bdd81SGreg Kurz if (intc_phandle <= 0) { 3887bb2bdd81SGreg Kurz return -1; 3888bb2bdd81SGreg Kurz } 3889bb2bdd81SGreg Kurz 3890bb2bdd81SGreg Kurz if (spapr_populate_pci_dt(sphb, intc_phandle, fdt, spapr->irq->nr_msis, 3891bb2bdd81SGreg Kurz fdt_start_offset)) { 3892bb2bdd81SGreg Kurz error_setg(errp, "unable to create FDT node for PHB %d", sphb->index); 3893bb2bdd81SGreg Kurz return -1; 3894bb2bdd81SGreg Kurz } 3895bb2bdd81SGreg Kurz 3896bb2bdd81SGreg Kurz /* generally SLOF creates these, for hotplug it's up to QEMU */ 3897bb2bdd81SGreg Kurz _FDT(fdt_setprop_string(fdt, *fdt_start_offset, "name", "pci")); 3898bb2bdd81SGreg Kurz 3899bb2bdd81SGreg Kurz return 0; 3900bb2bdd81SGreg Kurz } 3901bb2bdd81SGreg Kurz 3902bb2bdd81SGreg Kurz static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3903bb2bdd81SGreg Kurz Error **errp) 3904bb2bdd81SGreg Kurz { 3905bb2bdd81SGreg Kurz sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3906bb2bdd81SGreg Kurz sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 3907bb2bdd81SGreg Kurz sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 3908bb2bdd81SGreg Kurz const unsigned windows_supported = spapr_phb_windows_supported(sphb); 3909bb2bdd81SGreg Kurz 3910bb2bdd81SGreg Kurz if (dev->hotplugged && !smc->dr_phb_enabled) { 3911bb2bdd81SGreg Kurz error_setg(errp, "PHB hotplug not supported for this machine"); 3912bb2bdd81SGreg Kurz return; 3913bb2bdd81SGreg Kurz } 3914bb2bdd81SGreg Kurz 3915bb2bdd81SGreg Kurz if (sphb->index == (uint32_t)-1) { 3916bb2bdd81SGreg Kurz error_setg(errp, "\"index\" for PAPR PHB is mandatory"); 3917bb2bdd81SGreg Kurz return; 3918bb2bdd81SGreg Kurz } 3919bb2bdd81SGreg Kurz 3920bb2bdd81SGreg Kurz /* 3921bb2bdd81SGreg Kurz * This will check that sphb->index doesn't exceed the maximum number of 3922bb2bdd81SGreg Kurz * PHBs for the current machine type. 3923bb2bdd81SGreg Kurz */ 3924bb2bdd81SGreg Kurz smc->phb_placement(spapr, sphb->index, 3925bb2bdd81SGreg Kurz &sphb->buid, &sphb->io_win_addr, 3926bb2bdd81SGreg Kurz &sphb->mem_win_addr, &sphb->mem64_win_addr, 3927bb2bdd81SGreg Kurz windows_supported, sphb->dma_liobn, errp); 3928bb2bdd81SGreg Kurz } 3929bb2bdd81SGreg Kurz 3930bb2bdd81SGreg Kurz static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3931bb2bdd81SGreg Kurz Error **errp) 3932bb2bdd81SGreg Kurz { 3933bb2bdd81SGreg Kurz sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3934bb2bdd81SGreg Kurz sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 3935bb2bdd81SGreg Kurz sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 3936bb2bdd81SGreg Kurz sPAPRDRConnector *drc; 3937bb2bdd81SGreg Kurz bool hotplugged = spapr_drc_hotplugged(dev); 3938bb2bdd81SGreg Kurz Error *local_err = NULL; 3939bb2bdd81SGreg Kurz 3940bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) { 3941bb2bdd81SGreg Kurz return; 3942bb2bdd81SGreg Kurz } 3943bb2bdd81SGreg Kurz 3944bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); 3945bb2bdd81SGreg Kurz /* hotplug hooks should check it's enabled before getting this far */ 3946bb2bdd81SGreg Kurz assert(drc); 3947bb2bdd81SGreg Kurz 3948bb2bdd81SGreg Kurz spapr_drc_attach(drc, DEVICE(dev), &local_err); 3949bb2bdd81SGreg Kurz if (local_err) { 3950bb2bdd81SGreg Kurz error_propagate(errp, local_err); 3951bb2bdd81SGreg Kurz return; 3952bb2bdd81SGreg Kurz } 3953bb2bdd81SGreg Kurz 3954bb2bdd81SGreg Kurz if (hotplugged) { 3955bb2bdd81SGreg Kurz spapr_hotplug_req_add_by_index(drc); 3956bb2bdd81SGreg Kurz } else { 3957bb2bdd81SGreg Kurz spapr_drc_reset(drc); 3958bb2bdd81SGreg Kurz } 3959bb2bdd81SGreg Kurz } 3960bb2bdd81SGreg Kurz 3961bb2bdd81SGreg Kurz void spapr_phb_release(DeviceState *dev) 3962bb2bdd81SGreg Kurz { 3963bb2bdd81SGreg Kurz HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3964bb2bdd81SGreg Kurz 3965bb2bdd81SGreg Kurz hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 396607578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 3967bb2bdd81SGreg Kurz } 3968bb2bdd81SGreg Kurz 3969bb2bdd81SGreg Kurz static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 3970bb2bdd81SGreg Kurz { 397107578b0aSDavid Hildenbrand object_property_set_bool(OBJECT(dev), false, "realized", NULL); 3972bb2bdd81SGreg Kurz } 3973bb2bdd81SGreg Kurz 3974bb2bdd81SGreg Kurz static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev, 3975bb2bdd81SGreg Kurz DeviceState *dev, Error **errp) 3976bb2bdd81SGreg Kurz { 3977bb2bdd81SGreg Kurz sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 3978bb2bdd81SGreg Kurz sPAPRDRConnector *drc; 3979bb2bdd81SGreg Kurz 3980bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); 3981bb2bdd81SGreg Kurz assert(drc); 3982bb2bdd81SGreg Kurz 3983bb2bdd81SGreg Kurz if (!spapr_drc_unplug_requested(drc)) { 3984bb2bdd81SGreg Kurz spapr_drc_detach(drc); 3985bb2bdd81SGreg Kurz spapr_hotplug_req_remove_by_index(drc); 3986bb2bdd81SGreg Kurz } 3987bb2bdd81SGreg Kurz } 3988bb2bdd81SGreg Kurz 3989c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, 3990c20d332aSBharata B Rao DeviceState *dev, Error **errp) 3991c20d332aSBharata B Rao { 3992c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 399381985f3bSDavid Hildenbrand spapr_memory_plug(hotplug_dev, dev, errp); 3994af81cf32SBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 3995af81cf32SBharata B Rao spapr_core_plug(hotplug_dev, dev, errp); 3996bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 3997bb2bdd81SGreg Kurz spapr_phb_plug(hotplug_dev, dev, errp); 3998c20d332aSBharata B Rao } 3999c20d332aSBharata B Rao } 4000c20d332aSBharata B Rao 400188432f44SDavid Hildenbrand static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, 400288432f44SDavid Hildenbrand DeviceState *dev, Error **errp) 400388432f44SDavid Hildenbrand { 40043ec71474SDavid Hildenbrand if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 40053ec71474SDavid Hildenbrand spapr_memory_unplug(hotplug_dev, dev); 4006a4261be1SDavid Hildenbrand } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4007a4261be1SDavid Hildenbrand spapr_core_unplug(hotplug_dev, dev); 4008bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4009bb2bdd81SGreg Kurz spapr_phb_unplug(hotplug_dev, dev); 40103ec71474SDavid Hildenbrand } 401188432f44SDavid Hildenbrand } 401288432f44SDavid Hildenbrand 4013cf632463SBharata B Rao static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev, 4014cf632463SBharata B Rao DeviceState *dev, Error **errp) 4015cf632463SBharata B Rao { 4016c86c1affSDaniel Henrique Barboza sPAPRMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev)); 4017c86c1affSDaniel Henrique Barboza MachineClass *mc = MACHINE_GET_CLASS(sms); 4018bb2bdd81SGreg Kurz sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4019cf632463SBharata B Rao 4020cf632463SBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 4021cf632463SBharata B Rao if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) { 4022cf632463SBharata B Rao spapr_memory_unplug_request(hotplug_dev, dev, errp); 4023cf632463SBharata B Rao } else { 4024cf632463SBharata B Rao /* NOTE: this means there is a window after guest reset, prior to 4025cf632463SBharata B Rao * CAS negotiation, where unplug requests will fail due to the 4026cf632463SBharata B Rao * capability not being detected yet. This is a bit different than 4027cf632463SBharata B Rao * the case with PCI unplug, where the events will be queued and 4028cf632463SBharata B Rao * eventually handled by the guest after boot 4029cf632463SBharata B Rao */ 4030cf632463SBharata B Rao error_setg(errp, "Memory hot unplug not supported for this guest"); 4031cf632463SBharata B Rao } 40326f4b5c3eSBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4033c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 40346f4b5c3eSBharata B Rao error_setg(errp, "CPU hot unplug not supported on this machine"); 40356f4b5c3eSBharata B Rao return; 40366f4b5c3eSBharata B Rao } 4037115debf2SIgor Mammedov spapr_core_unplug_request(hotplug_dev, dev, errp); 4038bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4039bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) { 4040bb2bdd81SGreg Kurz error_setg(errp, "PHB hot unplug not supported on this machine"); 4041bb2bdd81SGreg Kurz return; 4042bb2bdd81SGreg Kurz } 4043bb2bdd81SGreg Kurz spapr_phb_unplug_request(hotplug_dev, dev, errp); 4044c20d332aSBharata B Rao } 4045c20d332aSBharata B Rao } 4046c20d332aSBharata B Rao 404794a94e4cSBharata B Rao static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, 404894a94e4cSBharata B Rao DeviceState *dev, Error **errp) 404994a94e4cSBharata B Rao { 4050c871bc70SLaurent Vivier if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 4051c871bc70SLaurent Vivier spapr_memory_pre_plug(hotplug_dev, dev, errp); 4052c871bc70SLaurent Vivier } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 405394a94e4cSBharata B Rao spapr_core_pre_plug(hotplug_dev, dev, errp); 4054bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4055bb2bdd81SGreg Kurz spapr_phb_pre_plug(hotplug_dev, dev, errp); 405694a94e4cSBharata B Rao } 405794a94e4cSBharata B Rao } 405894a94e4cSBharata B Rao 40597ebaf795SBharata B Rao static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine, 4060c20d332aSBharata B Rao DeviceState *dev) 4061c20d332aSBharata B Rao { 406294a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || 4063bb2bdd81SGreg Kurz object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE) || 4064bb2bdd81SGreg Kurz object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4065c20d332aSBharata B Rao return HOTPLUG_HANDLER(machine); 4066c20d332aSBharata B Rao } 4067c20d332aSBharata B Rao return NULL; 4068c20d332aSBharata B Rao } 4069c20d332aSBharata B Rao 4070ea089eebSIgor Mammedov static CpuInstanceProperties 4071ea089eebSIgor Mammedov spapr_cpu_index_to_props(MachineState *machine, unsigned cpu_index) 407220bb648dSDavid Gibson { 4073ea089eebSIgor Mammedov CPUArchId *core_slot; 4074ea089eebSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 4075ea089eebSIgor Mammedov 4076ea089eebSIgor Mammedov /* make sure possible_cpu are intialized */ 4077ea089eebSIgor Mammedov mc->possible_cpu_arch_ids(machine); 4078ea089eebSIgor Mammedov /* get CPU core slot containing thread that matches cpu_index */ 4079ea089eebSIgor Mammedov core_slot = spapr_find_cpu_slot(machine, cpu_index, NULL); 4080ea089eebSIgor Mammedov assert(core_slot); 4081ea089eebSIgor Mammedov return core_slot->props; 408220bb648dSDavid Gibson } 408320bb648dSDavid Gibson 408479e07936SIgor Mammedov static int64_t spapr_get_default_cpu_node_id(const MachineState *ms, int idx) 408579e07936SIgor Mammedov { 408679e07936SIgor Mammedov return idx / smp_cores % nb_numa_nodes; 408779e07936SIgor Mammedov } 408879e07936SIgor Mammedov 4089535455fdSIgor Mammedov static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine) 4090535455fdSIgor Mammedov { 4091535455fdSIgor Mammedov int i; 4092d342eb76SIgor Mammedov const char *core_type; 4093535455fdSIgor Mammedov int spapr_max_cores = max_cpus / smp_threads; 4094535455fdSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 4095535455fdSIgor Mammedov 4096c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 4097535455fdSIgor Mammedov spapr_max_cores = QEMU_ALIGN_UP(smp_cpus, smp_threads) / smp_threads; 4098535455fdSIgor Mammedov } 4099535455fdSIgor Mammedov if (machine->possible_cpus) { 4100535455fdSIgor Mammedov assert(machine->possible_cpus->len == spapr_max_cores); 4101535455fdSIgor Mammedov return machine->possible_cpus; 4102535455fdSIgor Mammedov } 4103535455fdSIgor Mammedov 4104d342eb76SIgor Mammedov core_type = spapr_get_cpu_core_type(machine->cpu_type); 4105d342eb76SIgor Mammedov if (!core_type) { 4106d342eb76SIgor Mammedov error_report("Unable to find sPAPR CPU Core definition"); 4107d342eb76SIgor Mammedov exit(1); 4108d342eb76SIgor Mammedov } 4109d342eb76SIgor Mammedov 4110535455fdSIgor Mammedov machine->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + 4111535455fdSIgor Mammedov sizeof(CPUArchId) * spapr_max_cores); 4112535455fdSIgor Mammedov machine->possible_cpus->len = spapr_max_cores; 4113535455fdSIgor Mammedov for (i = 0; i < machine->possible_cpus->len; i++) { 4114535455fdSIgor Mammedov int core_id = i * smp_threads; 4115535455fdSIgor Mammedov 4116d342eb76SIgor Mammedov machine->possible_cpus->cpus[i].type = core_type; 4117f2d672c2SIgor Mammedov machine->possible_cpus->cpus[i].vcpus_count = smp_threads; 4118535455fdSIgor Mammedov machine->possible_cpus->cpus[i].arch_id = core_id; 4119535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.has_core_id = true; 4120535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.core_id = core_id; 4121535455fdSIgor Mammedov } 4122535455fdSIgor Mammedov return machine->possible_cpus; 4123535455fdSIgor Mammedov } 4124535455fdSIgor Mammedov 41256737d9adSDavid Gibson static void spapr_phb_placement(sPAPRMachineState *spapr, uint32_t index, 4126daa23699SDavid Gibson uint64_t *buid, hwaddr *pio, 4127daa23699SDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 41286737d9adSDavid Gibson unsigned n_dma, uint32_t *liobns, Error **errp) 41296737d9adSDavid Gibson { 4130357d1e3bSDavid Gibson /* 4131357d1e3bSDavid Gibson * New-style PHB window placement. 4132357d1e3bSDavid Gibson * 4133357d1e3bSDavid Gibson * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window 4134357d1e3bSDavid Gibson * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO 4135357d1e3bSDavid Gibson * windows. 4136357d1e3bSDavid Gibson * 4137357d1e3bSDavid Gibson * Some guest kernels can't work with MMIO windows above 1<<46 4138357d1e3bSDavid Gibson * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB 4139357d1e3bSDavid Gibson * 4140357d1e3bSDavid Gibson * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each 4141357d1e3bSDavid Gibson * PHB stacked together. (32TiB+2GiB)..(32TiB+64GiB) contains the 4142357d1e3bSDavid Gibson * 2GiB 32-bit MMIO windows for each PHB. Then 33..64TiB has the 4143357d1e3bSDavid Gibson * 1TiB 64-bit MMIO windows for each PHB. 4144357d1e3bSDavid Gibson */ 41456737d9adSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 41466737d9adSDavid Gibson int i; 41476737d9adSDavid Gibson 4148357d1e3bSDavid Gibson /* Sanity check natural alignments */ 4149357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 4150357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 4151357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0); 4152357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0); 4153357d1e3bSDavid Gibson /* Sanity check bounds */ 415425e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_IO_WIN_SIZE) > 415525e6a118SMichael S. Tsirkin SPAPR_PCI_MEM32_WIN_SIZE); 415625e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_MEM32_WIN_SIZE) > 415725e6a118SMichael S. Tsirkin SPAPR_PCI_MEM64_WIN_SIZE); 41582efff1c0SDavid Gibson 415925e6a118SMichael S. Tsirkin if (index >= SPAPR_MAX_PHBS) { 416025e6a118SMichael S. Tsirkin error_setg(errp, "\"index\" for PAPR PHB is too large (max %llu)", 416125e6a118SMichael S. Tsirkin SPAPR_MAX_PHBS - 1); 41626737d9adSDavid Gibson return; 41636737d9adSDavid Gibson } 41646737d9adSDavid Gibson 41656737d9adSDavid Gibson *buid = base_buid + index; 41666737d9adSDavid Gibson for (i = 0; i < n_dma; ++i) { 41676737d9adSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 41686737d9adSDavid Gibson } 41696737d9adSDavid Gibson 4170357d1e3bSDavid Gibson *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE; 4171357d1e3bSDavid Gibson *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE; 4172357d1e3bSDavid Gibson *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE; 41736737d9adSDavid Gibson } 41746737d9adSDavid Gibson 41757844e12bSCédric Le Goater static ICSState *spapr_ics_get(XICSFabric *dev, int irq) 41767844e12bSCédric Le Goater { 41777844e12bSCédric Le Goater sPAPRMachineState *spapr = SPAPR_MACHINE(dev); 41787844e12bSCédric Le Goater 41797844e12bSCédric Le Goater return ics_valid_irq(spapr->ics, irq) ? spapr->ics : NULL; 41807844e12bSCédric Le Goater } 41817844e12bSCédric Le Goater 41827844e12bSCédric Le Goater static void spapr_ics_resend(XICSFabric *dev) 41837844e12bSCédric Le Goater { 41847844e12bSCédric Le Goater sPAPRMachineState *spapr = SPAPR_MACHINE(dev); 41857844e12bSCédric Le Goater 41867844e12bSCédric Le Goater ics_resend(spapr->ics); 41877844e12bSCédric Le Goater } 41887844e12bSCédric Le Goater 418981210c20SSam Bobroff static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id) 4190b2fc59aaSCédric Le Goater { 41912e886fb3SSam Bobroff PowerPCCPU *cpu = spapr_find_cpu(vcpu_id); 4192b2fc59aaSCédric Le Goater 4193a28b9a5aSCédric Le Goater return cpu ? spapr_cpu_state(cpu)->icp : NULL; 4194b2fc59aaSCédric Le Goater } 4195b2fc59aaSCédric Le Goater 41966449da45SCédric Le Goater static void spapr_pic_print_info(InterruptStatsProvider *obj, 41976449da45SCédric Le Goater Monitor *mon) 41986449da45SCédric Le Goater { 41996449da45SCédric Le Goater sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 42006449da45SCédric Le Goater 42013ba3d0bcSCédric Le Goater spapr->irq->print_info(spapr, mon); 42026449da45SCédric Le Goater } 42036449da45SCédric Le Goater 420414bb4486SGreg Kurz int spapr_get_vcpu_id(PowerPCCPU *cpu) 42052e886fb3SSam Bobroff { 4206b1a568c1SGreg Kurz return cpu->vcpu_id; 42072e886fb3SSam Bobroff } 42082e886fb3SSam Bobroff 4209648edb64SGreg Kurz void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp) 4210648edb64SGreg Kurz { 4211648edb64SGreg Kurz sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 4212648edb64SGreg Kurz int vcpu_id; 4213648edb64SGreg Kurz 42145d0fb150SGreg Kurz vcpu_id = spapr_vcpu_id(spapr, cpu_index); 4215648edb64SGreg Kurz 4216648edb64SGreg Kurz if (kvm_enabled() && !kvm_vcpu_id_is_valid(vcpu_id)) { 4217648edb64SGreg Kurz error_setg(errp, "Can't create CPU with id %d in KVM", vcpu_id); 4218648edb64SGreg Kurz error_append_hint(errp, "Adjust the number of cpus to %d " 4219648edb64SGreg Kurz "or try to raise the number of threads per core\n", 4220648edb64SGreg Kurz vcpu_id * smp_threads / spapr->vsmt); 4221648edb64SGreg Kurz return; 4222648edb64SGreg Kurz } 4223648edb64SGreg Kurz 4224648edb64SGreg Kurz cpu->vcpu_id = vcpu_id; 4225648edb64SGreg Kurz } 4226648edb64SGreg Kurz 42272e886fb3SSam Bobroff PowerPCCPU *spapr_find_cpu(int vcpu_id) 42282e886fb3SSam Bobroff { 42292e886fb3SSam Bobroff CPUState *cs; 42302e886fb3SSam Bobroff 42312e886fb3SSam Bobroff CPU_FOREACH(cs) { 42322e886fb3SSam Bobroff PowerPCCPU *cpu = POWERPC_CPU(cs); 42332e886fb3SSam Bobroff 423414bb4486SGreg Kurz if (spapr_get_vcpu_id(cpu) == vcpu_id) { 42352e886fb3SSam Bobroff return cpu; 42362e886fb3SSam Bobroff } 42372e886fb3SSam Bobroff } 42382e886fb3SSam Bobroff 42392e886fb3SSam Bobroff return NULL; 42402e886fb3SSam Bobroff } 42412e886fb3SSam Bobroff 424229ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data) 424353018216SPaolo Bonzini { 424429ee3247SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 4245224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc); 424671461b0fSAlexey Kardashevskiy FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); 424734316482SAlexey Kardashevskiy NMIClass *nc = NMI_CLASS(oc); 4248c20d332aSBharata B Rao HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); 42491d1be34dSDavid Gibson PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc); 42507844e12bSCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 42516449da45SCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 425229ee3247SAlexey Kardashevskiy 42530eb9054cSDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant)"; 4254907aac2fSMark Cave-Ayland mc->ignore_boot_device_suffixes = true; 4255fc9f38c3SDavid Gibson 4256fc9f38c3SDavid Gibson /* 4257fc9f38c3SDavid Gibson * We set up the default / latest behaviour here. The class_init 4258fc9f38c3SDavid Gibson * functions for the specific versioned machine types can override 4259fc9f38c3SDavid Gibson * these details for backwards compatibility 4260fc9f38c3SDavid Gibson */ 4261bcb5ce08SDavid Gibson mc->init = spapr_machine_init; 4262bcb5ce08SDavid Gibson mc->reset = spapr_machine_reset; 4263958db90cSMarcel Apfelbaum mc->block_default_type = IF_SCSI; 42646244bb7eSGreg Kurz mc->max_cpus = 1024; 4265958db90cSMarcel Apfelbaum mc->no_parallel = 1; 42665b2128d2SAlexander Graf mc->default_boot_order = ""; 4267d23b6caaSPhilippe Mathieu-Daudé mc->default_ram_size = 512 * MiB; 426829f9cef3SSebastian Bauer mc->default_display = "std"; 4269958db90cSMarcel Apfelbaum mc->kvm_type = spapr_kvm_type; 42707da79a16SEduardo Habkost machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SPAPR_PCI_HOST_BRIDGE); 4271e4024630SLaurent Vivier mc->pci_allow_0_address = true; 4272debbdc00SIgor Mammedov assert(!mc->get_hotplug_handler); 42737ebaf795SBharata B Rao mc->get_hotplug_handler = spapr_get_hotplug_handler; 427494a94e4cSBharata B Rao hc->pre_plug = spapr_machine_device_pre_plug; 4275c20d332aSBharata B Rao hc->plug = spapr_machine_device_plug; 4276ea089eebSIgor Mammedov mc->cpu_index_to_instance_props = spapr_cpu_index_to_props; 427779e07936SIgor Mammedov mc->get_default_cpu_node_id = spapr_get_default_cpu_node_id; 4278535455fdSIgor Mammedov mc->possible_cpu_arch_ids = spapr_possible_cpu_arch_ids; 4279cf632463SBharata B Rao hc->unplug_request = spapr_machine_device_unplug_request; 428088432f44SDavid Hildenbrand hc->unplug = spapr_machine_device_unplug; 428100b4fbe2SMarcel Apfelbaum 4282fc9f38c3SDavid Gibson smc->dr_lmb_enabled = true; 4283fea35ca4SAlexey Kardashevskiy smc->update_dt_enabled = true; 428434a6b015SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 4285c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = true; 428652b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED; 428771461b0fSAlexey Kardashevskiy fwc->get_dev_path = spapr_get_fw_dev_path; 428834316482SAlexey Kardashevskiy nc->nmi_monitor_handler = spapr_nmi; 42896737d9adSDavid Gibson smc->phb_placement = spapr_phb_placement; 42901d1be34dSDavid Gibson vhc->hypercall = emulate_spapr_hypercall; 4291e57ca75cSDavid Gibson vhc->hpt_mask = spapr_hpt_mask; 4292e57ca75cSDavid Gibson vhc->map_hptes = spapr_map_hptes; 4293e57ca75cSDavid Gibson vhc->unmap_hptes = spapr_unmap_hptes; 4294e57ca75cSDavid Gibson vhc->store_hpte = spapr_store_hpte; 429579825f4dSBenjamin Herrenschmidt vhc->get_pate = spapr_get_pate; 42961ec26c75SGreg Kurz vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr; 42977844e12bSCédric Le Goater xic->ics_get = spapr_ics_get; 42987844e12bSCédric Le Goater xic->ics_resend = spapr_ics_resend; 4299b2fc59aaSCédric Le Goater xic->icp_get = spapr_icp_get; 43006449da45SCédric Le Goater ispc->print_info = spapr_pic_print_info; 430155641213SLaurent Vivier /* Force NUMA node memory size to be a multiple of 430255641213SLaurent Vivier * SPAPR_MEMORY_BLOCK_SIZE (256M) since that's the granularity 430355641213SLaurent Vivier * in which LMBs are represented and hot-added 430455641213SLaurent Vivier */ 430555641213SLaurent Vivier mc->numa_mem_align_shift = 28; 430633face6bSDavid Gibson 43074e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF; 43084e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON; 43094e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON; 4310*2782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND; 4311*2782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND; 4312*2782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_WORKAROUND; 43132309832aSDavid Gibson smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */ 4314b9a477b7SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF; 4315edaa7995SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON; 43168ff43ee4SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF; 431733face6bSDavid Gibson spapr_caps_add_properties(smc, &error_abort); 4318ef01ed9dSCédric Le Goater smc->irq = &spapr_irq_xics; 4319dae5e39aSMichael Roth smc->dr_phb_enabled = true; 432053018216SPaolo Bonzini } 432153018216SPaolo Bonzini 432229ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = { 432329ee3247SAlexey Kardashevskiy .name = TYPE_SPAPR_MACHINE, 432429ee3247SAlexey Kardashevskiy .parent = TYPE_MACHINE, 43254aee7362SDavid Gibson .abstract = true, 43266ca1502eSAlexey Kardashevskiy .instance_size = sizeof(sPAPRMachineState), 4327bcb5ce08SDavid Gibson .instance_init = spapr_instance_init, 432887bbdd9cSDavid Gibson .instance_finalize = spapr_machine_finalizefn, 4329183930c0SDavid Gibson .class_size = sizeof(sPAPRMachineClass), 433029ee3247SAlexey Kardashevskiy .class_init = spapr_machine_class_init, 433171461b0fSAlexey Kardashevskiy .interfaces = (InterfaceInfo[]) { 433271461b0fSAlexey Kardashevskiy { TYPE_FW_PATH_PROVIDER }, 433334316482SAlexey Kardashevskiy { TYPE_NMI }, 4334c20d332aSBharata B Rao { TYPE_HOTPLUG_HANDLER }, 43351d1be34dSDavid Gibson { TYPE_PPC_VIRTUAL_HYPERVISOR }, 43367844e12bSCédric Le Goater { TYPE_XICS_FABRIC }, 43376449da45SCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 433871461b0fSAlexey Kardashevskiy { } 433971461b0fSAlexey Kardashevskiy }, 434029ee3247SAlexey Kardashevskiy }; 434129ee3247SAlexey Kardashevskiy 4342fccbc785SDavid Gibson #define DEFINE_SPAPR_MACHINE(suffix, verstr, latest) \ 43435013c547SDavid Gibson static void spapr_machine_##suffix##_class_init(ObjectClass *oc, \ 43445013c547SDavid Gibson void *data) \ 43455013c547SDavid Gibson { \ 43465013c547SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); \ 43475013c547SDavid Gibson spapr_machine_##suffix##_class_options(mc); \ 4348fccbc785SDavid Gibson if (latest) { \ 4349fccbc785SDavid Gibson mc->alias = "pseries"; \ 4350fccbc785SDavid Gibson mc->is_default = 1; \ 4351fccbc785SDavid Gibson } \ 43525013c547SDavid Gibson } \ 43535013c547SDavid Gibson static const TypeInfo spapr_machine_##suffix##_info = { \ 43545013c547SDavid Gibson .name = MACHINE_TYPE_NAME("pseries-" verstr), \ 43555013c547SDavid Gibson .parent = TYPE_SPAPR_MACHINE, \ 43565013c547SDavid Gibson .class_init = spapr_machine_##suffix##_class_init, \ 43575013c547SDavid Gibson }; \ 43585013c547SDavid Gibson static void spapr_machine_register_##suffix(void) \ 43595013c547SDavid Gibson { \ 43605013c547SDavid Gibson type_register(&spapr_machine_##suffix##_info); \ 43615013c547SDavid Gibson } \ 43620e6aac87SEduardo Habkost type_init(spapr_machine_register_##suffix) 43635013c547SDavid Gibson 43641c5f29bbSDavid Gibson /* 436584e060bfSAlex Williamson * pseries-4.0 4366e2676b16SGreg Kurz */ 436784e060bfSAlex Williamson static void spapr_machine_4_0_class_options(MachineClass *mc) 4368e2676b16SGreg Kurz { 4369e2676b16SGreg Kurz /* Defaults for the latest behaviour inherited from the base class */ 4370e2676b16SGreg Kurz } 4371e2676b16SGreg Kurz 437284e060bfSAlex Williamson DEFINE_SPAPR_MACHINE(4_0, "4.0", true); 437384e060bfSAlex Williamson 437484e060bfSAlex Williamson /* 437584e060bfSAlex Williamson * pseries-3.1 437684e060bfSAlex Williamson */ 437788cbe073SMarc-André Lureau static void spapr_machine_3_1_class_options(MachineClass *mc) 437888cbe073SMarc-André Lureau { 4379fea35ca4SAlexey Kardashevskiy sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 438027461d69SPrasad J Pandit static GlobalProperty compat[] = { 438127461d69SPrasad J Pandit { TYPE_SPAPR_MACHINE, "host-model", "passthrough" }, 438227461d69SPrasad J Pandit { TYPE_SPAPR_MACHINE, "host-serial", "passthrough" }, 438327461d69SPrasad J Pandit }; 4384fea35ca4SAlexey Kardashevskiy 438584e060bfSAlex Williamson spapr_machine_4_0_class_options(mc); 4386abd93cc7SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len); 438727461d69SPrasad J Pandit compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 438827461d69SPrasad J Pandit 438934a6b015SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 4390fea35ca4SAlexey Kardashevskiy smc->update_dt_enabled = false; 4391dae5e39aSMichael Roth smc->dr_phb_enabled = false; 4392*2782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN; 4393*2782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN; 4394*2782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN; 4395edaa7995SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF; 439684e060bfSAlex Williamson } 439784e060bfSAlex Williamson 439884e060bfSAlex Williamson DEFINE_SPAPR_MACHINE(3_1, "3.1", false); 4399d45360d9SCédric Le Goater 4400d45360d9SCédric Le Goater /* 4401d45360d9SCédric Le Goater * pseries-3.0 4402d45360d9SCédric Le Goater */ 4403d45360d9SCédric Le Goater 4404d45360d9SCédric Le Goater static void spapr_machine_3_0_class_options(MachineClass *mc) 4405d45360d9SCédric Le Goater { 440682cffa2eSCédric Le Goater sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 440782cffa2eSCédric Le Goater 4408d45360d9SCédric Le Goater spapr_machine_3_1_class_options(mc); 4409ddb3235dSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len); 441082cffa2eSCédric Le Goater 441182cffa2eSCédric Le Goater smc->legacy_irq_allocation = true; 4412ae837402SCédric Le Goater smc->irq = &spapr_irq_xics_legacy; 4413d45360d9SCédric Le Goater } 4414d45360d9SCédric Le Goater 4415d45360d9SCédric Le Goater DEFINE_SPAPR_MACHINE(3_0, "3.0", false); 44168a4fd427SDavid Gibson 44178a4fd427SDavid Gibson /* 44188a4fd427SDavid Gibson * pseries-2.12 44198a4fd427SDavid Gibson */ 442088cbe073SMarc-André Lureau static void spapr_machine_2_12_class_options(MachineClass *mc) 442188cbe073SMarc-André Lureau { 442288cbe073SMarc-André Lureau sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 442388cbe073SMarc-André Lureau static GlobalProperty compat[] = { 44246c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-3.0-migration", "on" }, 44256c36bddfSEduardo Habkost { TYPE_SPAPR_CPU_CORE, "pre-3.0-migration", "on" }, 4426fa386d98SMarc-André Lureau }; 44278a4fd427SDavid Gibson 4428d8c0c7afSPeter Maydell spapr_machine_3_0_class_options(mc); 44290d47310bSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_12, hw_compat_2_12_len); 443088cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 44312309832aSDavid Gibson 4432e8937295SGreg Kurz /* We depend on kvm_enabled() to choose a default value for the 4433e8937295SGreg Kurz * hpt-max-page-size capability. Of course we can't do it here 4434e8937295SGreg Kurz * because this is too early and the HW accelerator isn't initialzed 4435e8937295SGreg Kurz * yet. Postpone this to machine init (see default_caps_with_cpu()). 4436e8937295SGreg Kurz */ 4437e8937295SGreg Kurz smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 0; 44388a4fd427SDavid Gibson } 44398a4fd427SDavid Gibson 44408a4fd427SDavid Gibson DEFINE_SPAPR_MACHINE(2_12, "2.12", false); 44412b615412SDavid Gibson 4442813f3cf6SSuraj Jitindar Singh static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc) 4443813f3cf6SSuraj Jitindar Singh { 4444813f3cf6SSuraj Jitindar Singh sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4445813f3cf6SSuraj Jitindar Singh 4446813f3cf6SSuraj Jitindar Singh spapr_machine_2_12_class_options(mc); 4447813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND; 4448813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND; 4449813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_FIXED_CCD; 4450813f3cf6SSuraj Jitindar Singh } 4451813f3cf6SSuraj Jitindar Singh 4452813f3cf6SSuraj Jitindar Singh DEFINE_SPAPR_MACHINE(2_12_sxxm, "2.12-sxxm", false); 4453813f3cf6SSuraj Jitindar Singh 44542b615412SDavid Gibson /* 44552b615412SDavid Gibson * pseries-2.11 44562b615412SDavid Gibson */ 44572b615412SDavid Gibson 44582b615412SDavid Gibson static void spapr_machine_2_11_class_options(MachineClass *mc) 44592b615412SDavid Gibson { 4460ee76a09fSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4461ee76a09fSDavid Gibson 44622b615412SDavid Gibson spapr_machine_2_12_class_options(mc); 44634e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON; 446443df70a9SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len); 44652b615412SDavid Gibson } 44662b615412SDavid Gibson 44672b615412SDavid Gibson DEFINE_SPAPR_MACHINE(2_11, "2.11", false); 4468e2676b16SGreg Kurz 4469e2676b16SGreg Kurz /* 44703fa14fbeSDavid Gibson * pseries-2.10 4471db800b21SDavid Gibson */ 4472e2676b16SGreg Kurz 44733fa14fbeSDavid Gibson static void spapr_machine_2_10_class_options(MachineClass *mc) 4474db800b21SDavid Gibson { 4475e2676b16SGreg Kurz spapr_machine_2_11_class_options(mc); 4476503224f4SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_10, hw_compat_2_10_len); 4477db800b21SDavid Gibson } 4478db800b21SDavid Gibson 4479e2676b16SGreg Kurz DEFINE_SPAPR_MACHINE(2_10, "2.10", false); 44803fa14fbeSDavid Gibson 44813fa14fbeSDavid Gibson /* 44823fa14fbeSDavid Gibson * pseries-2.9 44833fa14fbeSDavid Gibson */ 448488cbe073SMarc-André Lureau 448588cbe073SMarc-André Lureau static void spapr_machine_2_9_class_options(MachineClass *mc) 448688cbe073SMarc-André Lureau { 448788cbe073SMarc-André Lureau sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 448888cbe073SMarc-André Lureau static GlobalProperty compat[] = { 44896c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-2.10-migration", "on" }, 4490fa386d98SMarc-André Lureau }; 44913fa14fbeSDavid Gibson 44923fa14fbeSDavid Gibson spapr_machine_2_10_class_options(mc); 44933e803152SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len); 449488cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 44953bfe5716SLaurent Vivier mc->numa_auto_assign_ram = numa_legacy_auto_assign_ram; 449646f7afa3SGreg Kurz smc->pre_2_10_has_unused_icps = true; 449752b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED; 44983fa14fbeSDavid Gibson } 44993fa14fbeSDavid Gibson 45003fa14fbeSDavid Gibson DEFINE_SPAPR_MACHINE(2_9, "2.9", false); 4501fa325e6cSDavid Gibson 4502fa325e6cSDavid Gibson /* 4503fa325e6cSDavid Gibson * pseries-2.8 4504fa325e6cSDavid Gibson */ 450588cbe073SMarc-André Lureau 450688cbe073SMarc-André Lureau static void spapr_machine_2_8_class_options(MachineClass *mc) 450788cbe073SMarc-André Lureau { 450888cbe073SMarc-André Lureau static GlobalProperty compat[] = { 45096c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "pcie-extended-configuration-space", "off" }, 4510fa386d98SMarc-André Lureau }; 4511fa325e6cSDavid Gibson 4512fa325e6cSDavid Gibson spapr_machine_2_9_class_options(mc); 4513edc24ccdSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len); 451488cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 451555641213SLaurent Vivier mc->numa_mem_align_shift = 23; 4516fa325e6cSDavid Gibson } 4517fa325e6cSDavid Gibson 4518fa325e6cSDavid Gibson DEFINE_SPAPR_MACHINE(2_8, "2.8", false); 4519db800b21SDavid Gibson 4520db800b21SDavid Gibson /* 45211ea1eefcSBharata B Rao * pseries-2.7 45221ea1eefcSBharata B Rao */ 4523357d1e3bSDavid Gibson 4524357d1e3bSDavid Gibson static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index, 4525357d1e3bSDavid Gibson uint64_t *buid, hwaddr *pio, 4526357d1e3bSDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 4527357d1e3bSDavid Gibson unsigned n_dma, uint32_t *liobns, Error **errp) 4528357d1e3bSDavid Gibson { 4529357d1e3bSDavid Gibson /* Legacy PHB placement for pseries-2.7 and earlier machine types */ 4530357d1e3bSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 4531357d1e3bSDavid Gibson const hwaddr phb_spacing = 0x1000000000ULL; /* 64 GiB */ 4532357d1e3bSDavid Gibson const hwaddr mmio_offset = 0xa0000000; /* 2 GiB + 512 MiB */ 4533357d1e3bSDavid Gibson const hwaddr pio_offset = 0x80000000; /* 2 GiB */ 4534357d1e3bSDavid Gibson const uint32_t max_index = 255; 4535357d1e3bSDavid Gibson const hwaddr phb0_alignment = 0x10000000000ULL; /* 1 TiB */ 4536357d1e3bSDavid Gibson 4537357d1e3bSDavid Gibson uint64_t ram_top = MACHINE(spapr)->ram_size; 4538357d1e3bSDavid Gibson hwaddr phb0_base, phb_base; 4539357d1e3bSDavid Gibson int i; 4540357d1e3bSDavid Gibson 45410c9269a5SDavid Hildenbrand /* Do we have device memory? */ 4542357d1e3bSDavid Gibson if (MACHINE(spapr)->maxram_size > ram_top) { 4543357d1e3bSDavid Gibson /* Can't just use maxram_size, because there may be an 45440c9269a5SDavid Hildenbrand * alignment gap between normal and device memory regions 45450c9269a5SDavid Hildenbrand */ 4546b0c14ec4SDavid Hildenbrand ram_top = MACHINE(spapr)->device_memory->base + 4547b0c14ec4SDavid Hildenbrand memory_region_size(&MACHINE(spapr)->device_memory->mr); 4548357d1e3bSDavid Gibson } 4549357d1e3bSDavid Gibson 4550357d1e3bSDavid Gibson phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment); 4551357d1e3bSDavid Gibson 4552357d1e3bSDavid Gibson if (index > max_index) { 4553357d1e3bSDavid Gibson error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", 4554357d1e3bSDavid Gibson max_index); 4555357d1e3bSDavid Gibson return; 4556357d1e3bSDavid Gibson } 4557357d1e3bSDavid Gibson 4558357d1e3bSDavid Gibson *buid = base_buid + index; 4559357d1e3bSDavid Gibson for (i = 0; i < n_dma; ++i) { 4560357d1e3bSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 4561357d1e3bSDavid Gibson } 4562357d1e3bSDavid Gibson 4563357d1e3bSDavid Gibson phb_base = phb0_base + index * phb_spacing; 4564357d1e3bSDavid Gibson *pio = phb_base + pio_offset; 4565357d1e3bSDavid Gibson *mmio32 = phb_base + mmio_offset; 4566357d1e3bSDavid Gibson /* 4567357d1e3bSDavid Gibson * We don't set the 64-bit MMIO window, relying on the PHB's 4568357d1e3bSDavid Gibson * fallback behaviour of automatically splitting a large "32-bit" 4569357d1e3bSDavid Gibson * window into contiguous 32-bit and 64-bit windows 4570357d1e3bSDavid Gibson */ 4571357d1e3bSDavid Gibson } 4572db800b21SDavid Gibson 45731ea1eefcSBharata B Rao static void spapr_machine_2_7_class_options(MachineClass *mc) 45741ea1eefcSBharata B Rao { 45753daa4a9fSThomas Huth sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 457688cbe073SMarc-André Lureau static GlobalProperty compat[] = { 45776c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0xf80000000", }, 45786c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem64_win_size", "0", }, 45796c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-2.8-migration", "on", }, 45806c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-2.8-migration", "on", }, 458188cbe073SMarc-André Lureau }; 45823daa4a9fSThomas Huth 4583db800b21SDavid Gibson spapr_machine_2_8_class_options(mc); 45842e9c10ebSIgor Mammedov mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power7_v2.3"); 4585a140c199SEduardo Habkost mc->default_machine_opts = "modern-hotplug-events=off"; 45865a995064SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_7, hw_compat_2_7_len); 458788cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 4588357d1e3bSDavid Gibson smc->phb_placement = phb_placement_2_7; 45891ea1eefcSBharata B Rao } 45901ea1eefcSBharata B Rao 4591db800b21SDavid Gibson DEFINE_SPAPR_MACHINE(2_7, "2.7", false); 45921ea1eefcSBharata B Rao 45931ea1eefcSBharata B Rao /* 45944b23699cSDavid Gibson * pseries-2.6 45954b23699cSDavid Gibson */ 459688cbe073SMarc-André Lureau 459788cbe073SMarc-André Lureau static void spapr_machine_2_6_class_options(MachineClass *mc) 459888cbe073SMarc-André Lureau { 459988cbe073SMarc-André Lureau static GlobalProperty compat[] = { 46006c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "ddw", "off" }, 4601fa386d98SMarc-André Lureau }; 46021ea1eefcSBharata B Rao 46031ea1eefcSBharata B Rao spapr_machine_2_7_class_options(mc); 4604c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = false; 4605ff8f261fSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_6, hw_compat_2_6_len); 460688cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 46074b23699cSDavid Gibson } 46084b23699cSDavid Gibson 46091ea1eefcSBharata B Rao DEFINE_SPAPR_MACHINE(2_6, "2.6", false); 46104b23699cSDavid Gibson 46114b23699cSDavid Gibson /* 46121c5f29bbSDavid Gibson * pseries-2.5 46131c5f29bbSDavid Gibson */ 461488cbe073SMarc-André Lureau 461588cbe073SMarc-André Lureau static void spapr_machine_2_5_class_options(MachineClass *mc) 461688cbe073SMarc-André Lureau { 461788cbe073SMarc-André Lureau sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 461888cbe073SMarc-André Lureau static GlobalProperty compat[] = { 46196c36bddfSEduardo Habkost { "spapr-vlan", "use-rx-buffer-pools", "off" }, 4620fa386d98SMarc-André Lureau }; 46214b23699cSDavid Gibson 46224b23699cSDavid Gibson spapr_machine_2_6_class_options(mc); 462357040d45SThomas Huth smc->use_ohci_by_default = true; 4624fe759610SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_5, hw_compat_2_5_len); 462588cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 46261c5f29bbSDavid Gibson } 46271c5f29bbSDavid Gibson 46284b23699cSDavid Gibson DEFINE_SPAPR_MACHINE(2_5, "2.5", false); 46291c5f29bbSDavid Gibson 46301c5f29bbSDavid Gibson /* 46311c5f29bbSDavid Gibson * pseries-2.4 46321c5f29bbSDavid Gibson */ 463380fd50f9SCornelia Huck 46345013c547SDavid Gibson static void spapr_machine_2_4_class_options(MachineClass *mc) 46355013c547SDavid Gibson { 4636fc9f38c3SDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4637fc9f38c3SDavid Gibson 4638fc9f38c3SDavid Gibson spapr_machine_2_5_class_options(mc); 4639fc9f38c3SDavid Gibson smc->dr_lmb_enabled = false; 46402f99b9c2SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_4, hw_compat_2_4_len); 46411c5f29bbSDavid Gibson } 46421c5f29bbSDavid Gibson 4643fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_4, "2.4", false); 46441c5f29bbSDavid Gibson 46451c5f29bbSDavid Gibson /* 46461c5f29bbSDavid Gibson * pseries-2.3 46471c5f29bbSDavid Gibson */ 464888cbe073SMarc-André Lureau 464988cbe073SMarc-André Lureau static void spapr_machine_2_3_class_options(MachineClass *mc) 465088cbe073SMarc-André Lureau { 465188cbe073SMarc-André Lureau static GlobalProperty compat[] = { 46526c36bddfSEduardo Habkost { "spapr-pci-host-bridge", "dynamic-reconfiguration", "off" }, 4653fa386d98SMarc-André Lureau }; 4654fc9f38c3SDavid Gibson spapr_machine_2_4_class_options(mc); 46558995dd90SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_3, hw_compat_2_3_len); 465688cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 46571c5f29bbSDavid Gibson } 4658fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_3, "2.3", false); 46591c5f29bbSDavid Gibson 46601c5f29bbSDavid Gibson /* 46611c5f29bbSDavid Gibson * pseries-2.2 46621c5f29bbSDavid Gibson */ 466388cbe073SMarc-André Lureau 466488cbe073SMarc-André Lureau static void spapr_machine_2_2_class_options(MachineClass *mc) 466588cbe073SMarc-André Lureau { 466688cbe073SMarc-André Lureau static GlobalProperty compat[] = { 46676c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0x20000000" }, 4668fa386d98SMarc-André Lureau }; 4669b194df47SAlexey Kardashevskiy 4670fc9f38c3SDavid Gibson spapr_machine_2_3_class_options(mc); 46711c30044eSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_2, hw_compat_2_2_len); 467288cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 4673f6d0656bSEduardo Habkost mc->default_machine_opts = "modern-hotplug-events=off,suppress-vmdesc=on"; 46741c5f29bbSDavid Gibson } 4675fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_2, "2.2", false); 46761c5f29bbSDavid Gibson 46771c5f29bbSDavid Gibson /* 46781c5f29bbSDavid Gibson * pseries-2.1 46791c5f29bbSDavid Gibson */ 46801c5f29bbSDavid Gibson 46815013c547SDavid Gibson static void spapr_machine_2_1_class_options(MachineClass *mc) 4682b0e966d0SJason Wang { 4683fc9f38c3SDavid Gibson spapr_machine_2_2_class_options(mc); 4684c4fc5695SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_1, hw_compat_2_1_len); 46856026db45SAlexey Kardashevskiy } 4686fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_1, "2.1", false); 46876026db45SAlexey Kardashevskiy 468829ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void) 468929ee3247SAlexey Kardashevskiy { 469029ee3247SAlexey Kardashevskiy type_register_static(&spapr_machine_info); 469129ee3247SAlexey Kardashevskiy } 469229ee3247SAlexey Kardashevskiy 469329ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types) 4694