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 */ 26a8d25326SMarkus Armbruster 270d75590dSPeter Maydell #include "qemu/osdep.h" 28a8d25326SMarkus Armbruster #include "qemu-common.h" 29da34e65cSMarkus Armbruster #include "qapi/error.h" 30fa98fbfcSSam Bobroff #include "qapi/visitor.h" 3153018216SPaolo Bonzini #include "sysemu/sysemu.h" 32b58c5c2dSMarkus Armbruster #include "sysemu/hostmem.h" 33e35704baSEduardo Habkost #include "sysemu/numa.h" 3423ff81bdSGreg Kurz #include "sysemu/qtest.h" 3571e8a915SMarkus Armbruster #include "sysemu/reset.h" 3654d31236SMarkus Armbruster #include "sysemu/runstate.h" 3703dd024fSPaolo Bonzini #include "qemu/log.h" 3871461b0fSAlexey Kardashevskiy #include "hw/fw-path-provider.h" 3953018216SPaolo Bonzini #include "elf.h" 4053018216SPaolo Bonzini #include "net/net.h" 41ad440b4aSAndrew Jones #include "sysemu/device_tree.h" 4253018216SPaolo Bonzini #include "sysemu/cpus.h" 43b3946626SVincent Palatin #include "sysemu/hw_accel.h" 4453018216SPaolo Bonzini #include "kvm_ppc.h" 45c4b63b7cSJuan Quintela #include "migration/misc.h" 46ca77ee28SMarkus Armbruster #include "migration/qemu-file-types.h" 4784a899deSJuan Quintela #include "migration/global_state.h" 48f2a8f0a6SJuan Quintela #include "migration/register.h" 494be21d56SDavid Gibson #include "mmu-hash64.h" 50b4db5413SSuraj Jitindar Singh #include "mmu-book3s-v3.h" 517abd43baSSuraj Jitindar Singh #include "cpu-models.h" 522e5b09fdSMarkus Armbruster #include "hw/core/cpu.h" 5353018216SPaolo Bonzini 5453018216SPaolo Bonzini #include "hw/boards.h" 550d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h" 5653018216SPaolo Bonzini #include "hw/loader.h" 5753018216SPaolo Bonzini 587804c353SCédric Le Goater #include "hw/ppc/fdt.h" 590d09e41aSPaolo Bonzini #include "hw/ppc/spapr.h" 600d09e41aSPaolo Bonzini #include "hw/ppc/spapr_vio.h" 61a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 620d09e41aSPaolo Bonzini #include "hw/pci-host/spapr.h" 6353018216SPaolo Bonzini #include "hw/pci/msi.h" 6453018216SPaolo Bonzini 6553018216SPaolo Bonzini #include "hw/pci/pci.h" 6671461b0fSAlexey Kardashevskiy #include "hw/scsi/scsi.h" 6771461b0fSAlexey Kardashevskiy #include "hw/virtio/virtio-scsi.h" 68c4e13492SFelipe Franciosi #include "hw/virtio/vhost-scsi-common.h" 6953018216SPaolo Bonzini 7053018216SPaolo Bonzini #include "exec/address-spaces.h" 712309832aSDavid Gibson #include "exec/ram_addr.h" 7253018216SPaolo Bonzini #include "hw/usb.h" 7353018216SPaolo Bonzini #include "qemu/config-file.h" 74135a129aSAneesh Kumar K.V #include "qemu/error-report.h" 752a6593cbSAlexey Kardashevskiy #include "trace.h" 7634316482SAlexey Kardashevskiy #include "hw/nmi.h" 776449da45SCédric Le Goater #include "hw/intc/intc.h" 7853018216SPaolo Bonzini 79f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 8094a94e4cSBharata B Rao #include "hw/ppc/spapr_cpu_core.h" 812cc0e2e8SDavid Hildenbrand #include "hw/mem/memory-device.h" 820fb6bd07SMichael Roth #include "hw/ppc/spapr_tpm_proxy.h" 8368a27b20SMichael S. Tsirkin 8453018216SPaolo Bonzini #include <libfdt.h> 8553018216SPaolo Bonzini 8653018216SPaolo Bonzini /* SLOF memory layout: 8753018216SPaolo Bonzini * 8853018216SPaolo Bonzini * SLOF raw image loaded at 0, copies its romfs right below the flat 8953018216SPaolo Bonzini * device-tree, then position SLOF itself 31M below that 9053018216SPaolo Bonzini * 9153018216SPaolo Bonzini * So we set FW_OVERHEAD to 40MB which should account for all of that 9253018216SPaolo Bonzini * and more 9353018216SPaolo Bonzini * 9453018216SPaolo Bonzini * We load our kernel at 4M, leaving space for SLOF initial image 9553018216SPaolo Bonzini */ 9638b02bd8SAlexey Kardashevskiy #define FDT_MAX_SIZE 0x100000 9753018216SPaolo Bonzini #define RTAS_MAX_SIZE 0x10000 98b7d1f77aSBenjamin Herrenschmidt #define RTAS_MAX_ADDR 0x80000000 /* RTAS must stay below that */ 9953018216SPaolo Bonzini #define FW_MAX_SIZE 0x400000 10053018216SPaolo Bonzini #define FW_FILE_NAME "slof.bin" 10153018216SPaolo Bonzini #define FW_OVERHEAD 0x2800000 10253018216SPaolo Bonzini #define KERNEL_LOAD_ADDR FW_MAX_SIZE 10353018216SPaolo Bonzini 10453018216SPaolo Bonzini #define MIN_RMA_SLOF 128UL 10553018216SPaolo Bonzini 1065c7adcf4SGreg Kurz #define PHANDLE_INTC 0x00001111 10753018216SPaolo Bonzini 1085d0fb150SGreg Kurz /* These two functions implement the VCPU id numbering: one to compute them 1095d0fb150SGreg Kurz * all and one to identify thread 0 of a VCORE. Any change to the first one 1105d0fb150SGreg Kurz * is likely to have an impact on the second one, so let's keep them close. 1115d0fb150SGreg Kurz */ 112ce2918cbSDavid Gibson static int spapr_vcpu_id(SpaprMachineState *spapr, int cpu_index) 1135d0fb150SGreg Kurz { 114fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 115fe6b6346SLike Xu unsigned int smp_threads = ms->smp.threads; 116fe6b6346SLike Xu 1171a5008fcSGreg Kurz assert(spapr->vsmt); 1185d0fb150SGreg Kurz return 1195d0fb150SGreg Kurz (cpu_index / smp_threads) * spapr->vsmt + cpu_index % smp_threads; 1205d0fb150SGreg Kurz } 121ce2918cbSDavid Gibson static bool spapr_is_thread0_in_vcore(SpaprMachineState *spapr, 1225d0fb150SGreg Kurz PowerPCCPU *cpu) 1235d0fb150SGreg Kurz { 1241a5008fcSGreg Kurz assert(spapr->vsmt); 1255d0fb150SGreg Kurz return spapr_get_vcpu_id(cpu) % spapr->vsmt == 0; 1265d0fb150SGreg Kurz } 1275d0fb150SGreg Kurz 12846f7afa3SGreg Kurz static bool pre_2_10_vmstate_dummy_icp_needed(void *opaque) 12946f7afa3SGreg Kurz { 13046f7afa3SGreg Kurz /* Dummy entries correspond to unused ICPState objects in older QEMUs, 13146f7afa3SGreg Kurz * and newer QEMUs don't even have them. In both cases, we don't want 13246f7afa3SGreg Kurz * to send anything on the wire. 13346f7afa3SGreg Kurz */ 13446f7afa3SGreg Kurz return false; 13546f7afa3SGreg Kurz } 13646f7afa3SGreg Kurz 13746f7afa3SGreg Kurz static const VMStateDescription pre_2_10_vmstate_dummy_icp = { 13846f7afa3SGreg Kurz .name = "icp/server", 13946f7afa3SGreg Kurz .version_id = 1, 14046f7afa3SGreg Kurz .minimum_version_id = 1, 14146f7afa3SGreg Kurz .needed = pre_2_10_vmstate_dummy_icp_needed, 14246f7afa3SGreg Kurz .fields = (VMStateField[]) { 14346f7afa3SGreg Kurz VMSTATE_UNUSED(4), /* uint32_t xirr */ 14446f7afa3SGreg Kurz VMSTATE_UNUSED(1), /* uint8_t pending_priority */ 14546f7afa3SGreg Kurz VMSTATE_UNUSED(1), /* uint8_t mfrr */ 14646f7afa3SGreg Kurz VMSTATE_END_OF_LIST() 14746f7afa3SGreg Kurz }, 14846f7afa3SGreg Kurz }; 14946f7afa3SGreg Kurz 15046f7afa3SGreg Kurz static void pre_2_10_vmstate_register_dummy_icp(int i) 15146f7afa3SGreg Kurz { 15246f7afa3SGreg Kurz vmstate_register(NULL, i, &pre_2_10_vmstate_dummy_icp, 15346f7afa3SGreg Kurz (void *)(uintptr_t) i); 15446f7afa3SGreg Kurz } 15546f7afa3SGreg Kurz 15646f7afa3SGreg Kurz static void pre_2_10_vmstate_unregister_dummy_icp(int i) 15746f7afa3SGreg Kurz { 15846f7afa3SGreg Kurz vmstate_unregister(NULL, &pre_2_10_vmstate_dummy_icp, 15946f7afa3SGreg Kurz (void *)(uintptr_t) i); 16046f7afa3SGreg Kurz } 16146f7afa3SGreg Kurz 162ce2918cbSDavid Gibson int spapr_max_server_number(SpaprMachineState *spapr) 16346f7afa3SGreg Kurz { 164fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 165fe6b6346SLike Xu 1661a5008fcSGreg Kurz assert(spapr->vsmt); 167fe6b6346SLike Xu return DIV_ROUND_UP(ms->smp.max_cpus * spapr->vsmt, ms->smp.threads); 16846f7afa3SGreg Kurz } 16946f7afa3SGreg Kurz 170833d4668SAlexey Kardashevskiy static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, 171833d4668SAlexey Kardashevskiy int smt_threads) 172833d4668SAlexey Kardashevskiy { 173833d4668SAlexey Kardashevskiy int i, ret = 0; 174833d4668SAlexey Kardashevskiy uint32_t servers_prop[smt_threads]; 175833d4668SAlexey Kardashevskiy uint32_t gservers_prop[smt_threads * 2]; 17614bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 177833d4668SAlexey Kardashevskiy 178d6e166c0SDavid Gibson if (cpu->compat_pvr) { 179d6e166c0SDavid Gibson ret = fdt_setprop_cell(fdt, offset, "cpu-version", cpu->compat_pvr); 1806d9412eaSAlexey Kardashevskiy if (ret < 0) { 1816d9412eaSAlexey Kardashevskiy return ret; 1826d9412eaSAlexey Kardashevskiy } 1836d9412eaSAlexey Kardashevskiy } 1846d9412eaSAlexey Kardashevskiy 185833d4668SAlexey Kardashevskiy /* Build interrupt servers and gservers properties */ 186833d4668SAlexey Kardashevskiy for (i = 0; i < smt_threads; i++) { 187833d4668SAlexey Kardashevskiy servers_prop[i] = cpu_to_be32(index + i); 188833d4668SAlexey Kardashevskiy /* Hack, direct the group queues back to cpu 0 */ 189833d4668SAlexey Kardashevskiy gservers_prop[i*2] = cpu_to_be32(index + i); 190833d4668SAlexey Kardashevskiy gservers_prop[i*2 + 1] = 0; 191833d4668SAlexey Kardashevskiy } 192833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 193833d4668SAlexey Kardashevskiy servers_prop, sizeof(servers_prop)); 194833d4668SAlexey Kardashevskiy if (ret < 0) { 195833d4668SAlexey Kardashevskiy return ret; 196833d4668SAlexey Kardashevskiy } 197833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-gserver#s", 198833d4668SAlexey Kardashevskiy gservers_prop, sizeof(gservers_prop)); 199833d4668SAlexey Kardashevskiy 200833d4668SAlexey Kardashevskiy return ret; 201833d4668SAlexey Kardashevskiy } 202833d4668SAlexey Kardashevskiy 20399861ecbSIgor Mammedov static int spapr_fixup_cpu_numa_dt(void *fdt, int offset, PowerPCCPU *cpu) 2040da6f3feSBharata B Rao { 20514bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 2060da6f3feSBharata B Rao uint32_t associativity[] = {cpu_to_be32(0x5), 2070da6f3feSBharata B Rao cpu_to_be32(0x0), 2080da6f3feSBharata B Rao cpu_to_be32(0x0), 2090da6f3feSBharata B Rao cpu_to_be32(0x0), 21015f8b142SIgor Mammedov cpu_to_be32(cpu->node_id), 2110da6f3feSBharata B Rao cpu_to_be32(index)}; 2120da6f3feSBharata B Rao 2130da6f3feSBharata B Rao /* Advertise NUMA via ibm,associativity */ 21499861ecbSIgor Mammedov return fdt_setprop(fdt, offset, "ibm,associativity", associativity, 2150da6f3feSBharata B Rao sizeof(associativity)); 2160da6f3feSBharata B Rao } 2170da6f3feSBharata B Rao 21886d5771aSSam Bobroff /* Populate the "ibm,pa-features" property */ 219ce2918cbSDavid Gibson static void spapr_populate_pa_features(SpaprMachineState *spapr, 220ee76a09fSDavid Gibson PowerPCCPU *cpu, 221ee76a09fSDavid Gibson void *fdt, int offset, 222e957f6a9SSam Bobroff bool legacy_guest) 22386d5771aSSam Bobroff { 22486d5771aSSam Bobroff uint8_t pa_features_206[] = { 6, 0, 22586d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 }; 22686d5771aSSam Bobroff uint8_t pa_features_207[] = { 24, 0, 22786d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, 22886d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 22986d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 23086d5771aSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 }; 2319fb4541fSSam Bobroff uint8_t pa_features_300[] = { 66, 0, 2329fb4541fSSam Bobroff /* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */ 2339fb4541fSSam Bobroff /* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, SSO, 5: LE|CFAR|EB|LSQ */ 23486d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, /* 0 - 5 */ 2359fb4541fSSam Bobroff /* 6: DS207 */ 23686d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */ 2379fb4541fSSam Bobroff /* 16: Vector */ 23886d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */ 2399fb4541fSSam Bobroff /* 18: Vec. Scalar, 20: Vec. XOR, 22: HTM */ 2409bf502feSDavid Gibson 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */ 2419fb4541fSSam Bobroff /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */ 2429fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */ 2439fb4541fSSam Bobroff /* 30: MMR, 32: LE atomic, 34: EBB + ext EBB */ 2449fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */ 2459fb4541fSSam Bobroff /* 36: SPR SO, 38: Copy/Paste, 40: Radix MMU */ 2469fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 36 - 41 */ 2479fb4541fSSam Bobroff /* 42: PM, 44: PC RA, 46: SC vec'd */ 2489fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */ 2499fb4541fSSam Bobroff /* 48: SIMD, 50: QP BFP, 52: String */ 2509fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */ 2519fb4541fSSam Bobroff /* 54: DecFP, 56: DecI, 58: SHA */ 2529fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */ 2539fb4541fSSam Bobroff /* 60: NM atomic, 62: RNG */ 2549fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */ 2559fb4541fSSam Bobroff }; 2567abd43baSSuraj Jitindar Singh uint8_t *pa_features = NULL; 25786d5771aSSam Bobroff size_t pa_size; 25886d5771aSSam Bobroff 2597abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06, 0, cpu->compat_pvr)) { 26086d5771aSSam Bobroff pa_features = pa_features_206; 26186d5771aSSam Bobroff pa_size = sizeof(pa_features_206); 2627abd43baSSuraj Jitindar Singh } 2637abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07, 0, cpu->compat_pvr)) { 26486d5771aSSam Bobroff pa_features = pa_features_207; 26586d5771aSSam Bobroff pa_size = sizeof(pa_features_207); 2667abd43baSSuraj Jitindar Singh } 2677abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0, cpu->compat_pvr)) { 26886d5771aSSam Bobroff pa_features = pa_features_300; 26986d5771aSSam Bobroff pa_size = sizeof(pa_features_300); 2707abd43baSSuraj Jitindar Singh } 2717abd43baSSuraj Jitindar Singh if (!pa_features) { 27286d5771aSSam Bobroff return; 27386d5771aSSam Bobroff } 27486d5771aSSam Bobroff 27526cd35b8SDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_CI_LARGEPAGE)) { 27686d5771aSSam Bobroff /* 27786d5771aSSam Bobroff * Note: we keep CI large pages off by default because a 64K capable 27886d5771aSSam Bobroff * guest provisioned with large pages might otherwise try to map a qemu 27986d5771aSSam Bobroff * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages 28086d5771aSSam Bobroff * even if that qemu runs on a 4k host. 28186d5771aSSam Bobroff * We dd this bit back here if we are confident this is not an issue 28286d5771aSSam Bobroff */ 28386d5771aSSam Bobroff pa_features[3] |= 0x20; 28486d5771aSSam Bobroff } 2854e5fe368SSuraj Jitindar Singh if ((spapr_get_cap(spapr, SPAPR_CAP_HTM) != 0) && pa_size > 24) { 28686d5771aSSam Bobroff pa_features[24] |= 0x80; /* Transactional memory support */ 28786d5771aSSam Bobroff } 288e957f6a9SSam Bobroff if (legacy_guest && pa_size > 40) { 289e957f6a9SSam Bobroff /* Workaround for broken kernels that attempt (guest) radix 290e957f6a9SSam Bobroff * mode when they can't handle it, if they see the radix bit set 291e957f6a9SSam Bobroff * in pa-features. So hide it from them. */ 292e957f6a9SSam Bobroff pa_features[40 + 2] &= ~0x80; /* Radix MMU */ 293e957f6a9SSam Bobroff } 29486d5771aSSam Bobroff 29586d5771aSSam Bobroff _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size))); 29686d5771aSSam Bobroff } 29786d5771aSSam Bobroff 298ce2918cbSDavid Gibson static int spapr_fixup_cpu_dt(void *fdt, SpaprMachineState *spapr) 29953018216SPaolo Bonzini { 300fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 30182677ed2SAlexey Kardashevskiy int ret = 0, offset, cpus_offset; 30282677ed2SAlexey Kardashevskiy CPUState *cs; 30353018216SPaolo Bonzini char cpu_model[32]; 30453018216SPaolo Bonzini uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 30553018216SPaolo Bonzini 30682677ed2SAlexey Kardashevskiy CPU_FOREACH(cs) { 30782677ed2SAlexey Kardashevskiy PowerPCCPU *cpu = POWERPC_CPU(cs); 30882677ed2SAlexey Kardashevskiy DeviceClass *dc = DEVICE_GET_CLASS(cs); 30914bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 310fe6b6346SLike Xu int compat_smt = MIN(ms->smp.threads, ppc_compat_max_vthreads(cpu)); 31153018216SPaolo Bonzini 3125d0fb150SGreg Kurz if (!spapr_is_thread0_in_vcore(spapr, cpu)) { 31353018216SPaolo Bonzini continue; 31453018216SPaolo Bonzini } 31553018216SPaolo Bonzini 31682677ed2SAlexey Kardashevskiy snprintf(cpu_model, 32, "%s@%x", dc->fw_name, index); 31753018216SPaolo Bonzini 31882677ed2SAlexey Kardashevskiy cpus_offset = fdt_path_offset(fdt, "/cpus"); 31982677ed2SAlexey Kardashevskiy if (cpus_offset < 0) { 320a4f3885cSGreg Kurz cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 32182677ed2SAlexey Kardashevskiy if (cpus_offset < 0) { 32282677ed2SAlexey Kardashevskiy return cpus_offset; 32382677ed2SAlexey Kardashevskiy } 32482677ed2SAlexey Kardashevskiy } 32582677ed2SAlexey Kardashevskiy offset = fdt_subnode_offset(fdt, cpus_offset, cpu_model); 32682677ed2SAlexey Kardashevskiy if (offset < 0) { 32782677ed2SAlexey Kardashevskiy offset = fdt_add_subnode(fdt, cpus_offset, cpu_model); 32853018216SPaolo Bonzini if (offset < 0) { 32953018216SPaolo Bonzini return offset; 33053018216SPaolo Bonzini } 33182677ed2SAlexey Kardashevskiy } 33253018216SPaolo Bonzini 3330da6f3feSBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,pft-size", 3340da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)); 33553018216SPaolo Bonzini if (ret < 0) { 33653018216SPaolo Bonzini return ret; 33753018216SPaolo Bonzini } 33853018216SPaolo Bonzini 339aa570207STao Xu if (ms->numa_state->num_nodes > 1) { 34099861ecbSIgor Mammedov ret = spapr_fixup_cpu_numa_dt(fdt, offset, cpu); 34153018216SPaolo Bonzini if (ret < 0) { 34253018216SPaolo Bonzini return ret; 34353018216SPaolo Bonzini } 34499861ecbSIgor Mammedov } 345833d4668SAlexey Kardashevskiy 34612dbeb16SDavid Gibson ret = spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt); 347833d4668SAlexey Kardashevskiy if (ret < 0) { 348833d4668SAlexey Kardashevskiy return ret; 349833d4668SAlexey Kardashevskiy } 350e957f6a9SSam Bobroff 351ee76a09fSDavid Gibson spapr_populate_pa_features(spapr, cpu, fdt, offset, 352e957f6a9SSam Bobroff spapr->cas_legacy_guest_workaround); 35353018216SPaolo Bonzini } 35453018216SPaolo Bonzini return ret; 35553018216SPaolo Bonzini } 35653018216SPaolo Bonzini 357c86c1affSDaniel Henrique Barboza static hwaddr spapr_node0_size(MachineState *machine) 358b082d65aSAlexey Kardashevskiy { 359aa570207STao Xu if (machine->numa_state->num_nodes) { 360b082d65aSAlexey Kardashevskiy int i; 361aa570207STao Xu for (i = 0; i < machine->numa_state->num_nodes; ++i) { 3627e721e7bSTao Xu if (machine->numa_state->nodes[i].node_mem) { 3637e721e7bSTao Xu return MIN(pow2floor(machine->numa_state->nodes[i].node_mem), 364fb164994SDavid Gibson machine->ram_size); 365b082d65aSAlexey Kardashevskiy } 366b082d65aSAlexey Kardashevskiy } 367b082d65aSAlexey Kardashevskiy } 368fb164994SDavid Gibson return machine->ram_size; 369b082d65aSAlexey Kardashevskiy } 370b082d65aSAlexey Kardashevskiy 371a1d59c0fSAlexey Kardashevskiy static void add_str(GString *s, const gchar *s1) 372a1d59c0fSAlexey Kardashevskiy { 373a1d59c0fSAlexey Kardashevskiy g_string_append_len(s, s1, strlen(s1) + 1); 374a1d59c0fSAlexey Kardashevskiy } 37553018216SPaolo Bonzini 37603d196b7SBharata B Rao static int spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start, 37726a8c353SAlexey Kardashevskiy hwaddr size) 37826a8c353SAlexey Kardashevskiy { 37926a8c353SAlexey Kardashevskiy uint32_t associativity[] = { 38026a8c353SAlexey Kardashevskiy cpu_to_be32(0x4), /* length */ 38126a8c353SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(0x0), 382c3b4f589SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(nodeid) 38326a8c353SAlexey Kardashevskiy }; 38426a8c353SAlexey Kardashevskiy char mem_name[32]; 38526a8c353SAlexey Kardashevskiy uint64_t mem_reg_property[2]; 38626a8c353SAlexey Kardashevskiy int off; 38726a8c353SAlexey Kardashevskiy 38826a8c353SAlexey Kardashevskiy mem_reg_property[0] = cpu_to_be64(start); 38926a8c353SAlexey Kardashevskiy mem_reg_property[1] = cpu_to_be64(size); 39026a8c353SAlexey Kardashevskiy 39126a8c353SAlexey Kardashevskiy sprintf(mem_name, "memory@" TARGET_FMT_lx, start); 39226a8c353SAlexey Kardashevskiy off = fdt_add_subnode(fdt, 0, mem_name); 39326a8c353SAlexey Kardashevskiy _FDT(off); 39426a8c353SAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 39526a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 39626a8c353SAlexey Kardashevskiy sizeof(mem_reg_property)))); 39726a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity, 39826a8c353SAlexey Kardashevskiy sizeof(associativity)))); 39903d196b7SBharata B Rao return off; 40026a8c353SAlexey Kardashevskiy } 40126a8c353SAlexey Kardashevskiy 402ce2918cbSDavid Gibson static int spapr_populate_memory(SpaprMachineState *spapr, void *fdt) 40353018216SPaolo Bonzini { 404fb164994SDavid Gibson MachineState *machine = MACHINE(spapr); 4057db8a127SAlexey Kardashevskiy hwaddr mem_start, node_size; 406aa570207STao Xu int i, nb_nodes = machine->numa_state->num_nodes; 4077e721e7bSTao Xu NodeInfo *nodes = machine->numa_state->nodes; 4087db8a127SAlexey Kardashevskiy NodeInfo ramnode; 40953018216SPaolo Bonzini 4107db8a127SAlexey Kardashevskiy /* No NUMA nodes, assume there is just one node with whole RAM */ 411aa570207STao Xu if (!nb_nodes) { 4127db8a127SAlexey Kardashevskiy nb_nodes = 1; 413fb164994SDavid Gibson ramnode.node_mem = machine->ram_size; 4147db8a127SAlexey Kardashevskiy nodes = &ramnode; 4155fe269b1SPaul Mackerras } 41653018216SPaolo Bonzini 4177db8a127SAlexey Kardashevskiy for (i = 0, mem_start = 0; i < nb_nodes; ++i) { 4187db8a127SAlexey Kardashevskiy if (!nodes[i].node_mem) { 4197db8a127SAlexey Kardashevskiy continue; 42053018216SPaolo Bonzini } 421fb164994SDavid Gibson if (mem_start >= machine->ram_size) { 4225fe269b1SPaul Mackerras node_size = 0; 4235fe269b1SPaul Mackerras } else { 4247db8a127SAlexey Kardashevskiy node_size = nodes[i].node_mem; 425fb164994SDavid Gibson if (node_size > machine->ram_size - mem_start) { 426fb164994SDavid Gibson node_size = machine->ram_size - mem_start; 4275fe269b1SPaul Mackerras } 4285fe269b1SPaul Mackerras } 4297db8a127SAlexey Kardashevskiy if (!mem_start) { 430b472b1a7SDaniel Henrique Barboza /* spapr_machine_init() checks for rma_size <= node0_size 431b472b1a7SDaniel Henrique Barboza * already */ 432e8f986fcSBharata B Rao spapr_populate_memory_node(fdt, i, 0, spapr->rma_size); 4337db8a127SAlexey Kardashevskiy mem_start += spapr->rma_size; 4347db8a127SAlexey Kardashevskiy node_size -= spapr->rma_size; 4357db8a127SAlexey Kardashevskiy } 4366010818cSAlexey Kardashevskiy for ( ; node_size; ) { 4376010818cSAlexey Kardashevskiy hwaddr sizetmp = pow2floor(node_size); 4386010818cSAlexey Kardashevskiy 4396010818cSAlexey Kardashevskiy /* mem_start != 0 here */ 4406010818cSAlexey Kardashevskiy if (ctzl(mem_start) < ctzl(sizetmp)) { 4416010818cSAlexey Kardashevskiy sizetmp = 1ULL << ctzl(mem_start); 4426010818cSAlexey Kardashevskiy } 4436010818cSAlexey Kardashevskiy 4446010818cSAlexey Kardashevskiy spapr_populate_memory_node(fdt, i, mem_start, sizetmp); 4456010818cSAlexey Kardashevskiy node_size -= sizetmp; 4466010818cSAlexey Kardashevskiy mem_start += sizetmp; 4476010818cSAlexey Kardashevskiy } 44853018216SPaolo Bonzini } 44953018216SPaolo Bonzini 45053018216SPaolo Bonzini return 0; 45153018216SPaolo Bonzini } 45253018216SPaolo Bonzini 4530da6f3feSBharata B Rao static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, 454ce2918cbSDavid Gibson SpaprMachineState *spapr) 4550da6f3feSBharata B Rao { 456fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 4570da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 4580da6f3feSBharata B Rao CPUPPCState *env = &cpu->env; 4590da6f3feSBharata B Rao PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 46014bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 4610da6f3feSBharata B Rao uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 4620da6f3feSBharata B Rao 0xffffffff, 0xffffffff}; 463afd10a0fSBharata B Rao uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() 464afd10a0fSBharata B Rao : SPAPR_TIMEBASE_FREQ; 4650da6f3feSBharata B Rao uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; 4660da6f3feSBharata B Rao uint32_t page_sizes_prop[64]; 4670da6f3feSBharata B Rao size_t page_sizes_prop_size; 468fe6b6346SLike Xu unsigned int smp_threads = ms->smp.threads; 469fe6b6346SLike Xu uint32_t vcpus_per_socket = smp_threads * ms->smp.cores; 4700da6f3feSBharata B Rao uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 471abbc1247SDavid Gibson int compat_smt = MIN(smp_threads, ppc_compat_max_vthreads(cpu)); 472ce2918cbSDavid Gibson SpaprDrc *drc; 473af81cf32SBharata B Rao int drc_index; 474c64abd1fSSam Bobroff uint32_t radix_AP_encodings[PPC_PAGE_SIZES_MAX_SZ]; 475c64abd1fSSam Bobroff int i; 476af81cf32SBharata B Rao 477fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index); 478af81cf32SBharata B Rao if (drc) { 4790b55aa91SDavid Gibson drc_index = spapr_drc_index(drc); 480af81cf32SBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index))); 481af81cf32SBharata B Rao } 4820da6f3feSBharata B Rao 4830da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); 4840da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 4850da6f3feSBharata B Rao 4860da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 4870da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 4880da6f3feSBharata B Rao env->dcache_line_size))); 4890da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 4900da6f3feSBharata B Rao env->dcache_line_size))); 4910da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 4920da6f3feSBharata B Rao env->icache_line_size))); 4930da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 4940da6f3feSBharata B Rao env->icache_line_size))); 4950da6f3feSBharata B Rao 4960da6f3feSBharata B Rao if (pcc->l1_dcache_size) { 4970da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 4980da6f3feSBharata B Rao pcc->l1_dcache_size))); 4990da6f3feSBharata B Rao } else { 5003dc6f869SAlistair Francis warn_report("Unknown L1 dcache size for cpu"); 5010da6f3feSBharata B Rao } 5020da6f3feSBharata B Rao if (pcc->l1_icache_size) { 5030da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 5040da6f3feSBharata B Rao pcc->l1_icache_size))); 5050da6f3feSBharata B Rao } else { 5063dc6f869SAlistair Francis warn_report("Unknown L1 icache size for cpu"); 5070da6f3feSBharata B Rao } 5080da6f3feSBharata B Rao 5090da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 5100da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 51167d7d66fSDavid Gibson _FDT((fdt_setprop_cell(fdt, offset, "slb-size", cpu->hash64_opts->slb_size))); 51267d7d66fSDavid Gibson _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", cpu->hash64_opts->slb_size))); 5130da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 5140da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 5150da6f3feSBharata B Rao 5160da6f3feSBharata B Rao if (env->spr_cb[SPR_PURR].oea_read) { 51783f192d3SSuraj Jitindar Singh _FDT((fdt_setprop_cell(fdt, offset, "ibm,purr", 1))); 51883f192d3SSuraj Jitindar Singh } 51983f192d3SSuraj Jitindar Singh if (env->spr_cb[SPR_SPURR].oea_read) { 52083f192d3SSuraj Jitindar Singh _FDT((fdt_setprop_cell(fdt, offset, "ibm,spurr", 1))); 5210da6f3feSBharata B Rao } 5220da6f3feSBharata B Rao 52358969eeeSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 5240da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 5250da6f3feSBharata B Rao segs, sizeof(segs)))); 5260da6f3feSBharata B Rao } 5270da6f3feSBharata B Rao 52829386642SDavid Gibson /* Advertise VSX (vector extensions) if available 5290da6f3feSBharata B Rao * 1 == VMX / Altivec available 53029386642SDavid Gibson * 2 == VSX available 53129386642SDavid Gibson * 53229386642SDavid Gibson * Only CPUs for which we create core types in spapr_cpu_core.c 53329386642SDavid Gibson * are possible, and all of those have VMX */ 5344e5fe368SSuraj Jitindar Singh if (spapr_get_cap(spapr, SPAPR_CAP_VSX) != 0) { 53529386642SDavid Gibson _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2))); 53629386642SDavid Gibson } else { 53729386642SDavid Gibson _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1))); 5380da6f3feSBharata B Rao } 5390da6f3feSBharata B Rao 5400da6f3feSBharata B Rao /* Advertise DFP (Decimal Floating Point) if available 5410da6f3feSBharata B Rao * 0 / no property == no DFP 5420da6f3feSBharata B Rao * 1 == DFP available */ 5434e5fe368SSuraj Jitindar Singh if (spapr_get_cap(spapr, SPAPR_CAP_DFP) != 0) { 5440da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 5450da6f3feSBharata B Rao } 5460da6f3feSBharata B Rao 547644a2c99SDavid Gibson page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 5480da6f3feSBharata B Rao sizeof(page_sizes_prop)); 5490da6f3feSBharata B Rao if (page_sizes_prop_size) { 5500da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 5510da6f3feSBharata B Rao page_sizes_prop, page_sizes_prop_size))); 5520da6f3feSBharata B Rao } 5530da6f3feSBharata B Rao 554ee76a09fSDavid Gibson spapr_populate_pa_features(spapr, cpu, fdt, offset, false); 55590da0d5aSBenjamin Herrenschmidt 5560da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", 55722419c2aSDavid Gibson cs->cpu_index / vcpus_per_socket))); 5580da6f3feSBharata B Rao 5590da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", 5600da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)))); 5610da6f3feSBharata B Rao 562aa570207STao Xu if (ms->numa_state->num_nodes > 1) { 56399861ecbSIgor Mammedov _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cpu)); 56499861ecbSIgor Mammedov } 5650da6f3feSBharata B Rao 56612dbeb16SDavid Gibson _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt)); 567c64abd1fSSam Bobroff 568c64abd1fSSam Bobroff if (pcc->radix_page_info) { 569c64abd1fSSam Bobroff for (i = 0; i < pcc->radix_page_info->count; i++) { 570c64abd1fSSam Bobroff radix_AP_encodings[i] = 571c64abd1fSSam Bobroff cpu_to_be32(pcc->radix_page_info->entries[i]); 572c64abd1fSSam Bobroff } 573c64abd1fSSam Bobroff _FDT((fdt_setprop(fdt, offset, "ibm,processor-radix-AP-encodings", 574c64abd1fSSam Bobroff radix_AP_encodings, 575c64abd1fSSam Bobroff pcc->radix_page_info->count * 576c64abd1fSSam Bobroff sizeof(radix_AP_encodings[0])))); 577c64abd1fSSam Bobroff } 578a8dafa52SSuraj Jitindar Singh 579a8dafa52SSuraj Jitindar Singh /* 580a8dafa52SSuraj Jitindar Singh * We set this property to let the guest know that it can use the large 581a8dafa52SSuraj Jitindar Singh * decrementer and its width in bits. 582a8dafa52SSuraj Jitindar Singh */ 583a8dafa52SSuraj Jitindar Singh if (spapr_get_cap(spapr, SPAPR_CAP_LARGE_DECREMENTER) != SPAPR_CAP_OFF) 584a8dafa52SSuraj Jitindar Singh _FDT((fdt_setprop_u32(fdt, offset, "ibm,dec-bits", 585a8dafa52SSuraj Jitindar Singh pcc->lrg_decr_bits))); 5860da6f3feSBharata B Rao } 5870da6f3feSBharata B Rao 588ce2918cbSDavid Gibson static void spapr_populate_cpus_dt_node(void *fdt, SpaprMachineState *spapr) 5890da6f3feSBharata B Rao { 59004d595b3SEmilio G. Cota CPUState **rev; 5910da6f3feSBharata B Rao CPUState *cs; 59204d595b3SEmilio G. Cota int n_cpus; 5930da6f3feSBharata B Rao int cpus_offset; 5940da6f3feSBharata B Rao char *nodename; 59504d595b3SEmilio G. Cota int i; 5960da6f3feSBharata B Rao 5970da6f3feSBharata B Rao cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 5980da6f3feSBharata B Rao _FDT(cpus_offset); 5990da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 6000da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 6010da6f3feSBharata B Rao 6020da6f3feSBharata B Rao /* 6030da6f3feSBharata B Rao * We walk the CPUs in reverse order to ensure that CPU DT nodes 6040da6f3feSBharata B Rao * created by fdt_add_subnode() end up in the right order in FDT 6050da6f3feSBharata B Rao * for the guest kernel the enumerate the CPUs correctly. 60604d595b3SEmilio G. Cota * 60704d595b3SEmilio G. Cota * The CPU list cannot be traversed in reverse order, so we need 60804d595b3SEmilio G. Cota * to do extra work. 6090da6f3feSBharata B Rao */ 61004d595b3SEmilio G. Cota n_cpus = 0; 61104d595b3SEmilio G. Cota rev = NULL; 61204d595b3SEmilio G. Cota CPU_FOREACH(cs) { 61304d595b3SEmilio G. Cota rev = g_renew(CPUState *, rev, n_cpus + 1); 61404d595b3SEmilio G. Cota rev[n_cpus++] = cs; 61504d595b3SEmilio G. Cota } 61604d595b3SEmilio G. Cota 61704d595b3SEmilio G. Cota for (i = n_cpus - 1; i >= 0; i--) { 61804d595b3SEmilio G. Cota CPUState *cs = rev[i]; 6190da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 62014bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 6210da6f3feSBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 6220da6f3feSBharata B Rao int offset; 6230da6f3feSBharata B Rao 6245d0fb150SGreg Kurz if (!spapr_is_thread0_in_vcore(spapr, cpu)) { 6250da6f3feSBharata B Rao continue; 6260da6f3feSBharata B Rao } 6270da6f3feSBharata B Rao 6280da6f3feSBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, index); 6290da6f3feSBharata B Rao offset = fdt_add_subnode(fdt, cpus_offset, nodename); 6300da6f3feSBharata B Rao g_free(nodename); 6310da6f3feSBharata B Rao _FDT(offset); 6320da6f3feSBharata B Rao spapr_populate_cpu_dt(cs, fdt, offset, spapr); 6330da6f3feSBharata B Rao } 6340da6f3feSBharata B Rao 635eceba347SEmilio G. Cota g_free(rev); 6360da6f3feSBharata B Rao } 6370da6f3feSBharata B Rao 6380e947a89SThomas Huth static int spapr_rng_populate_dt(void *fdt) 6390e947a89SThomas Huth { 6400e947a89SThomas Huth int node; 6410e947a89SThomas Huth int ret; 6420e947a89SThomas Huth 6430e947a89SThomas Huth node = qemu_fdt_add_subnode(fdt, "/ibm,platform-facilities"); 6440e947a89SThomas Huth if (node <= 0) { 6450e947a89SThomas Huth return -1; 6460e947a89SThomas Huth } 6470e947a89SThomas Huth ret = fdt_setprop_string(fdt, node, "device_type", 6480e947a89SThomas Huth "ibm,platform-facilities"); 6490e947a89SThomas Huth ret |= fdt_setprop_cell(fdt, node, "#address-cells", 0x1); 6500e947a89SThomas Huth ret |= fdt_setprop_cell(fdt, node, "#size-cells", 0x0); 6510e947a89SThomas Huth 6520e947a89SThomas Huth node = fdt_add_subnode(fdt, node, "ibm,random-v1"); 6530e947a89SThomas Huth if (node <= 0) { 6540e947a89SThomas Huth return -1; 6550e947a89SThomas Huth } 6560e947a89SThomas Huth ret |= fdt_setprop_string(fdt, node, "compatible", "ibm,random"); 6570e947a89SThomas Huth 6580e947a89SThomas Huth return ret ? -1 : 0; 6590e947a89SThomas Huth } 6600e947a89SThomas Huth 661f47bd1c8SIgor Mammedov static uint32_t spapr_pc_dimm_node(MemoryDeviceInfoList *list, ram_addr_t addr) 662f47bd1c8SIgor Mammedov { 663f47bd1c8SIgor Mammedov MemoryDeviceInfoList *info; 664f47bd1c8SIgor Mammedov 665f47bd1c8SIgor Mammedov for (info = list; info; info = info->next) { 666f47bd1c8SIgor Mammedov MemoryDeviceInfo *value = info->value; 667f47bd1c8SIgor Mammedov 668f47bd1c8SIgor Mammedov if (value && value->type == MEMORY_DEVICE_INFO_KIND_DIMM) { 669f47bd1c8SIgor Mammedov PCDIMMDeviceInfo *pcdimm_info = value->u.dimm.data; 670f47bd1c8SIgor Mammedov 671ccc2cef8SDavid Gibson if (addr >= pcdimm_info->addr && 672f47bd1c8SIgor Mammedov addr < (pcdimm_info->addr + pcdimm_info->size)) { 673f47bd1c8SIgor Mammedov return pcdimm_info->node; 674f47bd1c8SIgor Mammedov } 675f47bd1c8SIgor Mammedov } 676f47bd1c8SIgor Mammedov } 677f47bd1c8SIgor Mammedov 678f47bd1c8SIgor Mammedov return -1; 679f47bd1c8SIgor Mammedov } 680f47bd1c8SIgor Mammedov 681a324d6f1SBharata B Rao struct sPAPRDrconfCellV2 { 682a324d6f1SBharata B Rao uint32_t seq_lmbs; 683a324d6f1SBharata B Rao uint64_t base_addr; 684a324d6f1SBharata B Rao uint32_t drc_index; 685a324d6f1SBharata B Rao uint32_t aa_index; 686a324d6f1SBharata B Rao uint32_t flags; 687a324d6f1SBharata B Rao } QEMU_PACKED; 688a324d6f1SBharata B Rao 689a324d6f1SBharata B Rao typedef struct DrconfCellQueue { 690a324d6f1SBharata B Rao struct sPAPRDrconfCellV2 cell; 691a324d6f1SBharata B Rao QSIMPLEQ_ENTRY(DrconfCellQueue) entry; 692a324d6f1SBharata B Rao } DrconfCellQueue; 693a324d6f1SBharata B Rao 694a324d6f1SBharata B Rao static DrconfCellQueue * 695a324d6f1SBharata B Rao spapr_get_drconf_cell(uint32_t seq_lmbs, uint64_t base_addr, 696a324d6f1SBharata B Rao uint32_t drc_index, uint32_t aa_index, 697a324d6f1SBharata B Rao uint32_t flags) 69803d196b7SBharata B Rao { 699a324d6f1SBharata B Rao DrconfCellQueue *elem; 700a324d6f1SBharata B Rao 701a324d6f1SBharata B Rao elem = g_malloc0(sizeof(*elem)); 702a324d6f1SBharata B Rao elem->cell.seq_lmbs = cpu_to_be32(seq_lmbs); 703a324d6f1SBharata B Rao elem->cell.base_addr = cpu_to_be64(base_addr); 704a324d6f1SBharata B Rao elem->cell.drc_index = cpu_to_be32(drc_index); 705a324d6f1SBharata B Rao elem->cell.aa_index = cpu_to_be32(aa_index); 706a324d6f1SBharata B Rao elem->cell.flags = cpu_to_be32(flags); 707a324d6f1SBharata B Rao 708a324d6f1SBharata B Rao return elem; 709a324d6f1SBharata B Rao } 710a324d6f1SBharata B Rao 711a324d6f1SBharata B Rao /* ibm,dynamic-memory-v2 */ 712ce2918cbSDavid Gibson static int spapr_populate_drmem_v2(SpaprMachineState *spapr, void *fdt, 713a324d6f1SBharata B Rao int offset, MemoryDeviceInfoList *dimms) 714a324d6f1SBharata B Rao { 715b0c14ec4SDavid Hildenbrand MachineState *machine = MACHINE(spapr); 716cc941111SFabiano Rosas uint8_t *int_buf, *cur_index; 717a324d6f1SBharata B Rao int ret; 71803d196b7SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 719a324d6f1SBharata B Rao uint64_t addr, cur_addr, size; 720b0c14ec4SDavid Hildenbrand uint32_t nr_boot_lmbs = (machine->device_memory->base / lmb_size); 721b0c14ec4SDavid Hildenbrand uint64_t mem_end = machine->device_memory->base + 722b0c14ec4SDavid Hildenbrand memory_region_size(&machine->device_memory->mr); 723cc941111SFabiano Rosas uint32_t node, buf_len, nr_entries = 0; 724ce2918cbSDavid Gibson SpaprDrc *drc; 725a324d6f1SBharata B Rao DrconfCellQueue *elem, *next; 726a324d6f1SBharata B Rao MemoryDeviceInfoList *info; 727a324d6f1SBharata B Rao QSIMPLEQ_HEAD(, DrconfCellQueue) drconf_queue 728a324d6f1SBharata B Rao = QSIMPLEQ_HEAD_INITIALIZER(drconf_queue); 729a324d6f1SBharata B Rao 730a324d6f1SBharata B Rao /* Entry to cover RAM and the gap area */ 731a324d6f1SBharata B Rao elem = spapr_get_drconf_cell(nr_boot_lmbs, 0, 0, -1, 732a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_RESERVED | 733a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 734a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 735a324d6f1SBharata B Rao nr_entries++; 736a324d6f1SBharata B Rao 737b0c14ec4SDavid Hildenbrand cur_addr = machine->device_memory->base; 738a324d6f1SBharata B Rao for (info = dimms; info; info = info->next) { 739a324d6f1SBharata B Rao PCDIMMDeviceInfo *di = info->value->u.dimm.data; 740a324d6f1SBharata B Rao 741a324d6f1SBharata B Rao addr = di->addr; 742a324d6f1SBharata B Rao size = di->size; 743a324d6f1SBharata B Rao node = di->node; 744a324d6f1SBharata B Rao 745a324d6f1SBharata B Rao /* Entry for hot-pluggable area */ 746a324d6f1SBharata B Rao if (cur_addr < addr) { 747a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size); 748a324d6f1SBharata B Rao g_assert(drc); 749a324d6f1SBharata B Rao elem = spapr_get_drconf_cell((addr - cur_addr) / lmb_size, 750a324d6f1SBharata B Rao cur_addr, spapr_drc_index(drc), -1, 0); 751a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 752a324d6f1SBharata B Rao nr_entries++; 753a324d6f1SBharata B Rao } 754a324d6f1SBharata B Rao 755a324d6f1SBharata B Rao /* Entry for DIMM */ 756a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr / lmb_size); 757a324d6f1SBharata B Rao g_assert(drc); 758a324d6f1SBharata B Rao elem = spapr_get_drconf_cell(size / lmb_size, addr, 759a324d6f1SBharata B Rao spapr_drc_index(drc), node, 760a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_ASSIGNED); 761a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 762a324d6f1SBharata B Rao nr_entries++; 763a324d6f1SBharata B Rao cur_addr = addr + size; 764a324d6f1SBharata B Rao } 765a324d6f1SBharata B Rao 766a324d6f1SBharata B Rao /* Entry for remaining hotpluggable area */ 767a324d6f1SBharata B Rao if (cur_addr < mem_end) { 768a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size); 769a324d6f1SBharata B Rao g_assert(drc); 770a324d6f1SBharata B Rao elem = spapr_get_drconf_cell((mem_end - cur_addr) / lmb_size, 771a324d6f1SBharata B Rao cur_addr, spapr_drc_index(drc), -1, 0); 772a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 773a324d6f1SBharata B Rao nr_entries++; 774a324d6f1SBharata B Rao } 775a324d6f1SBharata B Rao 776a324d6f1SBharata B Rao buf_len = nr_entries * sizeof(struct sPAPRDrconfCellV2) + sizeof(uint32_t); 777a324d6f1SBharata B Rao int_buf = cur_index = g_malloc0(buf_len); 778a324d6f1SBharata B Rao *(uint32_t *)int_buf = cpu_to_be32(nr_entries); 779a324d6f1SBharata B Rao cur_index += sizeof(nr_entries); 780a324d6f1SBharata B Rao 781a324d6f1SBharata B Rao QSIMPLEQ_FOREACH_SAFE(elem, &drconf_queue, entry, next) { 782a324d6f1SBharata B Rao memcpy(cur_index, &elem->cell, sizeof(elem->cell)); 783a324d6f1SBharata B Rao cur_index += sizeof(elem->cell); 784a324d6f1SBharata B Rao QSIMPLEQ_REMOVE(&drconf_queue, elem, DrconfCellQueue, entry); 785a324d6f1SBharata B Rao g_free(elem); 786a324d6f1SBharata B Rao } 787a324d6f1SBharata B Rao 788a324d6f1SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory-v2", int_buf, buf_len); 789a324d6f1SBharata B Rao g_free(int_buf); 790a324d6f1SBharata B Rao if (ret < 0) { 791a324d6f1SBharata B Rao return -1; 792a324d6f1SBharata B Rao } 793a324d6f1SBharata B Rao return 0; 794a324d6f1SBharata B Rao } 795a324d6f1SBharata B Rao 796a324d6f1SBharata B Rao /* ibm,dynamic-memory */ 797ce2918cbSDavid Gibson static int spapr_populate_drmem_v1(SpaprMachineState *spapr, void *fdt, 798a324d6f1SBharata B Rao int offset, MemoryDeviceInfoList *dimms) 799a324d6f1SBharata B Rao { 800b0c14ec4SDavid Hildenbrand MachineState *machine = MACHINE(spapr); 801a324d6f1SBharata B Rao int i, ret; 802a324d6f1SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 8030c9269a5SDavid Hildenbrand uint32_t device_lmb_start = machine->device_memory->base / lmb_size; 804b0c14ec4SDavid Hildenbrand uint32_t nr_lmbs = (machine->device_memory->base + 805b0c14ec4SDavid Hildenbrand memory_region_size(&machine->device_memory->mr)) / 806d0e5a8f2SBharata B Rao lmb_size; 80703d196b7SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 80816c25aefSBharata B Rao 80916c25aefSBharata B Rao /* 810ef001f06SThomas Huth * Allocate enough buffer size to fit in ibm,dynamic-memory 811ef001f06SThomas Huth */ 812a324d6f1SBharata B Rao buf_len = (nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1) * sizeof(uint32_t); 81303d196b7SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 81403d196b7SBharata B Rao int_buf[0] = cpu_to_be32(nr_lmbs); 81503d196b7SBharata B Rao cur_index++; 81603d196b7SBharata B Rao for (i = 0; i < nr_lmbs; i++) { 817d0e5a8f2SBharata B Rao uint64_t addr = i * lmb_size; 81803d196b7SBharata B Rao uint32_t *dynamic_memory = cur_index; 81903d196b7SBharata B Rao 8200c9269a5SDavid Hildenbrand if (i >= device_lmb_start) { 821ce2918cbSDavid Gibson SpaprDrc *drc; 822d0e5a8f2SBharata B Rao 823fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, i); 82403d196b7SBharata B Rao g_assert(drc); 82503d196b7SBharata B Rao 82603d196b7SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 82703d196b7SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 8280b55aa91SDavid Gibson dynamic_memory[2] = cpu_to_be32(spapr_drc_index(drc)); 82903d196b7SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 830f47bd1c8SIgor Mammedov dynamic_memory[4] = cpu_to_be32(spapr_pc_dimm_node(dimms, addr)); 831d0e5a8f2SBharata B Rao if (memory_region_present(get_system_memory(), addr)) { 83203d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); 83303d196b7SBharata B Rao } else { 83403d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(0); 83503d196b7SBharata B Rao } 836d0e5a8f2SBharata B Rao } else { 837d0e5a8f2SBharata B Rao /* 838d0e5a8f2SBharata B Rao * LMB information for RMA, boot time RAM and gap b/n RAM and 8390c9269a5SDavid Hildenbrand * device memory region -- all these are marked as reserved 840d0e5a8f2SBharata B Rao * and as having no valid DRC. 841d0e5a8f2SBharata B Rao */ 842d0e5a8f2SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 843d0e5a8f2SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 844d0e5a8f2SBharata B Rao dynamic_memory[2] = cpu_to_be32(0); 845d0e5a8f2SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 846d0e5a8f2SBharata B Rao dynamic_memory[4] = cpu_to_be32(-1); 847d0e5a8f2SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED | 848d0e5a8f2SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 849d0e5a8f2SBharata B Rao } 85003d196b7SBharata B Rao 85103d196b7SBharata B Rao cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; 85203d196b7SBharata B Rao } 85303d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len); 854a324d6f1SBharata B Rao g_free(int_buf); 85503d196b7SBharata B Rao if (ret < 0) { 856a324d6f1SBharata B Rao return -1; 857a324d6f1SBharata B Rao } 858a324d6f1SBharata B Rao return 0; 859a324d6f1SBharata B Rao } 860a324d6f1SBharata B Rao 861a324d6f1SBharata B Rao /* 862a324d6f1SBharata B Rao * Adds ibm,dynamic-reconfiguration-memory node. 863a324d6f1SBharata B Rao * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation 864a324d6f1SBharata B Rao * of this device tree node. 865a324d6f1SBharata B Rao */ 866ce2918cbSDavid Gibson static int spapr_populate_drconf_memory(SpaprMachineState *spapr, void *fdt) 867a324d6f1SBharata B Rao { 868a324d6f1SBharata B Rao MachineState *machine = MACHINE(spapr); 869aa570207STao Xu int nb_numa_nodes = machine->numa_state->num_nodes; 870a324d6f1SBharata B Rao int ret, i, offset; 871a324d6f1SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 872a324d6f1SBharata B Rao uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; 873a324d6f1SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 874a324d6f1SBharata B Rao int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; 875a324d6f1SBharata B Rao MemoryDeviceInfoList *dimms = NULL; 876a324d6f1SBharata B Rao 877a324d6f1SBharata B Rao /* 8780c9269a5SDavid Hildenbrand * Don't create the node if there is no device memory 879a324d6f1SBharata B Rao */ 880a324d6f1SBharata B Rao if (machine->ram_size == machine->maxram_size) { 881a324d6f1SBharata B Rao return 0; 882a324d6f1SBharata B Rao } 883a324d6f1SBharata B Rao 884a324d6f1SBharata B Rao offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory"); 885a324d6f1SBharata B Rao 886a324d6f1SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size, 887a324d6f1SBharata B Rao sizeof(prop_lmb_size)); 888a324d6f1SBharata B Rao if (ret < 0) { 889a324d6f1SBharata B Rao return ret; 890a324d6f1SBharata B Rao } 891a324d6f1SBharata B Rao 892a324d6f1SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff); 893a324d6f1SBharata B Rao if (ret < 0) { 894a324d6f1SBharata B Rao return ret; 895a324d6f1SBharata B Rao } 896a324d6f1SBharata B Rao 897a324d6f1SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0); 898a324d6f1SBharata B Rao if (ret < 0) { 899a324d6f1SBharata B Rao return ret; 900a324d6f1SBharata B Rao } 901a324d6f1SBharata B Rao 902a324d6f1SBharata B Rao /* ibm,dynamic-memory or ibm,dynamic-memory-v2 */ 9032cc0e2e8SDavid Hildenbrand dimms = qmp_memory_device_list(); 904a324d6f1SBharata B Rao if (spapr_ovec_test(spapr->ov5_cas, OV5_DRMEM_V2)) { 905a324d6f1SBharata B Rao ret = spapr_populate_drmem_v2(spapr, fdt, offset, dimms); 906a324d6f1SBharata B Rao } else { 907a324d6f1SBharata B Rao ret = spapr_populate_drmem_v1(spapr, fdt, offset, dimms); 908a324d6f1SBharata B Rao } 909a324d6f1SBharata B Rao qapi_free_MemoryDeviceInfoList(dimms); 910a324d6f1SBharata B Rao 911a324d6f1SBharata B Rao if (ret < 0) { 912a324d6f1SBharata B Rao return ret; 91303d196b7SBharata B Rao } 91403d196b7SBharata B Rao 91503d196b7SBharata B Rao /* ibm,associativity-lookup-arrays */ 916a324d6f1SBharata B Rao buf_len = (nr_nodes * 4 + 2) * sizeof(uint32_t); 917a324d6f1SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 9186663864eSBharata B Rao int_buf[0] = cpu_to_be32(nr_nodes); 91903d196b7SBharata B Rao int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */ 92003d196b7SBharata B Rao cur_index += 2; 9216663864eSBharata B Rao for (i = 0; i < nr_nodes; i++) { 92203d196b7SBharata B Rao uint32_t associativity[] = { 92303d196b7SBharata B Rao cpu_to_be32(0x0), 92403d196b7SBharata B Rao cpu_to_be32(0x0), 92503d196b7SBharata B Rao cpu_to_be32(0x0), 92603d196b7SBharata B Rao cpu_to_be32(i) 92703d196b7SBharata B Rao }; 92803d196b7SBharata B Rao memcpy(cur_index, associativity, sizeof(associativity)); 92903d196b7SBharata B Rao cur_index += 4; 93003d196b7SBharata B Rao } 93103d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf, 93203d196b7SBharata B Rao (cur_index - int_buf) * sizeof(uint32_t)); 93303d196b7SBharata B Rao g_free(int_buf); 934a324d6f1SBharata B Rao 93503d196b7SBharata B Rao return ret; 93603d196b7SBharata B Rao } 93703d196b7SBharata B Rao 938ce2918cbSDavid Gibson static int spapr_dt_cas_updates(SpaprMachineState *spapr, void *fdt, 939ce2918cbSDavid Gibson SpaprOptionVector *ov5_updates) 9406787d27bSMichael Roth { 941ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 942417ece33SMichael Roth int ret = 0, offset; 9436787d27bSMichael Roth 9446787d27bSMichael Roth /* Generate ibm,dynamic-reconfiguration-memory node if required */ 9456787d27bSMichael Roth if (spapr_ovec_test(ov5_updates, OV5_DRCONF_MEMORY)) { 9466787d27bSMichael Roth g_assert(smc->dr_lmb_enabled); 9476787d27bSMichael Roth ret = spapr_populate_drconf_memory(spapr, fdt); 948417ece33SMichael Roth if (ret) { 949417ece33SMichael Roth goto out; 950417ece33SMichael Roth } 9516787d27bSMichael Roth } 9526787d27bSMichael Roth 953417ece33SMichael Roth offset = fdt_path_offset(fdt, "/chosen"); 954417ece33SMichael Roth if (offset < 0) { 955417ece33SMichael Roth offset = fdt_add_subnode(fdt, 0, "chosen"); 956417ece33SMichael Roth if (offset < 0) { 957417ece33SMichael Roth return offset; 958417ece33SMichael Roth } 959417ece33SMichael Roth } 960417ece33SMichael Roth ret = spapr_ovec_populate_dt(fdt, offset, spapr->ov5_cas, 961417ece33SMichael Roth "ibm,architecture-vec-5"); 962417ece33SMichael Roth 963417ece33SMichael Roth out: 9646787d27bSMichael Roth return ret; 9656787d27bSMichael Roth } 9666787d27bSMichael Roth 96710f12e64SDaniel Henrique Barboza static bool spapr_hotplugged_dev_before_cas(void) 96810f12e64SDaniel Henrique Barboza { 96910f12e64SDaniel Henrique Barboza Object *drc_container, *obj; 97010f12e64SDaniel Henrique Barboza ObjectProperty *prop; 97110f12e64SDaniel Henrique Barboza ObjectPropertyIterator iter; 97210f12e64SDaniel Henrique Barboza 97310f12e64SDaniel Henrique Barboza drc_container = container_get(object_get_root(), "/dr-connector"); 97410f12e64SDaniel Henrique Barboza object_property_iter_init(&iter, drc_container); 97510f12e64SDaniel Henrique Barboza while ((prop = object_property_iter_next(&iter))) { 97610f12e64SDaniel Henrique Barboza if (!strstart(prop->type, "link<", NULL)) { 97710f12e64SDaniel Henrique Barboza continue; 97810f12e64SDaniel Henrique Barboza } 97910f12e64SDaniel Henrique Barboza obj = object_property_get_link(drc_container, prop->name, NULL); 98010f12e64SDaniel Henrique Barboza if (spapr_drc_needed(obj)) { 98110f12e64SDaniel Henrique Barboza return true; 98210f12e64SDaniel Henrique Barboza } 98310f12e64SDaniel Henrique Barboza } 98410f12e64SDaniel Henrique Barboza return false; 98510f12e64SDaniel Henrique Barboza } 98610f12e64SDaniel Henrique Barboza 987ce2918cbSDavid Gibson int spapr_h_cas_compose_response(SpaprMachineState *spapr, 98803d196b7SBharata B Rao target_ulong addr, target_ulong size, 989ce2918cbSDavid Gibson SpaprOptionVector *ov5_updates) 99003d196b7SBharata B Rao { 99103d196b7SBharata B Rao void *fdt, *fdt_skel; 992ce2918cbSDavid Gibson SpaprDeviceTreeUpdateHeader hdr = { .version_id = 1 }; 99303d196b7SBharata B Rao 99410f12e64SDaniel Henrique Barboza if (spapr_hotplugged_dev_before_cas()) { 99510f12e64SDaniel Henrique Barboza return 1; 99610f12e64SDaniel Henrique Barboza } 99710f12e64SDaniel Henrique Barboza 998827b17c4SGreg Kurz if (size < sizeof(hdr) || size > FW_MAX_SIZE) { 999827b17c4SGreg Kurz error_report("SLOF provided an unexpected CAS buffer size " 1000827b17c4SGreg Kurz TARGET_FMT_lu " (min: %zu, max: %u)", 1001827b17c4SGreg Kurz size, sizeof(hdr), FW_MAX_SIZE); 1002827b17c4SGreg Kurz exit(EXIT_FAILURE); 1003827b17c4SGreg Kurz } 1004827b17c4SGreg Kurz 100503d196b7SBharata B Rao size -= sizeof(hdr); 100603d196b7SBharata B Rao 100710f12e64SDaniel Henrique Barboza /* Create skeleton */ 100803d196b7SBharata B Rao fdt_skel = g_malloc0(size); 100903d196b7SBharata B Rao _FDT((fdt_create(fdt_skel, size))); 1010127f03e4SAlexey Kardashevskiy _FDT((fdt_finish_reservemap(fdt_skel))); 101103d196b7SBharata B Rao _FDT((fdt_begin_node(fdt_skel, ""))); 101203d196b7SBharata B Rao _FDT((fdt_end_node(fdt_skel))); 101303d196b7SBharata B Rao _FDT((fdt_finish(fdt_skel))); 101403d196b7SBharata B Rao fdt = g_malloc0(size); 101503d196b7SBharata B Rao _FDT((fdt_open_into(fdt_skel, fdt, size))); 101603d196b7SBharata B Rao g_free(fdt_skel); 101703d196b7SBharata B Rao 101803d196b7SBharata B Rao /* Fixup cpu nodes */ 101903d196b7SBharata B Rao _FDT((spapr_fixup_cpu_dt(fdt, spapr))); 102003d196b7SBharata B Rao 10216787d27bSMichael Roth if (spapr_dt_cas_updates(spapr, fdt, ov5_updates)) { 10226787d27bSMichael Roth return -1; 102303d196b7SBharata B Rao } 102403d196b7SBharata B Rao 102503d196b7SBharata B Rao /* Pack resulting tree */ 102603d196b7SBharata B Rao _FDT((fdt_pack(fdt))); 102703d196b7SBharata B Rao 102803d196b7SBharata B Rao if (fdt_totalsize(fdt) + sizeof(hdr) > size) { 102903d196b7SBharata B Rao trace_spapr_cas_failed(size); 103003d196b7SBharata B Rao return -1; 103103d196b7SBharata B Rao } 103203d196b7SBharata B Rao 103303d196b7SBharata B Rao cpu_physical_memory_write(addr, &hdr, sizeof(hdr)); 103403d196b7SBharata B Rao cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt)); 103503d196b7SBharata B Rao trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr)); 103603d196b7SBharata B Rao g_free(fdt); 103703d196b7SBharata B Rao 103803d196b7SBharata B Rao return 0; 103903d196b7SBharata B Rao } 104003d196b7SBharata B Rao 1041ce2918cbSDavid Gibson static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt) 10423f5dabceSDavid Gibson { 1043fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 10443f5dabceSDavid Gibson int rtas; 10453f5dabceSDavid Gibson GString *hypertas = g_string_sized_new(256); 10463f5dabceSDavid Gibson GString *qemu_hypertas = g_string_sized_new(256); 10473f5dabceSDavid Gibson uint32_t refpoints[] = { cpu_to_be32(0x4), cpu_to_be32(0x4) }; 10480c9269a5SDavid Hildenbrand uint64_t max_device_addr = MACHINE(spapr)->device_memory->base + 1049b0c14ec4SDavid Hildenbrand memory_region_size(&MACHINE(spapr)->device_memory->mr); 10503f5dabceSDavid Gibson uint32_t lrdr_capacity[] = { 10510c9269a5SDavid Hildenbrand cpu_to_be32(max_device_addr >> 32), 10520c9269a5SDavid Hildenbrand cpu_to_be32(max_device_addr & 0xffffffff), 10533f5dabceSDavid Gibson 0, cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE), 1054fe6b6346SLike Xu cpu_to_be32(ms->smp.max_cpus / ms->smp.threads), 10553f5dabceSDavid Gibson }; 1056ec132efaSAlexey Kardashevskiy uint32_t maxdomain = cpu_to_be32(spapr->gpu_numa_id > 1 ? 1 : 0); 1057da9f80fbSSerhii Popovych uint32_t maxdomains[] = { 1058da9f80fbSSerhii Popovych cpu_to_be32(4), 1059ec132efaSAlexey Kardashevskiy maxdomain, 1060ec132efaSAlexey Kardashevskiy maxdomain, 1061ec132efaSAlexey Kardashevskiy maxdomain, 1062ec132efaSAlexey Kardashevskiy cpu_to_be32(spapr->gpu_numa_id), 1063da9f80fbSSerhii Popovych }; 10643f5dabceSDavid Gibson 10653f5dabceSDavid Gibson _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas")); 10663f5dabceSDavid Gibson 10673f5dabceSDavid Gibson /* hypertas */ 10683f5dabceSDavid Gibson add_str(hypertas, "hcall-pft"); 10693f5dabceSDavid Gibson add_str(hypertas, "hcall-term"); 10703f5dabceSDavid Gibson add_str(hypertas, "hcall-dabr"); 10713f5dabceSDavid Gibson add_str(hypertas, "hcall-interrupt"); 10723f5dabceSDavid Gibson add_str(hypertas, "hcall-tce"); 10733f5dabceSDavid Gibson add_str(hypertas, "hcall-vio"); 10743f5dabceSDavid Gibson add_str(hypertas, "hcall-splpar"); 107510741314SNicholas Piggin add_str(hypertas, "hcall-join"); 10763f5dabceSDavid Gibson add_str(hypertas, "hcall-bulk"); 10773f5dabceSDavid Gibson add_str(hypertas, "hcall-set-mode"); 10783f5dabceSDavid Gibson add_str(hypertas, "hcall-sprg0"); 10793f5dabceSDavid Gibson add_str(hypertas, "hcall-copy"); 10803f5dabceSDavid Gibson add_str(hypertas, "hcall-debug"); 1081c24ba3d0SLaurent Vivier add_str(hypertas, "hcall-vphn"); 10823f5dabceSDavid Gibson add_str(qemu_hypertas, "hcall-memop1"); 10833f5dabceSDavid Gibson 10843f5dabceSDavid Gibson if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { 10853f5dabceSDavid Gibson add_str(hypertas, "hcall-multi-tce"); 10863f5dabceSDavid Gibson } 108730f4b05bSDavid Gibson 108830f4b05bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { 108930f4b05bSDavid Gibson add_str(hypertas, "hcall-hpt-resize"); 109030f4b05bSDavid Gibson } 109130f4b05bSDavid Gibson 10923f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions", 10933f5dabceSDavid Gibson hypertas->str, hypertas->len)); 10943f5dabceSDavid Gibson g_string_free(hypertas, TRUE); 10953f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "qemu,hypertas-functions", 10963f5dabceSDavid Gibson qemu_hypertas->str, qemu_hypertas->len)); 10973f5dabceSDavid Gibson g_string_free(qemu_hypertas, TRUE); 10983f5dabceSDavid Gibson 10993f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,associativity-reference-points", 11003f5dabceSDavid Gibson refpoints, sizeof(refpoints))); 11013f5dabceSDavid Gibson 1102da9f80fbSSerhii Popovych _FDT(fdt_setprop(fdt, rtas, "ibm,max-associativity-domains", 1103da9f80fbSSerhii Popovych maxdomains, sizeof(maxdomains))); 1104da9f80fbSSerhii Popovych 11053f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-error-log-max", 11063f5dabceSDavid Gibson RTAS_ERROR_LOG_MAX)); 11073f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-event-scan-rate", 11083f5dabceSDavid Gibson RTAS_EVENT_SCAN_RATE)); 11093f5dabceSDavid Gibson 11104f441474SDavid Gibson g_assert(msi_nonbroken); 11113f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,change-msix-capable", NULL, 0)); 11123f5dabceSDavid Gibson 11133f5dabceSDavid Gibson /* 11143f5dabceSDavid Gibson * According to PAPR, rtas ibm,os-term does not guarantee a return 11153f5dabceSDavid Gibson * back to the guest cpu. 11163f5dabceSDavid Gibson * 11173f5dabceSDavid Gibson * While an additional ibm,extended-os-term property indicates 11183f5dabceSDavid Gibson * that rtas call return will always occur. Set this property. 11193f5dabceSDavid Gibson */ 11203f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,extended-os-term", NULL, 0)); 11213f5dabceSDavid Gibson 11223f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,lrdr-capacity", 11233f5dabceSDavid Gibson lrdr_capacity, sizeof(lrdr_capacity))); 11243f5dabceSDavid Gibson 11253f5dabceSDavid Gibson spapr_dt_rtas_tokens(fdt, rtas); 11263f5dabceSDavid Gibson } 11273f5dabceSDavid Gibson 1128db592b5bSCédric Le Goater /* 1129db592b5bSCédric Le Goater * Prepare ibm,arch-vec-5-platform-support, which indicates the MMU 1130db592b5bSCédric Le Goater * and the XIVE features that the guest may request and thus the valid 1131db592b5bSCédric Le Goater * values for bytes 23..26 of option vector 5: 1132db592b5bSCédric Le Goater */ 1133ce2918cbSDavid Gibson static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt, 1134db592b5bSCédric Le Goater int chosen) 11359fb4541fSSam Bobroff { 1136545d6e2bSSuraj Jitindar Singh PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); 1137545d6e2bSSuraj Jitindar Singh 1138f2b14e3aSCédric Le Goater char val[2 * 4] = { 11393ba3d0bcSCédric Le Goater 23, spapr->irq->ov5, /* Xive mode. */ 11409fb4541fSSam Bobroff 24, 0x00, /* Hash/Radix, filled in below. */ 11419fb4541fSSam Bobroff 25, 0x00, /* Hash options: Segment Tables == no, GTSE == no. */ 11429fb4541fSSam Bobroff 26, 0x40, /* Radix options: GTSE == yes. */ 11439fb4541fSSam Bobroff }; 11449fb4541fSSam Bobroff 11457abd43baSSuraj Jitindar Singh if (!ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0, 11467abd43baSSuraj Jitindar Singh first_ppc_cpu->compat_pvr)) { 1147db592b5bSCédric Le Goater /* 1148db592b5bSCédric Le Goater * If we're in a pre POWER9 compat mode then the guest should 1149db592b5bSCédric Le Goater * do hash and use the legacy interrupt mode 1150db592b5bSCédric Le Goater */ 1151db592b5bSCédric Le Goater val[1] = 0x00; /* XICS */ 11527abd43baSSuraj Jitindar Singh val[3] = 0x00; /* Hash */ 11537abd43baSSuraj Jitindar Singh } else if (kvm_enabled()) { 11549fb4541fSSam Bobroff if (kvmppc_has_cap_mmu_radix() && kvmppc_has_cap_mmu_hash_v3()) { 1155f2b14e3aSCédric Le Goater val[3] = 0x80; /* OV5_MMU_BOTH */ 11569fb4541fSSam Bobroff } else if (kvmppc_has_cap_mmu_radix()) { 1157f2b14e3aSCédric Le Goater val[3] = 0x40; /* OV5_MMU_RADIX_300 */ 11589fb4541fSSam Bobroff } else { 1159f2b14e3aSCédric Le Goater val[3] = 0x00; /* Hash */ 11609fb4541fSSam Bobroff } 11619fb4541fSSam Bobroff } else { 11627abd43baSSuraj Jitindar Singh /* V3 MMU supports both hash and radix in tcg (with dynamic switching) */ 1163f2b14e3aSCédric Le Goater val[3] = 0xC0; 1164545d6e2bSSuraj Jitindar Singh } 11659fb4541fSSam Bobroff _FDT(fdt_setprop(fdt, chosen, "ibm,arch-vec-5-platform-support", 11669fb4541fSSam Bobroff val, sizeof(val))); 11679fb4541fSSam Bobroff } 11689fb4541fSSam Bobroff 1169ce2918cbSDavid Gibson static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt) 11707c866c6aSDavid Gibson { 11717c866c6aSDavid Gibson MachineState *machine = MACHINE(spapr); 11726c3829a2SAlexey Kardashevskiy SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 11737c866c6aSDavid Gibson int chosen; 11747c866c6aSDavid Gibson const char *boot_device = machine->boot_order; 11757c866c6aSDavid Gibson char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus); 11767c866c6aSDavid Gibson size_t cb = 0; 1177907aac2fSMark Cave-Ayland char *bootlist = get_boot_devices_list(&cb); 11787c866c6aSDavid Gibson 11797c866c6aSDavid Gibson _FDT(chosen = fdt_add_subnode(fdt, 0, "chosen")); 11807c866c6aSDavid Gibson 11817c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "bootargs", machine->kernel_cmdline)); 11827c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-start", 11837c866c6aSDavid Gibson spapr->initrd_base)); 11847c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-end", 11857c866c6aSDavid Gibson spapr->initrd_base + spapr->initrd_size)); 11867c866c6aSDavid Gibson 11877c866c6aSDavid Gibson if (spapr->kernel_size) { 11887c866c6aSDavid Gibson uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR), 11897c866c6aSDavid Gibson cpu_to_be64(spapr->kernel_size) }; 11907c866c6aSDavid Gibson 11917c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel", 11927c866c6aSDavid Gibson &kprop, sizeof(kprop))); 11937c866c6aSDavid Gibson if (spapr->kernel_le) { 11947c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel-le", NULL, 0)); 11957c866c6aSDavid Gibson } 11967c866c6aSDavid Gibson } 11977c866c6aSDavid Gibson if (boot_menu) { 11987c866c6aSDavid Gibson _FDT((fdt_setprop_cell(fdt, chosen, "qemu,boot-menu", boot_menu))); 11997c866c6aSDavid Gibson } 12007c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-width", graphic_width)); 12017c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-height", graphic_height)); 12027c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-depth", graphic_depth)); 12037c866c6aSDavid Gibson 12047c866c6aSDavid Gibson if (cb && bootlist) { 12057c866c6aSDavid Gibson int i; 12067c866c6aSDavid Gibson 12077c866c6aSDavid Gibson for (i = 0; i < cb; i++) { 12087c866c6aSDavid Gibson if (bootlist[i] == '\n') { 12097c866c6aSDavid Gibson bootlist[i] = ' '; 12107c866c6aSDavid Gibson } 12117c866c6aSDavid Gibson } 12127c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-list", bootlist)); 12137c866c6aSDavid Gibson } 12147c866c6aSDavid Gibson 12157c866c6aSDavid Gibson if (boot_device && strlen(boot_device)) { 12167c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-device", boot_device)); 12177c866c6aSDavid Gibson } 12187c866c6aSDavid Gibson 12197c866c6aSDavid Gibson if (!spapr->has_graphics && stdout_path) { 122090ee4e01SNikunj A Dadhania /* 122190ee4e01SNikunj A Dadhania * "linux,stdout-path" and "stdout" properties are deprecated by linux 122290ee4e01SNikunj A Dadhania * kernel. New platforms should only use the "stdout-path" property. Set 122390ee4e01SNikunj A Dadhania * the new property and continue using older property to remain 122490ee4e01SNikunj A Dadhania * compatible with the existing firmware. 122590ee4e01SNikunj A Dadhania */ 12267c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "linux,stdout-path", stdout_path)); 122790ee4e01SNikunj A Dadhania _FDT(fdt_setprop_string(fdt, chosen, "stdout-path", stdout_path)); 12287c866c6aSDavid Gibson } 12297c866c6aSDavid Gibson 12306c3829a2SAlexey Kardashevskiy /* We can deal with BAR reallocation just fine, advertise it to the guest */ 12316c3829a2SAlexey Kardashevskiy if (smc->linux_pci_probe) { 12326c3829a2SAlexey Kardashevskiy _FDT(fdt_setprop_cell(fdt, chosen, "linux,pci-probe-only", 0)); 12336c3829a2SAlexey Kardashevskiy } 12346c3829a2SAlexey Kardashevskiy 1235db592b5bSCédric Le Goater spapr_dt_ov5_platform_support(spapr, fdt, chosen); 12369fb4541fSSam Bobroff 12377c866c6aSDavid Gibson g_free(stdout_path); 12387c866c6aSDavid Gibson g_free(bootlist); 12397c866c6aSDavid Gibson } 12407c866c6aSDavid Gibson 1241ce2918cbSDavid Gibson static void spapr_dt_hypervisor(SpaprMachineState *spapr, void *fdt) 1242fca5f2dcSDavid Gibson { 1243fca5f2dcSDavid Gibson /* The /hypervisor node isn't in PAPR - this is a hack to allow PR 1244fca5f2dcSDavid Gibson * KVM to work under pHyp with some guest co-operation */ 1245fca5f2dcSDavid Gibson int hypervisor; 1246fca5f2dcSDavid Gibson uint8_t hypercall[16]; 1247fca5f2dcSDavid Gibson 1248fca5f2dcSDavid Gibson _FDT(hypervisor = fdt_add_subnode(fdt, 0, "hypervisor")); 1249fca5f2dcSDavid Gibson /* indicate KVM hypercall interface */ 1250fca5f2dcSDavid Gibson _FDT(fdt_setprop_string(fdt, hypervisor, "compatible", "linux,kvm")); 1251fca5f2dcSDavid Gibson if (kvmppc_has_cap_fixup_hcalls()) { 1252fca5f2dcSDavid Gibson /* 1253fca5f2dcSDavid Gibson * Older KVM versions with older guest kernels were broken 1254fca5f2dcSDavid Gibson * with the magic page, don't allow the guest to map it. 1255fca5f2dcSDavid Gibson */ 1256fca5f2dcSDavid Gibson if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall, 1257fca5f2dcSDavid Gibson sizeof(hypercall))) { 1258fca5f2dcSDavid Gibson _FDT(fdt_setprop(fdt, hypervisor, "hcall-instructions", 1259fca5f2dcSDavid Gibson hypercall, sizeof(hypercall))); 1260fca5f2dcSDavid Gibson } 1261fca5f2dcSDavid Gibson } 1262fca5f2dcSDavid Gibson } 1263fca5f2dcSDavid Gibson 1264ce2918cbSDavid Gibson static void *spapr_build_fdt(SpaprMachineState *spapr) 126553018216SPaolo Bonzini { 1266c86c1affSDaniel Henrique Barboza MachineState *machine = MACHINE(spapr); 12673c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 1268ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 12697c866c6aSDavid Gibson int ret; 127053018216SPaolo Bonzini void *fdt; 1271ce2918cbSDavid Gibson SpaprPhbState *phb; 1272398a0bd5SDavid Gibson char *buf; 127353018216SPaolo Bonzini 1274398a0bd5SDavid Gibson fdt = g_malloc0(FDT_MAX_SIZE); 1275398a0bd5SDavid Gibson _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 127653018216SPaolo Bonzini 1277398a0bd5SDavid Gibson /* Root node */ 1278398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "device_type", "chrp")); 1279398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "model", "IBM pSeries (emulated by qemu)")); 1280398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "compatible", "qemu,pseries")); 1281398a0bd5SDavid Gibson 12820a794529SDavid Gibson /* Guest UUID & Name*/ 1283398a0bd5SDavid Gibson buf = qemu_uuid_unparse_strdup(&qemu_uuid); 1284398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "vm,uuid", buf)); 1285398a0bd5SDavid Gibson if (qemu_uuid_set) { 1286398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "system-id", buf)); 1287398a0bd5SDavid Gibson } 1288398a0bd5SDavid Gibson g_free(buf); 1289398a0bd5SDavid Gibson 1290398a0bd5SDavid Gibson if (qemu_get_vm_name()) { 1291398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "ibm,partition-name", 1292398a0bd5SDavid Gibson qemu_get_vm_name())); 1293398a0bd5SDavid Gibson } 1294398a0bd5SDavid Gibson 12950a794529SDavid Gibson /* Host Model & Serial Number */ 12960a794529SDavid Gibson if (spapr->host_model) { 12970a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model)); 12980a794529SDavid Gibson } else if (smc->broken_host_serial_model && kvmppc_get_host_model(&buf)) { 12990a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-model", buf)); 13000a794529SDavid Gibson g_free(buf); 13010a794529SDavid Gibson } 13020a794529SDavid Gibson 13030a794529SDavid Gibson if (spapr->host_serial) { 13040a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial)); 13050a794529SDavid Gibson } else if (smc->broken_host_serial_model && kvmppc_get_host_serial(&buf)) { 13060a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf)); 13070a794529SDavid Gibson g_free(buf); 13080a794529SDavid Gibson } 13090a794529SDavid Gibson 1310398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#address-cells", 2)); 1311398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2)); 131253018216SPaolo Bonzini 1313fc7e0765SDavid Gibson /* /interrupt controller */ 13143ba3d0bcSCédric Le Goater spapr->irq->dt_populate(spapr, spapr_max_server_number(spapr), fdt, 13155c7adcf4SGreg Kurz PHANDLE_INTC); 1316fc7e0765SDavid Gibson 1317e8f986fcSBharata B Rao ret = spapr_populate_memory(spapr, fdt); 1318e8f986fcSBharata B Rao if (ret < 0) { 1319ce9863b7SCédric Le Goater error_report("couldn't setup memory nodes in fdt"); 1320e8f986fcSBharata B Rao exit(1); 132153018216SPaolo Bonzini } 132253018216SPaolo Bonzini 1323bf5a6696SDavid Gibson /* /vdevice */ 1324bf5a6696SDavid Gibson spapr_dt_vdevice(spapr->vio_bus, fdt); 132553018216SPaolo Bonzini 13264d9392beSThomas Huth if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) { 13274d9392beSThomas Huth ret = spapr_rng_populate_dt(fdt); 13284d9392beSThomas Huth if (ret < 0) { 1329ce9863b7SCédric Le Goater error_report("could not set up rng device in the fdt"); 13304d9392beSThomas Huth exit(1); 13314d9392beSThomas Huth } 13324d9392beSThomas Huth } 13334d9392beSThomas Huth 133453018216SPaolo Bonzini QLIST_FOREACH(phb, &spapr->phbs, list) { 1335466e8831SDavid Gibson ret = spapr_dt_phb(phb, PHANDLE_INTC, fdt, spapr->irq->nr_msis, NULL); 133653018216SPaolo Bonzini if (ret < 0) { 1337da34fed7SThomas Huth error_report("couldn't setup PCI devices in fdt"); 133853018216SPaolo Bonzini exit(1); 133953018216SPaolo Bonzini } 1340da34fed7SThomas Huth } 134153018216SPaolo Bonzini 13420da6f3feSBharata B Rao /* cpus */ 13430da6f3feSBharata B Rao spapr_populate_cpus_dt_node(fdt, spapr); 134453018216SPaolo Bonzini 1345c20d332aSBharata B Rao if (smc->dr_lmb_enabled) { 13469e7d38e8SDavid Gibson _FDT(spapr_dt_drc(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB)); 1347c20d332aSBharata B Rao } 1348c20d332aSBharata B Rao 1349c5514d0eSIgor Mammedov if (mc->has_hotpluggable_cpus) { 1350af81cf32SBharata B Rao int offset = fdt_path_offset(fdt, "/cpus"); 13519e7d38e8SDavid Gibson ret = spapr_dt_drc(fdt, offset, NULL, SPAPR_DR_CONNECTOR_TYPE_CPU); 1352af81cf32SBharata B Rao if (ret < 0) { 1353af81cf32SBharata B Rao error_report("Couldn't set up CPU DR device tree properties"); 1354af81cf32SBharata B Rao exit(1); 1355af81cf32SBharata B Rao } 1356af81cf32SBharata B Rao } 1357af81cf32SBharata B Rao 1358ffb1e275SDavid Gibson /* /event-sources */ 1359ffbb1705SMichael Roth spapr_dt_events(spapr, fdt); 1360ffb1e275SDavid Gibson 13613f5dabceSDavid Gibson /* /rtas */ 13623f5dabceSDavid Gibson spapr_dt_rtas(spapr, fdt); 13633f5dabceSDavid Gibson 13647c866c6aSDavid Gibson /* /chosen */ 13657c866c6aSDavid Gibson spapr_dt_chosen(spapr, fdt); 1366cf6e5223SDavid Gibson 1367fca5f2dcSDavid Gibson /* /hypervisor */ 1368fca5f2dcSDavid Gibson if (kvm_enabled()) { 1369fca5f2dcSDavid Gibson spapr_dt_hypervisor(spapr, fdt); 1370fca5f2dcSDavid Gibson } 1371fca5f2dcSDavid Gibson 1372cf6e5223SDavid Gibson /* Build memory reserve map */ 1373cf6e5223SDavid Gibson if (spapr->kernel_size) { 1374cf6e5223SDavid Gibson _FDT((fdt_add_mem_rsv(fdt, KERNEL_LOAD_ADDR, spapr->kernel_size))); 1375cf6e5223SDavid Gibson } 1376cf6e5223SDavid Gibson if (spapr->initrd_size) { 1377cf6e5223SDavid Gibson _FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base, spapr->initrd_size))); 1378cf6e5223SDavid Gibson } 1379cf6e5223SDavid Gibson 13806787d27bSMichael Roth /* ibm,client-architecture-support updates */ 13816787d27bSMichael Roth ret = spapr_dt_cas_updates(spapr, fdt, spapr->ov5_cas); 13826787d27bSMichael Roth if (ret < 0) { 13836787d27bSMichael Roth error_report("couldn't setup CAS properties fdt"); 13846787d27bSMichael Roth exit(1); 13856787d27bSMichael Roth } 13866787d27bSMichael Roth 13873998ccd0SNathan Fontenot if (smc->dr_phb_enabled) { 13889e7d38e8SDavid Gibson ret = spapr_dt_drc(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_PHB); 13893998ccd0SNathan Fontenot if (ret < 0) { 13903998ccd0SNathan Fontenot error_report("Couldn't set up PHB DR device tree properties"); 13913998ccd0SNathan Fontenot exit(1); 13923998ccd0SNathan Fontenot } 13933998ccd0SNathan Fontenot } 13943998ccd0SNathan Fontenot 1395997b6cfcSDavid Gibson return fdt; 139653018216SPaolo Bonzini } 139753018216SPaolo Bonzini 139853018216SPaolo Bonzini static uint64_t translate_kernel_address(void *opaque, uint64_t addr) 139953018216SPaolo Bonzini { 140053018216SPaolo Bonzini return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR; 140153018216SPaolo Bonzini } 140253018216SPaolo Bonzini 14031d1be34dSDavid Gibson static void emulate_spapr_hypercall(PPCVirtualHypervisor *vhyp, 14041d1be34dSDavid Gibson PowerPCCPU *cpu) 140553018216SPaolo Bonzini { 140653018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 140753018216SPaolo Bonzini 14088d04fb55SJan Kiszka /* The TCG path should also be holding the BQL at this point */ 14098d04fb55SJan Kiszka g_assert(qemu_mutex_iothread_locked()); 14108d04fb55SJan Kiszka 141153018216SPaolo Bonzini if (msr_pr) { 141253018216SPaolo Bonzini hcall_dprintf("Hypercall made with MSR[PR]=1\n"); 141353018216SPaolo Bonzini env->gpr[3] = H_PRIVILEGE; 141453018216SPaolo Bonzini } else { 141553018216SPaolo Bonzini env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]); 141653018216SPaolo Bonzini } 141753018216SPaolo Bonzini } 141853018216SPaolo Bonzini 141900fd075eSBenjamin Herrenschmidt struct LPCRSyncState { 142000fd075eSBenjamin Herrenschmidt target_ulong value; 142100fd075eSBenjamin Herrenschmidt target_ulong mask; 142200fd075eSBenjamin Herrenschmidt }; 142300fd075eSBenjamin Herrenschmidt 142400fd075eSBenjamin Herrenschmidt static void do_lpcr_sync(CPUState *cs, run_on_cpu_data arg) 142500fd075eSBenjamin Herrenschmidt { 142600fd075eSBenjamin Herrenschmidt struct LPCRSyncState *s = arg.host_ptr; 142700fd075eSBenjamin Herrenschmidt PowerPCCPU *cpu = POWERPC_CPU(cs); 142800fd075eSBenjamin Herrenschmidt CPUPPCState *env = &cpu->env; 142900fd075eSBenjamin Herrenschmidt target_ulong lpcr; 143000fd075eSBenjamin Herrenschmidt 143100fd075eSBenjamin Herrenschmidt cpu_synchronize_state(cs); 143200fd075eSBenjamin Herrenschmidt lpcr = env->spr[SPR_LPCR]; 143300fd075eSBenjamin Herrenschmidt lpcr &= ~s->mask; 143400fd075eSBenjamin Herrenschmidt lpcr |= s->value; 143500fd075eSBenjamin Herrenschmidt ppc_store_lpcr(cpu, lpcr); 143600fd075eSBenjamin Herrenschmidt } 143700fd075eSBenjamin Herrenschmidt 143800fd075eSBenjamin Herrenschmidt void spapr_set_all_lpcrs(target_ulong value, target_ulong mask) 143900fd075eSBenjamin Herrenschmidt { 144000fd075eSBenjamin Herrenschmidt CPUState *cs; 144100fd075eSBenjamin Herrenschmidt struct LPCRSyncState s = { 144200fd075eSBenjamin Herrenschmidt .value = value, 144300fd075eSBenjamin Herrenschmidt .mask = mask 144400fd075eSBenjamin Herrenschmidt }; 144500fd075eSBenjamin Herrenschmidt CPU_FOREACH(cs) { 144600fd075eSBenjamin Herrenschmidt run_on_cpu(cs, do_lpcr_sync, RUN_ON_CPU_HOST_PTR(&s)); 144700fd075eSBenjamin Herrenschmidt } 144800fd075eSBenjamin Herrenschmidt } 144900fd075eSBenjamin Herrenschmidt 145079825f4dSBenjamin Herrenschmidt static void spapr_get_pate(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry) 14519861bb3eSSuraj Jitindar Singh { 1452ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 14539861bb3eSSuraj Jitindar Singh 145479825f4dSBenjamin Herrenschmidt /* Copy PATE1:GR into PATE0:HR */ 145579825f4dSBenjamin Herrenschmidt entry->dw0 = spapr->patb_entry & PATE0_HR; 145679825f4dSBenjamin Herrenschmidt entry->dw1 = spapr->patb_entry; 14579861bb3eSSuraj Jitindar Singh } 14589861bb3eSSuraj Jitindar Singh 1459e6b8fd24SSamuel Mendoza-Jonas #define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2)) 1460e6b8fd24SSamuel Mendoza-Jonas #define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID) 1461e6b8fd24SSamuel Mendoza-Jonas #define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY) 1462e6b8fd24SSamuel Mendoza-Jonas #define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY)) 1463e6b8fd24SSamuel Mendoza-Jonas #define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY)) 1464e6b8fd24SSamuel Mendoza-Jonas 1465715c5407SDavid Gibson /* 1466715c5407SDavid Gibson * Get the fd to access the kernel htab, re-opening it if necessary 1467715c5407SDavid Gibson */ 1468ce2918cbSDavid Gibson static int get_htab_fd(SpaprMachineState *spapr) 1469715c5407SDavid Gibson { 147014b0d748SGreg Kurz Error *local_err = NULL; 147114b0d748SGreg Kurz 1472715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1473715c5407SDavid Gibson return spapr->htab_fd; 1474715c5407SDavid Gibson } 1475715c5407SDavid Gibson 147614b0d748SGreg Kurz spapr->htab_fd = kvmppc_get_htab_fd(false, 0, &local_err); 1477715c5407SDavid Gibson if (spapr->htab_fd < 0) { 147814b0d748SGreg Kurz error_report_err(local_err); 1479715c5407SDavid Gibson } 1480715c5407SDavid Gibson 1481715c5407SDavid Gibson return spapr->htab_fd; 1482715c5407SDavid Gibson } 1483715c5407SDavid Gibson 1484ce2918cbSDavid Gibson void close_htab_fd(SpaprMachineState *spapr) 1485715c5407SDavid Gibson { 1486715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1487715c5407SDavid Gibson close(spapr->htab_fd); 1488715c5407SDavid Gibson } 1489715c5407SDavid Gibson spapr->htab_fd = -1; 1490715c5407SDavid Gibson } 1491715c5407SDavid Gibson 1492e57ca75cSDavid Gibson static hwaddr spapr_hpt_mask(PPCVirtualHypervisor *vhyp) 1493e57ca75cSDavid Gibson { 1494ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1495e57ca75cSDavid Gibson 1496e57ca75cSDavid Gibson return HTAB_SIZE(spapr) / HASH_PTEG_SIZE_64 - 1; 1497e57ca75cSDavid Gibson } 1498e57ca75cSDavid Gibson 14991ec26c75SGreg Kurz static target_ulong spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp) 15001ec26c75SGreg Kurz { 1501ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 15021ec26c75SGreg Kurz 15031ec26c75SGreg Kurz assert(kvm_enabled()); 15041ec26c75SGreg Kurz 15051ec26c75SGreg Kurz if (!spapr->htab) { 15061ec26c75SGreg Kurz return 0; 15071ec26c75SGreg Kurz } 15081ec26c75SGreg Kurz 15091ec26c75SGreg Kurz return (target_ulong)(uintptr_t)spapr->htab | (spapr->htab_shift - 18); 15101ec26c75SGreg Kurz } 15111ec26c75SGreg Kurz 1512e57ca75cSDavid Gibson static const ppc_hash_pte64_t *spapr_map_hptes(PPCVirtualHypervisor *vhyp, 1513e57ca75cSDavid Gibson hwaddr ptex, int n) 1514e57ca75cSDavid Gibson { 1515ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1516e57ca75cSDavid Gibson hwaddr pte_offset = ptex * HASH_PTE_SIZE_64; 1517e57ca75cSDavid Gibson 1518e57ca75cSDavid Gibson if (!spapr->htab) { 1519e57ca75cSDavid Gibson /* 1520e57ca75cSDavid Gibson * HTAB is controlled by KVM. Fetch into temporary buffer 1521e57ca75cSDavid Gibson */ 1522e57ca75cSDavid Gibson ppc_hash_pte64_t *hptes = g_malloc(n * HASH_PTE_SIZE_64); 1523e57ca75cSDavid Gibson kvmppc_read_hptes(hptes, ptex, n); 1524e57ca75cSDavid Gibson return hptes; 1525e57ca75cSDavid Gibson } 1526e57ca75cSDavid Gibson 1527e57ca75cSDavid Gibson /* 1528e57ca75cSDavid Gibson * HTAB is controlled by QEMU. Just point to the internally 1529e57ca75cSDavid Gibson * accessible PTEG. 1530e57ca75cSDavid Gibson */ 1531e57ca75cSDavid Gibson return (const ppc_hash_pte64_t *)(spapr->htab + pte_offset); 1532e57ca75cSDavid Gibson } 1533e57ca75cSDavid Gibson 1534e57ca75cSDavid Gibson static void spapr_unmap_hptes(PPCVirtualHypervisor *vhyp, 1535e57ca75cSDavid Gibson const ppc_hash_pte64_t *hptes, 1536e57ca75cSDavid Gibson hwaddr ptex, int n) 1537e57ca75cSDavid Gibson { 1538ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1539e57ca75cSDavid Gibson 1540e57ca75cSDavid Gibson if (!spapr->htab) { 1541e57ca75cSDavid Gibson g_free((void *)hptes); 1542e57ca75cSDavid Gibson } 1543e57ca75cSDavid Gibson 1544e57ca75cSDavid Gibson /* Nothing to do for qemu managed HPT */ 1545e57ca75cSDavid Gibson } 1546e57ca75cSDavid Gibson 1547a2dd4e83SBenjamin Herrenschmidt void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex, 1548e57ca75cSDavid Gibson uint64_t pte0, uint64_t pte1) 1549e57ca75cSDavid Gibson { 1550a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(cpu->vhyp); 1551e57ca75cSDavid Gibson hwaddr offset = ptex * HASH_PTE_SIZE_64; 1552e57ca75cSDavid Gibson 1553e57ca75cSDavid Gibson if (!spapr->htab) { 1554e57ca75cSDavid Gibson kvmppc_write_hpte(ptex, pte0, pte1); 1555e57ca75cSDavid Gibson } else { 15563054b0caSBenjamin Herrenschmidt if (pte0 & HPTE64_V_VALID) { 1557e57ca75cSDavid Gibson stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); 15583054b0caSBenjamin Herrenschmidt /* 15593054b0caSBenjamin Herrenschmidt * When setting valid, we write PTE1 first. This ensures 15603054b0caSBenjamin Herrenschmidt * proper synchronization with the reading code in 15613054b0caSBenjamin Herrenschmidt * ppc_hash64_pteg_search() 15623054b0caSBenjamin Herrenschmidt */ 15633054b0caSBenjamin Herrenschmidt smp_wmb(); 15643054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset, pte0); 15653054b0caSBenjamin Herrenschmidt } else { 15663054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset, pte0); 15673054b0caSBenjamin Herrenschmidt /* 15683054b0caSBenjamin Herrenschmidt * When clearing it we set PTE0 first. This ensures proper 15693054b0caSBenjamin Herrenschmidt * synchronization with the reading code in 15703054b0caSBenjamin Herrenschmidt * ppc_hash64_pteg_search() 15713054b0caSBenjamin Herrenschmidt */ 15723054b0caSBenjamin Herrenschmidt smp_wmb(); 15733054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); 15743054b0caSBenjamin Herrenschmidt } 1575e57ca75cSDavid Gibson } 1576e57ca75cSDavid Gibson } 1577e57ca75cSDavid Gibson 1578a2dd4e83SBenjamin Herrenschmidt static void spapr_hpte_set_c(PPCVirtualHypervisor *vhyp, hwaddr ptex, 1579a2dd4e83SBenjamin Herrenschmidt uint64_t pte1) 1580a2dd4e83SBenjamin Herrenschmidt { 1581a2dd4e83SBenjamin Herrenschmidt hwaddr offset = ptex * HASH_PTE_SIZE_64 + 15; 1582a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1583a2dd4e83SBenjamin Herrenschmidt 1584a2dd4e83SBenjamin Herrenschmidt if (!spapr->htab) { 1585a2dd4e83SBenjamin Herrenschmidt /* There should always be a hash table when this is called */ 1586a2dd4e83SBenjamin Herrenschmidt error_report("spapr_hpte_set_c called with no hash table !"); 1587a2dd4e83SBenjamin Herrenschmidt return; 1588a2dd4e83SBenjamin Herrenschmidt } 1589a2dd4e83SBenjamin Herrenschmidt 1590a2dd4e83SBenjamin Herrenschmidt /* The HW performs a non-atomic byte update */ 1591a2dd4e83SBenjamin Herrenschmidt stb_p(spapr->htab + offset, (pte1 & 0xff) | 0x80); 1592a2dd4e83SBenjamin Herrenschmidt } 1593a2dd4e83SBenjamin Herrenschmidt 1594a2dd4e83SBenjamin Herrenschmidt static void spapr_hpte_set_r(PPCVirtualHypervisor *vhyp, hwaddr ptex, 1595a2dd4e83SBenjamin Herrenschmidt uint64_t pte1) 1596a2dd4e83SBenjamin Herrenschmidt { 1597a2dd4e83SBenjamin Herrenschmidt hwaddr offset = ptex * HASH_PTE_SIZE_64 + 14; 1598a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1599a2dd4e83SBenjamin Herrenschmidt 1600a2dd4e83SBenjamin Herrenschmidt if (!spapr->htab) { 1601a2dd4e83SBenjamin Herrenschmidt /* There should always be a hash table when this is called */ 1602a2dd4e83SBenjamin Herrenschmidt error_report("spapr_hpte_set_r called with no hash table !"); 1603a2dd4e83SBenjamin Herrenschmidt return; 1604a2dd4e83SBenjamin Herrenschmidt } 1605a2dd4e83SBenjamin Herrenschmidt 1606a2dd4e83SBenjamin Herrenschmidt /* The HW performs a non-atomic byte update */ 1607a2dd4e83SBenjamin Herrenschmidt stb_p(spapr->htab + offset, ((pte1 >> 8) & 0xff) | 0x01); 1608a2dd4e83SBenjamin Herrenschmidt } 1609a2dd4e83SBenjamin Herrenschmidt 16100b0b8310SDavid Gibson int spapr_hpt_shift_for_ramsize(uint64_t ramsize) 16118dfe8e7fSDavid Gibson { 16128dfe8e7fSDavid Gibson int shift; 16138dfe8e7fSDavid Gibson 16148dfe8e7fSDavid Gibson /* We aim for a hash table of size 1/128 the size of RAM (rounded 16158dfe8e7fSDavid Gibson * up). The PAPR recommendation is actually 1/64 of RAM size, but 16168dfe8e7fSDavid Gibson * that's much more than is needed for Linux guests */ 16178dfe8e7fSDavid Gibson shift = ctz64(pow2ceil(ramsize)) - 7; 16188dfe8e7fSDavid Gibson shift = MAX(shift, 18); /* Minimum architected size */ 16198dfe8e7fSDavid Gibson shift = MIN(shift, 46); /* Maximum architected size */ 16208dfe8e7fSDavid Gibson return shift; 16218dfe8e7fSDavid Gibson } 16228dfe8e7fSDavid Gibson 1623ce2918cbSDavid Gibson void spapr_free_hpt(SpaprMachineState *spapr) 162406ec79e8SBharata B Rao { 162506ec79e8SBharata B Rao g_free(spapr->htab); 162606ec79e8SBharata B Rao spapr->htab = NULL; 162706ec79e8SBharata B Rao spapr->htab_shift = 0; 162806ec79e8SBharata B Rao close_htab_fd(spapr); 162906ec79e8SBharata B Rao } 163006ec79e8SBharata B Rao 1631ce2918cbSDavid Gibson void spapr_reallocate_hpt(SpaprMachineState *spapr, int shift, 1632c5f54f3eSDavid Gibson Error **errp) 163353018216SPaolo Bonzini { 1634c5f54f3eSDavid Gibson long rc; 163553018216SPaolo Bonzini 1636c5f54f3eSDavid Gibson /* Clean up any HPT info from a previous boot */ 163706ec79e8SBharata B Rao spapr_free_hpt(spapr); 163853018216SPaolo Bonzini 1639c5f54f3eSDavid Gibson rc = kvmppc_reset_htab(shift); 1640c5f54f3eSDavid Gibson if (rc < 0) { 1641c5f54f3eSDavid Gibson /* kernel-side HPT needed, but couldn't allocate one */ 1642c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1643c5f54f3eSDavid Gibson "Failed to allocate KVM HPT of order %d (try smaller maxmem?)", 1644c5f54f3eSDavid Gibson shift); 1645c5f54f3eSDavid Gibson /* This is almost certainly fatal, but if the caller really 1646c5f54f3eSDavid Gibson * wants to carry on with shift == 0, it's welcome to try */ 1647c5f54f3eSDavid Gibson } else if (rc > 0) { 1648c5f54f3eSDavid Gibson /* kernel-side HPT allocated */ 1649c5f54f3eSDavid Gibson if (rc != shift) { 1650c5f54f3eSDavid Gibson error_setg(errp, 1651c5f54f3eSDavid Gibson "Requested order %d HPT, but kernel allocated order %ld (try smaller maxmem?)", 1652c5f54f3eSDavid Gibson shift, rc); 16537735fedaSBharata B Rao } 16547735fedaSBharata B Rao 165553018216SPaolo Bonzini spapr->htab_shift = shift; 1656c18ad9a5SDavid Gibson spapr->htab = NULL; 1657b817772aSBharata B Rao } else { 1658c5f54f3eSDavid Gibson /* kernel-side HPT not needed, allocate in userspace instead */ 1659c5f54f3eSDavid Gibson size_t size = 1ULL << shift; 1660c5f54f3eSDavid Gibson int i; 166101a57972SSamuel Mendoza-Jonas 1662c5f54f3eSDavid Gibson spapr->htab = qemu_memalign(size, size); 1663c5f54f3eSDavid Gibson if (!spapr->htab) { 1664c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1665c5f54f3eSDavid Gibson "Could not allocate HPT of order %d", shift); 1666c5f54f3eSDavid Gibson return; 1667b817772aSBharata B Rao } 1668b817772aSBharata B Rao 1669c5f54f3eSDavid Gibson memset(spapr->htab, 0, size); 1670c5f54f3eSDavid Gibson spapr->htab_shift = shift; 1671b817772aSBharata B Rao 1672c5f54f3eSDavid Gibson for (i = 0; i < size / HASH_PTE_SIZE_64; i++) { 1673c5f54f3eSDavid Gibson DIRTY_HPTE(HPTE(spapr->htab, i)); 16747735fedaSBharata B Rao } 167553018216SPaolo Bonzini } 1676ee4d9eccSSuraj Jitindar Singh /* We're setting up a hash table, so that means we're not radix */ 1677176dcceeSSuraj Jitindar Singh spapr->patb_entry = 0; 167800fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(0, LPCR_HR | LPCR_UPRT); 167953018216SPaolo Bonzini } 168053018216SPaolo Bonzini 1681ce2918cbSDavid Gibson void spapr_setup_hpt_and_vrma(SpaprMachineState *spapr) 1682b4db5413SSuraj Jitindar Singh { 16832772cf6bSDavid Gibson int hpt_shift; 16842772cf6bSDavid Gibson 16852772cf6bSDavid Gibson if ((spapr->resize_hpt == SPAPR_RESIZE_HPT_DISABLED) 16862772cf6bSDavid Gibson || (spapr->cas_reboot 16872772cf6bSDavid Gibson && !spapr_ovec_test(spapr->ov5_cas, OV5_HPT_RESIZE))) { 16882772cf6bSDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(MACHINE(spapr)->maxram_size); 16892772cf6bSDavid Gibson } else { 1690768a20f3SDavid Gibson uint64_t current_ram_size; 1691768a20f3SDavid Gibson 1692768a20f3SDavid Gibson current_ram_size = MACHINE(spapr)->ram_size + get_plugged_memory_size(); 1693768a20f3SDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(current_ram_size); 16942772cf6bSDavid Gibson } 16952772cf6bSDavid Gibson spapr_reallocate_hpt(spapr, hpt_shift, &error_fatal); 16962772cf6bSDavid Gibson 1697b4db5413SSuraj Jitindar Singh if (spapr->vrma_adjust) { 1698c86c1affSDaniel Henrique Barboza spapr->rma_size = kvmppc_rma_size(spapr_node0_size(MACHINE(spapr)), 1699b4db5413SSuraj Jitindar Singh spapr->htab_shift); 1700b4db5413SSuraj Jitindar Singh } 1701b4db5413SSuraj Jitindar Singh } 1702b4db5413SSuraj Jitindar Singh 170382512483SGreg Kurz static int spapr_reset_drcs(Object *child, void *opaque) 170482512483SGreg Kurz { 1705ce2918cbSDavid Gibson SpaprDrc *drc = 1706ce2918cbSDavid Gibson (SpaprDrc *) object_dynamic_cast(child, 170782512483SGreg Kurz TYPE_SPAPR_DR_CONNECTOR); 170882512483SGreg Kurz 170982512483SGreg Kurz if (drc) { 171082512483SGreg Kurz spapr_drc_reset(drc); 171182512483SGreg Kurz } 171282512483SGreg Kurz 171382512483SGreg Kurz return 0; 171482512483SGreg Kurz } 171582512483SGreg Kurz 1716a0628599SLike Xu static void spapr_machine_reset(MachineState *machine) 171753018216SPaolo Bonzini { 1718ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(machine); 1719182735efSAndreas Färber PowerPCCPU *first_ppc_cpu; 1720b7d1f77aSBenjamin Herrenschmidt uint32_t rtas_limit; 1721cae172abSDavid Gibson hwaddr rtas_addr, fdt_addr; 1722997b6cfcSDavid Gibson void *fdt; 1723997b6cfcSDavid Gibson int rc; 1724259186a7SAndreas Färber 17259f6edd06SDavid Gibson spapr_caps_apply(spapr); 172633face6bSDavid Gibson 17271481fe5fSLaurent Vivier first_ppc_cpu = POWERPC_CPU(first_cpu); 17281481fe5fSLaurent Vivier if (kvm_enabled() && kvmppc_has_cap_mmu_radix() && 1729ad99d04cSDavid Gibson ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, 17301481fe5fSLaurent Vivier spapr->max_compat_pvr)) { 173179825f4dSBenjamin Herrenschmidt /* 173279825f4dSBenjamin Herrenschmidt * If using KVM with radix mode available, VCPUs can be started 1733b4db5413SSuraj Jitindar Singh * without a HPT because KVM will start them in radix mode. 173479825f4dSBenjamin Herrenschmidt * Set the GR bit in PATE so that we know there is no HPT. 173579825f4dSBenjamin Herrenschmidt */ 173679825f4dSBenjamin Herrenschmidt spapr->patb_entry = PATE1_GR; 173700fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(LPCR_HR | LPCR_UPRT, LPCR_HR | LPCR_UPRT); 1738b4db5413SSuraj Jitindar Singh } else { 1739b4db5413SSuraj Jitindar Singh spapr_setup_hpt_and_vrma(spapr); 1740c5f54f3eSDavid Gibson } 174153018216SPaolo Bonzini 174279825f4dSBenjamin Herrenschmidt /* 174325c9780dSDavid Gibson * NVLink2-connected GPU RAM needs to be placed on a separate NUMA node. 174425c9780dSDavid Gibson * We assign a new numa ID per GPU in spapr_pci_collect_nvgpu() which is 174525c9780dSDavid Gibson * called from vPHB reset handler so we initialize the counter here. 174625c9780dSDavid Gibson * If no NUMA is configured from the QEMU side, we start from 1 as GPU RAM 174725c9780dSDavid Gibson * must be equally distant from any other node. 174825c9780dSDavid Gibson * The final value of spapr->gpu_numa_id is going to be written to 174925c9780dSDavid Gibson * max-associativity-domains in spapr_build_fdt(). 175025c9780dSDavid Gibson */ 1751aa570207STao Xu spapr->gpu_numa_id = MAX(1, machine->numa_state->num_nodes); 175225c9780dSDavid Gibson qemu_devices_reset(); 175325c9780dSDavid Gibson 175425c9780dSDavid Gibson /* 175579825f4dSBenjamin Herrenschmidt * If this reset wasn't generated by CAS, we should reset our 175679825f4dSBenjamin Herrenschmidt * negotiated options and start from scratch 175779825f4dSBenjamin Herrenschmidt */ 17589012a53fSGreg Kurz if (!spapr->cas_reboot) { 17599012a53fSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas); 17609012a53fSGreg Kurz spapr->ov5_cas = spapr_ovec_new(); 17619012a53fSGreg Kurz 1762ce03a193SLaurent Vivier ppc_set_compat_all(spapr->max_compat_pvr, &error_fatal); 17639012a53fSGreg Kurz } 17649012a53fSGreg Kurz 1765ec132efaSAlexey Kardashevskiy /* 1766b2e22477SCédric Le Goater * This is fixing some of the default configuration of the XIVE 1767b2e22477SCédric Le Goater * devices. To be called after the reset of the machine devices. 1768b2e22477SCédric Le Goater */ 1769b2e22477SCédric Le Goater spapr_irq_reset(spapr, &error_fatal); 1770b2e22477SCédric Le Goater 177123ff81bdSGreg Kurz /* 177223ff81bdSGreg Kurz * There is no CAS under qtest. Simulate one to please the code that 177323ff81bdSGreg Kurz * depends on spapr->ov5_cas. This is especially needed to test device 177423ff81bdSGreg Kurz * unplug, so we do that before resetting the DRCs. 177523ff81bdSGreg Kurz */ 177623ff81bdSGreg Kurz if (qtest_enabled()) { 177723ff81bdSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas); 177823ff81bdSGreg Kurz spapr->ov5_cas = spapr_ovec_clone(spapr->ov5); 177923ff81bdSGreg Kurz } 178023ff81bdSGreg Kurz 178182512483SGreg Kurz /* DRC reset may cause a device to be unplugged. This will cause troubles 178282512483SGreg Kurz * if this device is used by another device (eg, a running vhost backend 178382512483SGreg Kurz * will crash QEMU if the DIMM holding the vring goes away). To avoid such 178482512483SGreg Kurz * situations, we reset DRCs after all devices have been reset. 178582512483SGreg Kurz */ 178682512483SGreg Kurz object_child_foreach_recursive(object_get_root(), spapr_reset_drcs, NULL); 178782512483SGreg Kurz 178856258174SDaniel Henrique Barboza spapr_clear_pending_events(spapr); 178953018216SPaolo Bonzini 1790b7d1f77aSBenjamin Herrenschmidt /* 1791b7d1f77aSBenjamin Herrenschmidt * We place the device tree and RTAS just below either the top of the RMA, 1792df269271SAlexey Kardashevskiy * or just below 2GB, whichever is lower, so that it can be 1793b7d1f77aSBenjamin Herrenschmidt * processed with 32-bit real mode code if necessary 1794b7d1f77aSBenjamin Herrenschmidt */ 1795b7d1f77aSBenjamin Herrenschmidt rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR); 1796cae172abSDavid Gibson rtas_addr = rtas_limit - RTAS_MAX_SIZE; 1797cae172abSDavid Gibson fdt_addr = rtas_addr - FDT_MAX_SIZE; 1798b7d1f77aSBenjamin Herrenschmidt 1799df269271SAlexey Kardashevskiy fdt = spapr_build_fdt(spapr); 180053018216SPaolo Bonzini 18012cac78c1SDavid Gibson spapr_load_rtas(spapr, fdt, rtas_addr); 1802b7d1f77aSBenjamin Herrenschmidt 1803997b6cfcSDavid Gibson rc = fdt_pack(fdt); 1804997b6cfcSDavid Gibson 1805997b6cfcSDavid Gibson /* Should only fail if we've built a corrupted tree */ 1806997b6cfcSDavid Gibson assert(rc == 0); 1807997b6cfcSDavid Gibson 1808997b6cfcSDavid Gibson if (fdt_totalsize(fdt) > FDT_MAX_SIZE) { 1809997b6cfcSDavid Gibson error_report("FDT too big ! 0x%x bytes (max is 0x%x)", 1810997b6cfcSDavid Gibson fdt_totalsize(fdt), FDT_MAX_SIZE); 1811997b6cfcSDavid Gibson exit(1); 1812997b6cfcSDavid Gibson } 1813997b6cfcSDavid Gibson 1814997b6cfcSDavid Gibson /* Load the fdt */ 1815997b6cfcSDavid Gibson qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 1816cae172abSDavid Gibson cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); 1817fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob); 1818fea35ca4SAlexey Kardashevskiy spapr->fdt_size = fdt_totalsize(fdt); 1819fea35ca4SAlexey Kardashevskiy spapr->fdt_initial_size = spapr->fdt_size; 1820fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = fdt; 1821997b6cfcSDavid Gibson 182253018216SPaolo Bonzini /* Set up the entry state */ 182384369f63SDavid Gibson spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT, fdt_addr); 1824182735efSAndreas Färber first_ppc_cpu->env.gpr[5] = 0; 182553018216SPaolo Bonzini 18266787d27bSMichael Roth spapr->cas_reboot = false; 182753018216SPaolo Bonzini } 182853018216SPaolo Bonzini 1829ce2918cbSDavid Gibson static void spapr_create_nvram(SpaprMachineState *spapr) 183053018216SPaolo Bonzini { 18312ff3de68SMarkus Armbruster DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); 18323978b863SPaolo Bonzini DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); 183353018216SPaolo Bonzini 18343978b863SPaolo Bonzini if (dinfo) { 18356231a6daSMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo), 18366231a6daSMarkus Armbruster &error_fatal); 183753018216SPaolo Bonzini } 183853018216SPaolo Bonzini 183953018216SPaolo Bonzini qdev_init_nofail(dev); 184053018216SPaolo Bonzini 1841ce2918cbSDavid Gibson spapr->nvram = (struct SpaprNvram *)dev; 184253018216SPaolo Bonzini } 184353018216SPaolo Bonzini 1844ce2918cbSDavid Gibson static void spapr_rtc_create(SpaprMachineState *spapr) 184528df36a1SDavid Gibson { 1846f6d4dca8SThomas Huth object_initialize_child(OBJECT(spapr), "rtc", 1847f6d4dca8SThomas Huth &spapr->rtc, sizeof(spapr->rtc), TYPE_SPAPR_RTC, 1848f6d4dca8SThomas Huth &error_fatal, NULL); 1849147ff807SCédric Le Goater object_property_set_bool(OBJECT(&spapr->rtc), true, "realized", 1850147ff807SCédric Le Goater &error_fatal); 1851147ff807SCédric Le Goater object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc), 1852147ff807SCédric Le Goater "date", &error_fatal); 185328df36a1SDavid Gibson } 185428df36a1SDavid Gibson 185553018216SPaolo Bonzini /* Returns whether we want to use VGA or not */ 185614c6a894SDavid Gibson static bool spapr_vga_init(PCIBus *pci_bus, Error **errp) 185753018216SPaolo Bonzini { 185853018216SPaolo Bonzini switch (vga_interface_type) { 185953018216SPaolo Bonzini case VGA_NONE: 18607effdaa3SMark Wu return false; 18617effdaa3SMark Wu case VGA_DEVICE: 18627effdaa3SMark Wu return true; 186353018216SPaolo Bonzini case VGA_STD: 1864b798c190SBenjamin Herrenschmidt case VGA_VIRTIO: 18656e66d0c6SThomas Huth case VGA_CIRRUS: 186653018216SPaolo Bonzini return pci_vga_init(pci_bus) != NULL; 186753018216SPaolo Bonzini default: 186814c6a894SDavid Gibson error_setg(errp, 186914c6a894SDavid Gibson "Unsupported VGA mode, only -vga std or -vga virtio is supported"); 187014c6a894SDavid Gibson return false; 187153018216SPaolo Bonzini } 187253018216SPaolo Bonzini } 187353018216SPaolo Bonzini 18744e5fe368SSuraj Jitindar Singh static int spapr_pre_load(void *opaque) 18754e5fe368SSuraj Jitindar Singh { 18764e5fe368SSuraj Jitindar Singh int rc; 18774e5fe368SSuraj Jitindar Singh 18784e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_load(opaque); 18794e5fe368SSuraj Jitindar Singh if (rc) { 18804e5fe368SSuraj Jitindar Singh return rc; 18814e5fe368SSuraj Jitindar Singh } 18824e5fe368SSuraj Jitindar Singh 18834e5fe368SSuraj Jitindar Singh return 0; 18844e5fe368SSuraj Jitindar Singh } 18854e5fe368SSuraj Jitindar Singh 1886880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id) 1887880ae7deSDavid Gibson { 1888ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 1889880ae7deSDavid Gibson int err = 0; 1890880ae7deSDavid Gibson 1891be85537dSDavid Gibson err = spapr_caps_post_migration(spapr); 1892be85537dSDavid Gibson if (err) { 1893be85537dSDavid Gibson return err; 1894be85537dSDavid Gibson } 1895be85537dSDavid Gibson 1896e502202cSCédric Le Goater /* 1897e502202cSCédric Le Goater * In earlier versions, there was no separate qdev for the PAPR 1898880ae7deSDavid Gibson * RTC, so the RTC offset was stored directly in sPAPREnvironment. 1899880ae7deSDavid Gibson * So when migrating from those versions, poke the incoming offset 1900e502202cSCédric Le Goater * value into the RTC device 1901e502202cSCédric Le Goater */ 1902880ae7deSDavid Gibson if (version_id < 3) { 1903147ff807SCédric Le Goater err = spapr_rtc_import_offset(&spapr->rtc, spapr->rtc_offset); 1904e502202cSCédric Le Goater if (err) { 1905e502202cSCédric Le Goater return err; 1906e502202cSCédric Le Goater } 1907880ae7deSDavid Gibson } 1908880ae7deSDavid Gibson 19090c86b2dfSLaurent Vivier if (kvm_enabled() && spapr->patb_entry) { 1910d39c90f5SBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(first_cpu); 191179825f4dSBenjamin Herrenschmidt bool radix = !!(spapr->patb_entry & PATE1_GR); 1912d39c90f5SBharata B Rao bool gtse = !!(cpu->env.spr[SPR_LPCR] & LPCR_GTSE); 1913d39c90f5SBharata B Rao 191400fd075eSBenjamin Herrenschmidt /* 191500fd075eSBenjamin Herrenschmidt * Update LPCR:HR and UPRT as they may not be set properly in 191600fd075eSBenjamin Herrenschmidt * the stream 191700fd075eSBenjamin Herrenschmidt */ 191800fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(radix ? (LPCR_HR | LPCR_UPRT) : 0, 191900fd075eSBenjamin Herrenschmidt LPCR_HR | LPCR_UPRT); 192000fd075eSBenjamin Herrenschmidt 1921d39c90f5SBharata B Rao err = kvmppc_configure_v3_mmu(cpu, radix, gtse, spapr->patb_entry); 1922d39c90f5SBharata B Rao if (err) { 1923d39c90f5SBharata B Rao error_report("Process table config unsupported by the host"); 1924d39c90f5SBharata B Rao return -EINVAL; 1925d39c90f5SBharata B Rao } 1926d39c90f5SBharata B Rao } 1927d39c90f5SBharata B Rao 19281c53b06cSCédric Le Goater err = spapr_irq_post_load(spapr, version_id); 19291c53b06cSCédric Le Goater if (err) { 19301c53b06cSCédric Le Goater return err; 19311c53b06cSCédric Le Goater } 19321c53b06cSCédric Le Goater 1933880ae7deSDavid Gibson return err; 1934880ae7deSDavid Gibson } 1935880ae7deSDavid Gibson 19364e5fe368SSuraj Jitindar Singh static int spapr_pre_save(void *opaque) 19374e5fe368SSuraj Jitindar Singh { 19384e5fe368SSuraj Jitindar Singh int rc; 19394e5fe368SSuraj Jitindar Singh 19404e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_save(opaque); 19414e5fe368SSuraj Jitindar Singh if (rc) { 19424e5fe368SSuraj Jitindar Singh return rc; 19434e5fe368SSuraj Jitindar Singh } 19444e5fe368SSuraj Jitindar Singh 19454e5fe368SSuraj Jitindar Singh return 0; 19464e5fe368SSuraj Jitindar Singh } 19474e5fe368SSuraj Jitindar Singh 1948880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id) 1949880ae7deSDavid Gibson { 1950880ae7deSDavid Gibson return version_id < 3; 1951880ae7deSDavid Gibson } 1952880ae7deSDavid Gibson 1953fd38804bSDaniel Henrique Barboza static bool spapr_pending_events_needed(void *opaque) 1954fd38804bSDaniel Henrique Barboza { 1955ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 1956fd38804bSDaniel Henrique Barboza return !QTAILQ_EMPTY(&spapr->pending_events); 1957fd38804bSDaniel Henrique Barboza } 1958fd38804bSDaniel Henrique Barboza 1959fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_event_entry = { 1960fd38804bSDaniel Henrique Barboza .name = "spapr_event_log_entry", 1961fd38804bSDaniel Henrique Barboza .version_id = 1, 1962fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1963fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 1964ce2918cbSDavid Gibson VMSTATE_UINT32(summary, SpaprEventLogEntry), 1965ce2918cbSDavid Gibson VMSTATE_UINT32(extended_length, SpaprEventLogEntry), 1966ce2918cbSDavid Gibson VMSTATE_VBUFFER_ALLOC_UINT32(extended_log, SpaprEventLogEntry, 0, 19675341258eSDavid Gibson NULL, extended_length), 1968fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1969fd38804bSDaniel Henrique Barboza }, 1970fd38804bSDaniel Henrique Barboza }; 1971fd38804bSDaniel Henrique Barboza 1972fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_pending_events = { 1973fd38804bSDaniel Henrique Barboza .name = "spapr_pending_events", 1974fd38804bSDaniel Henrique Barboza .version_id = 1, 1975fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1976fd38804bSDaniel Henrique Barboza .needed = spapr_pending_events_needed, 1977fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 1978ce2918cbSDavid Gibson VMSTATE_QTAILQ_V(pending_events, SpaprMachineState, 1, 1979ce2918cbSDavid Gibson vmstate_spapr_event_entry, SpaprEventLogEntry, next), 1980fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1981fd38804bSDaniel Henrique Barboza }, 1982fd38804bSDaniel Henrique Barboza }; 1983fd38804bSDaniel Henrique Barboza 198462ef3760SMichael Roth static bool spapr_ov5_cas_needed(void *opaque) 198562ef3760SMichael Roth { 1986ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 1987ce2918cbSDavid Gibson SpaprOptionVector *ov5_mask = spapr_ovec_new(); 1988ce2918cbSDavid Gibson SpaprOptionVector *ov5_legacy = spapr_ovec_new(); 1989ce2918cbSDavid Gibson SpaprOptionVector *ov5_removed = spapr_ovec_new(); 199062ef3760SMichael Roth bool cas_needed; 199162ef3760SMichael Roth 1992ce2918cbSDavid Gibson /* Prior to the introduction of SpaprOptionVector, we had two option 199362ef3760SMichael Roth * vectors we dealt with: OV5_FORM1_AFFINITY, and OV5_DRCONF_MEMORY. 199462ef3760SMichael Roth * Both of these options encode machine topology into the device-tree 199562ef3760SMichael Roth * in such a way that the now-booted OS should still be able to interact 199662ef3760SMichael Roth * appropriately with QEMU regardless of what options were actually 199762ef3760SMichael Roth * negotiatied on the source side. 199862ef3760SMichael Roth * 199962ef3760SMichael Roth * As such, we can avoid migrating the CAS-negotiated options if these 200062ef3760SMichael Roth * are the only options available on the current machine/platform. 200162ef3760SMichael Roth * Since these are the only options available for pseries-2.7 and 200262ef3760SMichael Roth * earlier, this allows us to maintain old->new/new->old migration 200362ef3760SMichael Roth * compatibility. 200462ef3760SMichael Roth * 200562ef3760SMichael Roth * For QEMU 2.8+, there are additional CAS-negotiatable options available 200662ef3760SMichael Roth * via default pseries-2.8 machines and explicit command-line parameters. 200762ef3760SMichael Roth * Some of these options, like OV5_HP_EVT, *do* require QEMU to be aware 200862ef3760SMichael Roth * of the actual CAS-negotiated values to continue working properly. For 200962ef3760SMichael Roth * example, availability of memory unplug depends on knowing whether 201062ef3760SMichael Roth * OV5_HP_EVT was negotiated via CAS. 201162ef3760SMichael Roth * 201262ef3760SMichael Roth * Thus, for any cases where the set of available CAS-negotiatable 201362ef3760SMichael Roth * options extends beyond OV5_FORM1_AFFINITY and OV5_DRCONF_MEMORY, we 2014aef19c04SGreg Kurz * include the CAS-negotiated options in the migration stream, unless 2015aef19c04SGreg Kurz * if they affect boot time behaviour only. 201662ef3760SMichael Roth */ 201762ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_FORM1_AFFINITY); 201862ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_DRCONF_MEMORY); 2019aef19c04SGreg Kurz spapr_ovec_set(ov5_mask, OV5_DRMEM_V2); 202062ef3760SMichael Roth 202162ef3760SMichael Roth /* spapr_ovec_diff returns true if bits were removed. we avoid using 202262ef3760SMichael Roth * the mask itself since in the future it's possible "legacy" bits may be 202362ef3760SMichael Roth * removed via machine options, which could generate a false positive 202462ef3760SMichael Roth * that breaks migration. 202562ef3760SMichael Roth */ 202662ef3760SMichael Roth spapr_ovec_intersect(ov5_legacy, spapr->ov5, ov5_mask); 202762ef3760SMichael Roth cas_needed = spapr_ovec_diff(ov5_removed, spapr->ov5, ov5_legacy); 202862ef3760SMichael Roth 202962ef3760SMichael Roth spapr_ovec_cleanup(ov5_mask); 203062ef3760SMichael Roth spapr_ovec_cleanup(ov5_legacy); 203162ef3760SMichael Roth spapr_ovec_cleanup(ov5_removed); 203262ef3760SMichael Roth 203362ef3760SMichael Roth return cas_needed; 203462ef3760SMichael Roth } 203562ef3760SMichael Roth 203662ef3760SMichael Roth static const VMStateDescription vmstate_spapr_ov5_cas = { 203762ef3760SMichael Roth .name = "spapr_option_vector_ov5_cas", 203862ef3760SMichael Roth .version_id = 1, 203962ef3760SMichael Roth .minimum_version_id = 1, 204062ef3760SMichael Roth .needed = spapr_ov5_cas_needed, 204162ef3760SMichael Roth .fields = (VMStateField[]) { 2042ce2918cbSDavid Gibson VMSTATE_STRUCT_POINTER_V(ov5_cas, SpaprMachineState, 1, 2043ce2918cbSDavid Gibson vmstate_spapr_ovec, SpaprOptionVector), 204462ef3760SMichael Roth VMSTATE_END_OF_LIST() 204562ef3760SMichael Roth }, 204662ef3760SMichael Roth }; 204762ef3760SMichael Roth 20489861bb3eSSuraj Jitindar Singh static bool spapr_patb_entry_needed(void *opaque) 20499861bb3eSSuraj Jitindar Singh { 2050ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 20519861bb3eSSuraj Jitindar Singh 20529861bb3eSSuraj Jitindar Singh return !!spapr->patb_entry; 20539861bb3eSSuraj Jitindar Singh } 20549861bb3eSSuraj Jitindar Singh 20559861bb3eSSuraj Jitindar Singh static const VMStateDescription vmstate_spapr_patb_entry = { 20569861bb3eSSuraj Jitindar Singh .name = "spapr_patb_entry", 20579861bb3eSSuraj Jitindar Singh .version_id = 1, 20589861bb3eSSuraj Jitindar Singh .minimum_version_id = 1, 20599861bb3eSSuraj Jitindar Singh .needed = spapr_patb_entry_needed, 20609861bb3eSSuraj Jitindar Singh .fields = (VMStateField[]) { 2061ce2918cbSDavid Gibson VMSTATE_UINT64(patb_entry, SpaprMachineState), 20629861bb3eSSuraj Jitindar Singh VMSTATE_END_OF_LIST() 20639861bb3eSSuraj Jitindar Singh }, 20649861bb3eSSuraj Jitindar Singh }; 20659861bb3eSSuraj Jitindar Singh 206682cffa2eSCédric Le Goater static bool spapr_irq_map_needed(void *opaque) 206782cffa2eSCédric Le Goater { 2068ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 206982cffa2eSCédric Le Goater 207082cffa2eSCédric Le Goater return spapr->irq_map && !bitmap_empty(spapr->irq_map, spapr->irq_map_nr); 207182cffa2eSCédric Le Goater } 207282cffa2eSCédric Le Goater 207382cffa2eSCédric Le Goater static const VMStateDescription vmstate_spapr_irq_map = { 207482cffa2eSCédric Le Goater .name = "spapr_irq_map", 207582cffa2eSCédric Le Goater .version_id = 1, 207682cffa2eSCédric Le Goater .minimum_version_id = 1, 207782cffa2eSCédric Le Goater .needed = spapr_irq_map_needed, 207882cffa2eSCédric Le Goater .fields = (VMStateField[]) { 2079ce2918cbSDavid Gibson VMSTATE_BITMAP(irq_map, SpaprMachineState, 0, irq_map_nr), 208082cffa2eSCédric Le Goater VMSTATE_END_OF_LIST() 208182cffa2eSCédric Le Goater }, 208282cffa2eSCédric Le Goater }; 208382cffa2eSCédric Le Goater 2084fea35ca4SAlexey Kardashevskiy static bool spapr_dtb_needed(void *opaque) 2085fea35ca4SAlexey Kardashevskiy { 2086ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(opaque); 2087fea35ca4SAlexey Kardashevskiy 2088fea35ca4SAlexey Kardashevskiy return smc->update_dt_enabled; 2089fea35ca4SAlexey Kardashevskiy } 2090fea35ca4SAlexey Kardashevskiy 2091fea35ca4SAlexey Kardashevskiy static int spapr_dtb_pre_load(void *opaque) 2092fea35ca4SAlexey Kardashevskiy { 2093ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 2094fea35ca4SAlexey Kardashevskiy 2095fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob); 2096fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = NULL; 2097fea35ca4SAlexey Kardashevskiy spapr->fdt_size = 0; 2098fea35ca4SAlexey Kardashevskiy 2099fea35ca4SAlexey Kardashevskiy return 0; 2100fea35ca4SAlexey Kardashevskiy } 2101fea35ca4SAlexey Kardashevskiy 2102fea35ca4SAlexey Kardashevskiy static const VMStateDescription vmstate_spapr_dtb = { 2103fea35ca4SAlexey Kardashevskiy .name = "spapr_dtb", 2104fea35ca4SAlexey Kardashevskiy .version_id = 1, 2105fea35ca4SAlexey Kardashevskiy .minimum_version_id = 1, 2106fea35ca4SAlexey Kardashevskiy .needed = spapr_dtb_needed, 2107fea35ca4SAlexey Kardashevskiy .pre_load = spapr_dtb_pre_load, 2108fea35ca4SAlexey Kardashevskiy .fields = (VMStateField[]) { 2109ce2918cbSDavid Gibson VMSTATE_UINT32(fdt_initial_size, SpaprMachineState), 2110ce2918cbSDavid Gibson VMSTATE_UINT32(fdt_size, SpaprMachineState), 2111ce2918cbSDavid Gibson VMSTATE_VBUFFER_ALLOC_UINT32(fdt_blob, SpaprMachineState, 0, NULL, 2112fea35ca4SAlexey Kardashevskiy fdt_size), 2113fea35ca4SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 2114fea35ca4SAlexey Kardashevskiy }, 2115fea35ca4SAlexey Kardashevskiy }; 2116fea35ca4SAlexey Kardashevskiy 21174be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = { 21184be21d56SDavid Gibson .name = "spapr", 2119880ae7deSDavid Gibson .version_id = 3, 21204be21d56SDavid Gibson .minimum_version_id = 1, 21214e5fe368SSuraj Jitindar Singh .pre_load = spapr_pre_load, 2122880ae7deSDavid Gibson .post_load = spapr_post_load, 21234e5fe368SSuraj Jitindar Singh .pre_save = spapr_pre_save, 21244be21d56SDavid Gibson .fields = (VMStateField[]) { 2125880ae7deSDavid Gibson /* used to be @next_irq */ 2126880ae7deSDavid Gibson VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4), 21274be21d56SDavid Gibson 21284be21d56SDavid Gibson /* RTC offset */ 2129ce2918cbSDavid Gibson VMSTATE_UINT64_TEST(rtc_offset, SpaprMachineState, version_before_3), 2130880ae7deSDavid Gibson 2131ce2918cbSDavid Gibson VMSTATE_PPC_TIMEBASE_V(tb, SpaprMachineState, 2), 21324be21d56SDavid Gibson VMSTATE_END_OF_LIST() 21334be21d56SDavid Gibson }, 213462ef3760SMichael Roth .subsections = (const VMStateDescription*[]) { 213562ef3760SMichael Roth &vmstate_spapr_ov5_cas, 21369861bb3eSSuraj Jitindar Singh &vmstate_spapr_patb_entry, 2137fd38804bSDaniel Henrique Barboza &vmstate_spapr_pending_events, 21384e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_htm, 21394e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_vsx, 21404e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_dfp, 21418f38eaf8SSuraj Jitindar Singh &vmstate_spapr_cap_cfpc, 214209114fd8SSuraj Jitindar Singh &vmstate_spapr_cap_sbbc, 21434be8d4e7SSuraj Jitindar Singh &vmstate_spapr_cap_ibs, 214464d4a534SDavid Gibson &vmstate_spapr_cap_hpt_maxpagesize, 214582cffa2eSCédric Le Goater &vmstate_spapr_irq_map, 2146b9a477b7SSuraj Jitindar Singh &vmstate_spapr_cap_nested_kvm_hv, 2147fea35ca4SAlexey Kardashevskiy &vmstate_spapr_dtb, 2148c982f5cfSSuraj Jitindar Singh &vmstate_spapr_cap_large_decr, 21498ff43ee4SSuraj Jitindar Singh &vmstate_spapr_cap_ccf_assist, 215062ef3760SMichael Roth NULL 215162ef3760SMichael Roth } 21524be21d56SDavid Gibson }; 21534be21d56SDavid Gibson 21544be21d56SDavid Gibson static int htab_save_setup(QEMUFile *f, void *opaque) 21554be21d56SDavid Gibson { 2156ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 21574be21d56SDavid Gibson 21584be21d56SDavid Gibson /* "Iteration" header */ 21593a384297SBharata B Rao if (!spapr->htab_shift) { 21603a384297SBharata B Rao qemu_put_be32(f, -1); 21613a384297SBharata B Rao } else { 21624be21d56SDavid Gibson qemu_put_be32(f, spapr->htab_shift); 21633a384297SBharata B Rao } 21644be21d56SDavid Gibson 2165e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 2166e68cb8b4SAlexey Kardashevskiy spapr->htab_save_index = 0; 2167e68cb8b4SAlexey Kardashevskiy spapr->htab_first_pass = true; 2168e68cb8b4SAlexey Kardashevskiy } else { 21693a384297SBharata B Rao if (spapr->htab_shift) { 2170e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 21714be21d56SDavid Gibson } 21723a384297SBharata B Rao } 21734be21d56SDavid Gibson 2174e68cb8b4SAlexey Kardashevskiy 2175e68cb8b4SAlexey Kardashevskiy return 0; 2176e68cb8b4SAlexey Kardashevskiy } 21774be21d56SDavid Gibson 2178ce2918cbSDavid Gibson static void htab_save_chunk(QEMUFile *f, SpaprMachineState *spapr, 2179332f7721SGreg Kurz int chunkstart, int n_valid, int n_invalid) 2180332f7721SGreg Kurz { 2181332f7721SGreg Kurz qemu_put_be32(f, chunkstart); 2182332f7721SGreg Kurz qemu_put_be16(f, n_valid); 2183332f7721SGreg Kurz qemu_put_be16(f, n_invalid); 2184332f7721SGreg Kurz qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 2185332f7721SGreg Kurz HASH_PTE_SIZE_64 * n_valid); 2186332f7721SGreg Kurz } 2187332f7721SGreg Kurz 2188332f7721SGreg Kurz static void htab_save_end_marker(QEMUFile *f) 2189332f7721SGreg Kurz { 2190332f7721SGreg Kurz qemu_put_be32(f, 0); 2191332f7721SGreg Kurz qemu_put_be16(f, 0); 2192332f7721SGreg Kurz qemu_put_be16(f, 0); 2193332f7721SGreg Kurz } 2194332f7721SGreg Kurz 2195ce2918cbSDavid Gibson static void htab_save_first_pass(QEMUFile *f, SpaprMachineState *spapr, 21964be21d56SDavid Gibson int64_t max_ns) 21974be21d56SDavid Gibson { 2198378bc217SDavid Gibson bool has_timeout = max_ns != -1; 21994be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 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; 22074be21d56SDavid Gibson 22084be21d56SDavid Gibson /* Consume invalid HPTEs */ 22094be21d56SDavid Gibson while ((index < htabslots) 22104be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 22114be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 221224ec2863SMarc-André Lureau index++; 22134be21d56SDavid Gibson } 22144be21d56SDavid Gibson 22154be21d56SDavid Gibson /* Consume valid HPTEs */ 22164be21d56SDavid Gibson chunkstart = index; 2217338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 22184be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 22194be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 222024ec2863SMarc-André Lureau index++; 22214be21d56SDavid Gibson } 22224be21d56SDavid Gibson 22234be21d56SDavid Gibson if (index > chunkstart) { 22244be21d56SDavid Gibson int n_valid = index - chunkstart; 22254be21d56SDavid Gibson 2226332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, 0); 22274be21d56SDavid Gibson 2228378bc217SDavid Gibson if (has_timeout && 2229378bc217SDavid Gibson (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 22304be21d56SDavid Gibson break; 22314be21d56SDavid Gibson } 22324be21d56SDavid Gibson } 22334be21d56SDavid Gibson } while ((index < htabslots) && !qemu_file_rate_limit(f)); 22344be21d56SDavid Gibson 22354be21d56SDavid Gibson if (index >= htabslots) { 22364be21d56SDavid Gibson assert(index == htabslots); 22374be21d56SDavid Gibson index = 0; 22384be21d56SDavid Gibson spapr->htab_first_pass = false; 22394be21d56SDavid Gibson } 22404be21d56SDavid Gibson spapr->htab_save_index = index; 22414be21d56SDavid Gibson } 22424be21d56SDavid Gibson 2243ce2918cbSDavid Gibson static int htab_save_later_pass(QEMUFile *f, SpaprMachineState *spapr, 22444be21d56SDavid Gibson int64_t max_ns) 22454be21d56SDavid Gibson { 22464be21d56SDavid Gibson bool final = max_ns < 0; 22474be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 22484be21d56SDavid Gibson int examined = 0, sent = 0; 22494be21d56SDavid Gibson int index = spapr->htab_save_index; 2250bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 22514be21d56SDavid Gibson 22524be21d56SDavid Gibson assert(!spapr->htab_first_pass); 22534be21d56SDavid Gibson 22544be21d56SDavid Gibson do { 22554be21d56SDavid Gibson int chunkstart, invalidstart; 22564be21d56SDavid Gibson 22574be21d56SDavid Gibson /* Consume non-dirty HPTEs */ 22584be21d56SDavid Gibson while ((index < htabslots) 22594be21d56SDavid Gibson && !HPTE_DIRTY(HPTE(spapr->htab, index))) { 22604be21d56SDavid Gibson index++; 22614be21d56SDavid Gibson examined++; 22624be21d56SDavid Gibson } 22634be21d56SDavid Gibson 22644be21d56SDavid Gibson chunkstart = index; 22654be21d56SDavid Gibson /* Consume valid dirty HPTEs */ 2266338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 22674be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 22684be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 22694be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 22704be21d56SDavid Gibson index++; 22714be21d56SDavid Gibson examined++; 22724be21d56SDavid Gibson } 22734be21d56SDavid Gibson 22744be21d56SDavid Gibson invalidstart = index; 22754be21d56SDavid Gibson /* Consume invalid dirty HPTEs */ 2276338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - invalidstart < USHRT_MAX) 22774be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 22784be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 22794be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 22804be21d56SDavid Gibson index++; 22814be21d56SDavid Gibson examined++; 22824be21d56SDavid Gibson } 22834be21d56SDavid Gibson 22844be21d56SDavid Gibson if (index > chunkstart) { 22854be21d56SDavid Gibson int n_valid = invalidstart - chunkstart; 22864be21d56SDavid Gibson int n_invalid = index - invalidstart; 22874be21d56SDavid Gibson 2288332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, n_invalid); 22894be21d56SDavid Gibson sent += index - chunkstart; 22904be21d56SDavid Gibson 2291bc72ad67SAlex Bligh if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 22924be21d56SDavid Gibson break; 22934be21d56SDavid Gibson } 22944be21d56SDavid Gibson } 22954be21d56SDavid Gibson 22964be21d56SDavid Gibson if (examined >= htabslots) { 22974be21d56SDavid Gibson break; 22984be21d56SDavid Gibson } 22994be21d56SDavid Gibson 23004be21d56SDavid Gibson if (index >= htabslots) { 23014be21d56SDavid Gibson assert(index == htabslots); 23024be21d56SDavid Gibson index = 0; 23034be21d56SDavid Gibson } 23044be21d56SDavid Gibson } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final)); 23054be21d56SDavid Gibson 23064be21d56SDavid Gibson if (index >= htabslots) { 23074be21d56SDavid Gibson assert(index == htabslots); 23084be21d56SDavid Gibson index = 0; 23094be21d56SDavid Gibson } 23104be21d56SDavid Gibson 23114be21d56SDavid Gibson spapr->htab_save_index = index; 23124be21d56SDavid Gibson 2313e68cb8b4SAlexey Kardashevskiy return (examined >= htabslots) && (sent == 0) ? 1 : 0; 23144be21d56SDavid Gibson } 23154be21d56SDavid Gibson 2316e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS 5000000 /* 5 ms */ 2317e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE 2048 2318e68cb8b4SAlexey Kardashevskiy 23194be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque) 23204be21d56SDavid Gibson { 2321ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2322715c5407SDavid Gibson int fd; 2323e68cb8b4SAlexey Kardashevskiy int rc = 0; 23244be21d56SDavid Gibson 23254be21d56SDavid Gibson /* Iteration header */ 23263a384297SBharata B Rao if (!spapr->htab_shift) { 23273a384297SBharata B Rao qemu_put_be32(f, -1); 2328e8cd4247SLaurent Vivier return 1; 23293a384297SBharata B Rao } else { 23304be21d56SDavid Gibson qemu_put_be32(f, 0); 23313a384297SBharata B Rao } 23324be21d56SDavid Gibson 2333e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2334e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2335e68cb8b4SAlexey Kardashevskiy 2336715c5407SDavid Gibson fd = get_htab_fd(spapr); 2337715c5407SDavid Gibson if (fd < 0) { 2338715c5407SDavid Gibson return fd; 233901a57972SSamuel Mendoza-Jonas } 234001a57972SSamuel Mendoza-Jonas 2341715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); 2342e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2343e68cb8b4SAlexey Kardashevskiy return rc; 2344e68cb8b4SAlexey Kardashevskiy } 2345e68cb8b4SAlexey Kardashevskiy } else if (spapr->htab_first_pass) { 23464be21d56SDavid Gibson htab_save_first_pass(f, spapr, MAX_ITERATION_NS); 23474be21d56SDavid Gibson } else { 2348e68cb8b4SAlexey Kardashevskiy rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS); 23494be21d56SDavid Gibson } 23504be21d56SDavid Gibson 2351332f7721SGreg Kurz htab_save_end_marker(f); 23524be21d56SDavid Gibson 2353e68cb8b4SAlexey Kardashevskiy return rc; 23544be21d56SDavid Gibson } 23554be21d56SDavid Gibson 23564be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque) 23574be21d56SDavid Gibson { 2358ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2359715c5407SDavid Gibson int fd; 23604be21d56SDavid Gibson 23614be21d56SDavid Gibson /* Iteration header */ 23623a384297SBharata B Rao if (!spapr->htab_shift) { 23633a384297SBharata B Rao qemu_put_be32(f, -1); 23643a384297SBharata B Rao return 0; 23653a384297SBharata B Rao } else { 23664be21d56SDavid Gibson qemu_put_be32(f, 0); 23673a384297SBharata B Rao } 23684be21d56SDavid Gibson 2369e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2370e68cb8b4SAlexey Kardashevskiy int rc; 2371e68cb8b4SAlexey Kardashevskiy 2372e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2373e68cb8b4SAlexey Kardashevskiy 2374715c5407SDavid Gibson fd = get_htab_fd(spapr); 2375715c5407SDavid Gibson if (fd < 0) { 2376715c5407SDavid Gibson return fd; 237701a57972SSamuel Mendoza-Jonas } 237801a57972SSamuel Mendoza-Jonas 2379715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1); 2380e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2381e68cb8b4SAlexey Kardashevskiy return rc; 2382e68cb8b4SAlexey Kardashevskiy } 2383e68cb8b4SAlexey Kardashevskiy } else { 2384378bc217SDavid Gibson if (spapr->htab_first_pass) { 2385378bc217SDavid Gibson htab_save_first_pass(f, spapr, -1); 2386378bc217SDavid Gibson } 23874be21d56SDavid Gibson htab_save_later_pass(f, spapr, -1); 2388e68cb8b4SAlexey Kardashevskiy } 23894be21d56SDavid Gibson 23904be21d56SDavid Gibson /* End marker */ 2391332f7721SGreg Kurz htab_save_end_marker(f); 23924be21d56SDavid Gibson 23934be21d56SDavid Gibson return 0; 23944be21d56SDavid Gibson } 23954be21d56SDavid Gibson 23964be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id) 23974be21d56SDavid Gibson { 2398ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 23994be21d56SDavid Gibson uint32_t section_hdr; 2400e68cb8b4SAlexey Kardashevskiy int fd = -1; 240114b0d748SGreg Kurz Error *local_err = NULL; 24024be21d56SDavid Gibson 24034be21d56SDavid Gibson if (version_id < 1 || version_id > 1) { 240498a5d100SDavid Gibson error_report("htab_load() bad version"); 24054be21d56SDavid Gibson return -EINVAL; 24064be21d56SDavid Gibson } 24074be21d56SDavid Gibson 24084be21d56SDavid Gibson section_hdr = qemu_get_be32(f); 24094be21d56SDavid Gibson 24103a384297SBharata B Rao if (section_hdr == -1) { 24113a384297SBharata B Rao spapr_free_hpt(spapr); 24123a384297SBharata B Rao return 0; 24133a384297SBharata B Rao } 24143a384297SBharata B Rao 24154be21d56SDavid Gibson if (section_hdr) { 2416c5f54f3eSDavid Gibson /* First section gives the htab size */ 2417c5f54f3eSDavid Gibson spapr_reallocate_hpt(spapr, section_hdr, &local_err); 2418c5f54f3eSDavid Gibson if (local_err) { 2419c5f54f3eSDavid Gibson error_report_err(local_err); 24204be21d56SDavid Gibson return -EINVAL; 24214be21d56SDavid Gibson } 24224be21d56SDavid Gibson return 0; 24234be21d56SDavid Gibson } 24244be21d56SDavid Gibson 2425e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2426e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2427e68cb8b4SAlexey Kardashevskiy 242814b0d748SGreg Kurz fd = kvmppc_get_htab_fd(true, 0, &local_err); 2429e68cb8b4SAlexey Kardashevskiy if (fd < 0) { 243014b0d748SGreg Kurz error_report_err(local_err); 243182be8e73SGreg Kurz return fd; 2432e68cb8b4SAlexey Kardashevskiy } 2433e68cb8b4SAlexey Kardashevskiy } 2434e68cb8b4SAlexey Kardashevskiy 24354be21d56SDavid Gibson while (true) { 24364be21d56SDavid Gibson uint32_t index; 24374be21d56SDavid Gibson uint16_t n_valid, n_invalid; 24384be21d56SDavid Gibson 24394be21d56SDavid Gibson index = qemu_get_be32(f); 24404be21d56SDavid Gibson n_valid = qemu_get_be16(f); 24414be21d56SDavid Gibson n_invalid = qemu_get_be16(f); 24424be21d56SDavid Gibson 24434be21d56SDavid Gibson if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) { 24444be21d56SDavid Gibson /* End of Stream */ 24454be21d56SDavid Gibson break; 24464be21d56SDavid Gibson } 24474be21d56SDavid Gibson 2448e68cb8b4SAlexey Kardashevskiy if ((index + n_valid + n_invalid) > 24494be21d56SDavid Gibson (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) { 24504be21d56SDavid Gibson /* Bad index in stream */ 245198a5d100SDavid Gibson error_report( 245298a5d100SDavid Gibson "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)", 245398a5d100SDavid Gibson index, n_valid, n_invalid, spapr->htab_shift); 24544be21d56SDavid Gibson return -EINVAL; 24554be21d56SDavid Gibson } 24564be21d56SDavid Gibson 2457e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 24584be21d56SDavid Gibson if (n_valid) { 24594be21d56SDavid Gibson qemu_get_buffer(f, HPTE(spapr->htab, index), 24604be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 24614be21d56SDavid Gibson } 24624be21d56SDavid Gibson if (n_invalid) { 24634be21d56SDavid Gibson memset(HPTE(spapr->htab, index + n_valid), 0, 24644be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_invalid); 24654be21d56SDavid Gibson } 2466e68cb8b4SAlexey Kardashevskiy } else { 2467e68cb8b4SAlexey Kardashevskiy int rc; 2468e68cb8b4SAlexey Kardashevskiy 2469e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2470e68cb8b4SAlexey Kardashevskiy 2471e68cb8b4SAlexey Kardashevskiy rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid); 2472e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2473e68cb8b4SAlexey Kardashevskiy return rc; 2474e68cb8b4SAlexey Kardashevskiy } 2475e68cb8b4SAlexey Kardashevskiy } 2476e68cb8b4SAlexey Kardashevskiy } 2477e68cb8b4SAlexey Kardashevskiy 2478e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2479e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2480e68cb8b4SAlexey Kardashevskiy close(fd); 24814be21d56SDavid Gibson } 24824be21d56SDavid Gibson 24834be21d56SDavid Gibson return 0; 24844be21d56SDavid Gibson } 24854be21d56SDavid Gibson 248670f794fcSJuan Quintela static void htab_save_cleanup(void *opaque) 2487c573fc03SThomas Huth { 2488ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2489c573fc03SThomas Huth 2490c573fc03SThomas Huth close_htab_fd(spapr); 2491c573fc03SThomas Huth } 2492c573fc03SThomas Huth 24934be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = { 24949907e842SJuan Quintela .save_setup = htab_save_setup, 24954be21d56SDavid Gibson .save_live_iterate = htab_save_iterate, 2496a3e06c3dSDr. David Alan Gilbert .save_live_complete_precopy = htab_save_complete, 249770f794fcSJuan Quintela .save_cleanup = htab_save_cleanup, 24984be21d56SDavid Gibson .load_state = htab_load, 24994be21d56SDavid Gibson }; 25004be21d56SDavid Gibson 25015b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device, 25025b2128d2SAlexander Graf Error **errp) 25035b2128d2SAlexander Graf { 2504c86c1affSDaniel Henrique Barboza MachineState *machine = MACHINE(opaque); 25055b2128d2SAlexander Graf machine->boot_order = g_strdup(boot_device); 25065b2128d2SAlexander Graf } 25075b2128d2SAlexander Graf 2508ce2918cbSDavid Gibson static void spapr_create_lmb_dr_connectors(SpaprMachineState *spapr) 2509224245bfSDavid Gibson { 2510224245bfSDavid Gibson MachineState *machine = MACHINE(spapr); 2511224245bfSDavid Gibson uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 2512e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 2513224245bfSDavid Gibson int i; 2514224245bfSDavid Gibson 2515224245bfSDavid Gibson for (i = 0; i < nr_lmbs; i++) { 2516224245bfSDavid Gibson uint64_t addr; 2517224245bfSDavid Gibson 2518b0c14ec4SDavid Hildenbrand addr = i * lmb_size + machine->device_memory->base; 25196caf3ac6SDavid Gibson spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_LMB, 2520224245bfSDavid Gibson addr / lmb_size); 2521224245bfSDavid Gibson } 2522224245bfSDavid Gibson } 2523224245bfSDavid Gibson 2524224245bfSDavid Gibson /* 2525224245bfSDavid Gibson * If RAM size, maxmem size and individual node mem sizes aren't aligned 2526224245bfSDavid Gibson * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest 2527224245bfSDavid Gibson * since we can't support such unaligned sizes with DRCONF_MEMORY. 2528224245bfSDavid Gibson */ 25297c150d6fSDavid Gibson static void spapr_validate_node_memory(MachineState *machine, Error **errp) 2530224245bfSDavid Gibson { 2531224245bfSDavid Gibson int i; 2532224245bfSDavid Gibson 25337c150d6fSDavid Gibson if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) { 25347c150d6fSDavid Gibson error_setg(errp, "Memory size 0x" RAM_ADDR_FMT 2535ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 25367c150d6fSDavid Gibson machine->ram_size, 2537d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 25387c150d6fSDavid Gibson return; 25397c150d6fSDavid Gibson } 25407c150d6fSDavid Gibson 25417c150d6fSDavid Gibson if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) { 25427c150d6fSDavid Gibson error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT 2543ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 25447c150d6fSDavid Gibson machine->ram_size, 2545d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 25467c150d6fSDavid Gibson return; 2547224245bfSDavid Gibson } 2548224245bfSDavid Gibson 2549aa570207STao Xu for (i = 0; i < machine->numa_state->num_nodes; i++) { 25507e721e7bSTao Xu if (machine->numa_state->nodes[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) { 25517c150d6fSDavid Gibson error_setg(errp, 25527c150d6fSDavid Gibson "Node %d memory size 0x%" PRIx64 2553ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 25547e721e7bSTao Xu i, machine->numa_state->nodes[i].node_mem, 2555d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 25567c150d6fSDavid Gibson return; 2557224245bfSDavid Gibson } 2558224245bfSDavid Gibson } 2559224245bfSDavid Gibson } 2560224245bfSDavid Gibson 2561535455fdSIgor Mammedov /* find cpu slot in machine->possible_cpus by core_id */ 2562535455fdSIgor Mammedov static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx) 2563535455fdSIgor Mammedov { 2564fe6b6346SLike Xu int index = id / ms->smp.threads; 2565535455fdSIgor Mammedov 2566535455fdSIgor Mammedov if (index >= ms->possible_cpus->len) { 2567535455fdSIgor Mammedov return NULL; 2568535455fdSIgor Mammedov } 2569535455fdSIgor Mammedov if (idx) { 2570535455fdSIgor Mammedov *idx = index; 2571535455fdSIgor Mammedov } 2572535455fdSIgor Mammedov return &ms->possible_cpus->cpus[index]; 2573535455fdSIgor Mammedov } 2574535455fdSIgor Mammedov 2575ce2918cbSDavid Gibson static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp) 2576fa98fbfcSSam Bobroff { 2577fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 2578fa98fbfcSSam Bobroff Error *local_err = NULL; 2579fa98fbfcSSam Bobroff bool vsmt_user = !!spapr->vsmt; 2580fa98fbfcSSam Bobroff int kvm_smt = kvmppc_smt_threads(); 2581fa98fbfcSSam Bobroff int ret; 2582fe6b6346SLike Xu unsigned int smp_threads = ms->smp.threads; 2583fa98fbfcSSam Bobroff 2584fa98fbfcSSam Bobroff if (!kvm_enabled() && (smp_threads > 1)) { 2585fa98fbfcSSam Bobroff error_setg(&local_err, "TCG cannot support more than 1 thread/core " 2586fa98fbfcSSam Bobroff "on a pseries machine"); 2587fa98fbfcSSam Bobroff goto out; 2588fa98fbfcSSam Bobroff } 2589fa98fbfcSSam Bobroff if (!is_power_of_2(smp_threads)) { 2590fa98fbfcSSam Bobroff error_setg(&local_err, "Cannot support %d threads/core on a pseries " 2591fa98fbfcSSam Bobroff "machine because it must be a power of 2", smp_threads); 2592fa98fbfcSSam Bobroff goto out; 2593fa98fbfcSSam Bobroff } 2594fa98fbfcSSam Bobroff 2595fa98fbfcSSam Bobroff /* Detemine the VSMT mode to use: */ 2596fa98fbfcSSam Bobroff if (vsmt_user) { 2597fa98fbfcSSam Bobroff if (spapr->vsmt < smp_threads) { 2598fa98fbfcSSam Bobroff error_setg(&local_err, "Cannot support VSMT mode %d" 2599fa98fbfcSSam Bobroff " because it must be >= threads/core (%d)", 2600fa98fbfcSSam Bobroff spapr->vsmt, smp_threads); 2601fa98fbfcSSam Bobroff goto out; 2602fa98fbfcSSam Bobroff } 2603fa98fbfcSSam Bobroff /* In this case, spapr->vsmt has been set by the command line */ 2604fa98fbfcSSam Bobroff } else { 26058904e5a7SDavid Gibson /* 26068904e5a7SDavid Gibson * Default VSMT value is tricky, because we need it to be as 26078904e5a7SDavid Gibson * consistent as possible (for migration), but this requires 26088904e5a7SDavid Gibson * changing it for at least some existing cases. We pick 8 as 26098904e5a7SDavid Gibson * the value that we'd get with KVM on POWER8, the 26108904e5a7SDavid Gibson * overwhelmingly common case in production systems. 26118904e5a7SDavid Gibson */ 26124ad64cbdSLaurent Vivier spapr->vsmt = MAX(8, smp_threads); 2613fa98fbfcSSam Bobroff } 2614fa98fbfcSSam Bobroff 2615fa98fbfcSSam Bobroff /* KVM: If necessary, set the SMT mode: */ 2616fa98fbfcSSam Bobroff if (kvm_enabled() && (spapr->vsmt != kvm_smt)) { 2617fa98fbfcSSam Bobroff ret = kvmppc_set_smt_threads(spapr->vsmt); 2618fa98fbfcSSam Bobroff if (ret) { 26191f20f2e0SDavid Gibson /* Looks like KVM isn't able to change VSMT mode */ 2620fa98fbfcSSam Bobroff error_setg(&local_err, 2621fa98fbfcSSam Bobroff "Failed to set KVM's VSMT mode to %d (errno %d)", 2622fa98fbfcSSam Bobroff spapr->vsmt, ret); 26231f20f2e0SDavid Gibson /* We can live with that if the default one is big enough 26241f20f2e0SDavid Gibson * for the number of threads, and a submultiple of the one 26251f20f2e0SDavid Gibson * we want. In this case we'll waste some vcpu ids, but 26261f20f2e0SDavid Gibson * behaviour will be correct */ 26271f20f2e0SDavid Gibson if ((kvm_smt >= smp_threads) && ((spapr->vsmt % kvm_smt) == 0)) { 26281f20f2e0SDavid Gibson warn_report_err(local_err); 26291f20f2e0SDavid Gibson local_err = NULL; 26301f20f2e0SDavid Gibson goto out; 26311f20f2e0SDavid Gibson } else { 2632fa98fbfcSSam Bobroff if (!vsmt_user) { 26331f20f2e0SDavid Gibson error_append_hint(&local_err, 26341f20f2e0SDavid Gibson "On PPC, a VM with %d threads/core" 26351f20f2e0SDavid Gibson " on a host with %d threads/core" 26361f20f2e0SDavid Gibson " requires the use of VSMT mode %d.\n", 2637fa98fbfcSSam Bobroff smp_threads, kvm_smt, spapr->vsmt); 2638fa98fbfcSSam Bobroff } 2639fa98fbfcSSam Bobroff kvmppc_hint_smt_possible(&local_err); 2640fa98fbfcSSam Bobroff goto out; 2641fa98fbfcSSam Bobroff } 2642fa98fbfcSSam Bobroff } 26431f20f2e0SDavid Gibson } 2644fa98fbfcSSam Bobroff /* else TCG: nothing to do currently */ 2645fa98fbfcSSam Bobroff out: 2646fa98fbfcSSam Bobroff error_propagate(errp, local_err); 2647fa98fbfcSSam Bobroff } 2648fa98fbfcSSam Bobroff 2649ce2918cbSDavid Gibson static void spapr_init_cpus(SpaprMachineState *spapr) 26501a5008fcSGreg Kurz { 26511a5008fcSGreg Kurz MachineState *machine = MACHINE(spapr); 26521a5008fcSGreg Kurz MachineClass *mc = MACHINE_GET_CLASS(machine); 2653ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 26541a5008fcSGreg Kurz const char *type = spapr_get_cpu_core_type(machine->cpu_type); 26551a5008fcSGreg Kurz const CPUArchIdList *possible_cpus; 2656fe6b6346SLike Xu unsigned int smp_cpus = machine->smp.cpus; 2657fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 2658fe6b6346SLike Xu unsigned int max_cpus = machine->smp.max_cpus; 26591a5008fcSGreg Kurz int boot_cores_nr = smp_cpus / smp_threads; 26601a5008fcSGreg Kurz int i; 26611a5008fcSGreg Kurz 26621a5008fcSGreg Kurz possible_cpus = mc->possible_cpu_arch_ids(machine); 26631a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 26641a5008fcSGreg Kurz if (smp_cpus % smp_threads) { 26651a5008fcSGreg Kurz error_report("smp_cpus (%u) must be multiple of threads (%u)", 26661a5008fcSGreg Kurz smp_cpus, smp_threads); 26671a5008fcSGreg Kurz exit(1); 26681a5008fcSGreg Kurz } 26691a5008fcSGreg Kurz if (max_cpus % smp_threads) { 26701a5008fcSGreg Kurz error_report("max_cpus (%u) must be multiple of threads (%u)", 26711a5008fcSGreg Kurz max_cpus, smp_threads); 26721a5008fcSGreg Kurz exit(1); 26731a5008fcSGreg Kurz } 26741a5008fcSGreg Kurz } else { 26751a5008fcSGreg Kurz if (max_cpus != smp_cpus) { 26761a5008fcSGreg Kurz error_report("This machine version does not support CPU hotplug"); 26771a5008fcSGreg Kurz exit(1); 26781a5008fcSGreg Kurz } 26791a5008fcSGreg Kurz boot_cores_nr = possible_cpus->len; 26801a5008fcSGreg Kurz } 26811a5008fcSGreg Kurz 26821a5008fcSGreg Kurz if (smc->pre_2_10_has_unused_icps) { 26831a5008fcSGreg Kurz int i; 26841a5008fcSGreg Kurz 26851a518e76SCédric Le Goater for (i = 0; i < spapr_max_server_number(spapr); i++) { 26861a5008fcSGreg Kurz /* Dummy entries get deregistered when real ICPState objects 26871a5008fcSGreg Kurz * are registered during CPU core hotplug. 26881a5008fcSGreg Kurz */ 26891a5008fcSGreg Kurz pre_2_10_vmstate_register_dummy_icp(i); 26901a5008fcSGreg Kurz } 26911a5008fcSGreg Kurz } 26921a5008fcSGreg Kurz 26931a5008fcSGreg Kurz for (i = 0; i < possible_cpus->len; i++) { 26941a5008fcSGreg Kurz int core_id = i * smp_threads; 26951a5008fcSGreg Kurz 26961a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 26971a5008fcSGreg Kurz spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU, 26981a5008fcSGreg Kurz spapr_vcpu_id(spapr, core_id)); 26991a5008fcSGreg Kurz } 27001a5008fcSGreg Kurz 27011a5008fcSGreg Kurz if (i < boot_cores_nr) { 27021a5008fcSGreg Kurz Object *core = object_new(type); 27031a5008fcSGreg Kurz int nr_threads = smp_threads; 27041a5008fcSGreg Kurz 27051a5008fcSGreg Kurz /* Handle the partially filled core for older machine types */ 27061a5008fcSGreg Kurz if ((i + 1) * smp_threads >= smp_cpus) { 27071a5008fcSGreg Kurz nr_threads = smp_cpus - i * smp_threads; 27081a5008fcSGreg Kurz } 27091a5008fcSGreg Kurz 27101a5008fcSGreg Kurz object_property_set_int(core, nr_threads, "nr-threads", 27111a5008fcSGreg Kurz &error_fatal); 27121a5008fcSGreg Kurz object_property_set_int(core, core_id, CPU_CORE_PROP_CORE_ID, 27131a5008fcSGreg Kurz &error_fatal); 27141a5008fcSGreg Kurz object_property_set_bool(core, true, "realized", &error_fatal); 2715ecda255eSSam Bobroff 2716ecda255eSSam Bobroff object_unref(core); 27171a5008fcSGreg Kurz } 27181a5008fcSGreg Kurz } 27191a5008fcSGreg Kurz } 27201a5008fcSGreg Kurz 2721999c9cafSGreg Kurz static PCIHostState *spapr_create_default_phb(void) 2722999c9cafSGreg Kurz { 2723999c9cafSGreg Kurz DeviceState *dev; 2724999c9cafSGreg Kurz 2725999c9cafSGreg Kurz dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE); 2726999c9cafSGreg Kurz qdev_prop_set_uint32(dev, "index", 0); 2727999c9cafSGreg Kurz qdev_init_nofail(dev); 2728999c9cafSGreg Kurz 2729999c9cafSGreg Kurz return PCI_HOST_BRIDGE(dev); 2730999c9cafSGreg Kurz } 2731999c9cafSGreg Kurz 273253018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */ 2733bcb5ce08SDavid Gibson static void spapr_machine_init(MachineState *machine) 273453018216SPaolo Bonzini { 2735ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(machine); 2736ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 27373ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 27383ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 273953018216SPaolo Bonzini PCIHostState *phb; 274053018216SPaolo Bonzini int i; 274153018216SPaolo Bonzini MemoryRegion *sysmem = get_system_memory(); 274253018216SPaolo Bonzini MemoryRegion *ram = g_new(MemoryRegion, 1); 2743c86c1affSDaniel Henrique Barboza hwaddr node0_size = spapr_node0_size(machine); 2744b7d1f77aSBenjamin Herrenschmidt long load_limit, fw_size; 274553018216SPaolo Bonzini char *filename; 274630f4b05bSDavid Gibson Error *resize_hpt_err = NULL; 274753018216SPaolo Bonzini 2748226419d6SMichael S. Tsirkin msi_nonbroken = true; 274953018216SPaolo Bonzini 275053018216SPaolo Bonzini QLIST_INIT(&spapr->phbs); 27510cffce56SDavid Gibson QTAILQ_INIT(&spapr->pending_dimm_unplugs); 275253018216SPaolo Bonzini 27539f6edd06SDavid Gibson /* Determine capabilities to run with */ 27549f6edd06SDavid Gibson spapr_caps_init(spapr); 27559f6edd06SDavid Gibson 275630f4b05bSDavid Gibson kvmppc_check_papr_resize_hpt(&resize_hpt_err); 275730f4b05bSDavid Gibson if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) { 275830f4b05bSDavid Gibson /* 275930f4b05bSDavid Gibson * If the user explicitly requested a mode we should either 276030f4b05bSDavid Gibson * supply it, or fail completely (which we do below). But if 276130f4b05bSDavid Gibson * it's not set explicitly, we reset our mode to something 276230f4b05bSDavid Gibson * that works 276330f4b05bSDavid Gibson */ 276430f4b05bSDavid Gibson if (resize_hpt_err) { 276530f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 276630f4b05bSDavid Gibson error_free(resize_hpt_err); 276730f4b05bSDavid Gibson resize_hpt_err = NULL; 276830f4b05bSDavid Gibson } else { 276930f4b05bSDavid Gibson spapr->resize_hpt = smc->resize_hpt_default; 277030f4b05bSDavid Gibson } 277130f4b05bSDavid Gibson } 277230f4b05bSDavid Gibson 277330f4b05bSDavid Gibson assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT); 277430f4b05bSDavid Gibson 277530f4b05bSDavid Gibson if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && resize_hpt_err) { 277630f4b05bSDavid Gibson /* 277730f4b05bSDavid Gibson * User requested HPT resize, but this host can't supply it. Bail out 277830f4b05bSDavid Gibson */ 277930f4b05bSDavid Gibson error_report_err(resize_hpt_err); 278030f4b05bSDavid Gibson exit(1); 278130f4b05bSDavid Gibson } 278230f4b05bSDavid Gibson 2783c4177479SAlexey Kardashevskiy spapr->rma_size = node0_size; 278453018216SPaolo Bonzini 278553018216SPaolo Bonzini /* With KVM, we don't actually know whether KVM supports an 278653018216SPaolo Bonzini * unbounded RMA (PR KVM) or is limited by the hash table size 278753018216SPaolo Bonzini * (HV KVM using VRMA), so we always assume the latter 278853018216SPaolo Bonzini * 278953018216SPaolo Bonzini * In that case, we also limit the initial allocations for RTAS 279053018216SPaolo Bonzini * etc... to 256M since we have no way to know what the VRMA size 279153018216SPaolo Bonzini * is going to be as it depends on the size of the hash table 2792090052aaSDavid Gibson * which isn't determined yet. 279353018216SPaolo Bonzini */ 279453018216SPaolo Bonzini if (kvm_enabled()) { 279553018216SPaolo Bonzini spapr->vrma_adjust = 1; 279653018216SPaolo Bonzini spapr->rma_size = MIN(spapr->rma_size, 0x10000000); 279753018216SPaolo Bonzini } 2798912acdf4SBenjamin Herrenschmidt 2799090052aaSDavid Gibson /* Actually we don't support unbounded RMA anymore since we added 2800090052aaSDavid Gibson * proper emulation of HV mode. The max we can get is 16G which 2801090052aaSDavid Gibson * also happens to be what we configure for PAPR mode so make sure 2802090052aaSDavid Gibson * we don't do anything bigger than that 2803912acdf4SBenjamin Herrenschmidt */ 2804912acdf4SBenjamin Herrenschmidt spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull); 280553018216SPaolo Bonzini 2806c4177479SAlexey Kardashevskiy if (spapr->rma_size > node0_size) { 2807d54e4d76SDavid Gibson error_report("Numa node 0 has to span the RMA (%#08"HWADDR_PRIx")", 2808c4177479SAlexey Kardashevskiy spapr->rma_size); 2809c4177479SAlexey Kardashevskiy exit(1); 2810c4177479SAlexey Kardashevskiy } 2811c4177479SAlexey Kardashevskiy 2812b7d1f77aSBenjamin Herrenschmidt /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */ 2813b7d1f77aSBenjamin Herrenschmidt load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; 281453018216SPaolo Bonzini 2815482969d6SCédric Le Goater /* 2816482969d6SCédric Le Goater * VSMT must be set in order to be able to compute VCPU ids, ie to 28171a518e76SCédric Le Goater * call spapr_max_server_number() or spapr_vcpu_id(). 2818482969d6SCédric Le Goater */ 2819482969d6SCédric Le Goater spapr_set_vsmt_mode(spapr, &error_fatal); 2820482969d6SCédric Le Goater 28217b565160SDavid Gibson /* Set up Interrupt Controller before we create the VCPUs */ 2822fab397d8SCédric Le Goater spapr_irq_init(spapr, &error_fatal); 28237b565160SDavid Gibson 2824dc1b5eeeSGreg Kurz /* Set up containers for ibm,client-architecture-support negotiated options 2825dc1b5eeeSGreg Kurz */ 2826facdb8b6SMichael Roth spapr->ov5 = spapr_ovec_new(); 2827facdb8b6SMichael Roth spapr->ov5_cas = spapr_ovec_new(); 2828facdb8b6SMichael Roth 2829224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2830facdb8b6SMichael Roth spapr_ovec_set(spapr->ov5, OV5_DRCONF_MEMORY); 28317c150d6fSDavid Gibson spapr_validate_node_memory(machine, &error_fatal); 2832224245bfSDavid Gibson } 2833224245bfSDavid Gibson 2834417ece33SMichael Roth spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY); 2835417ece33SMichael Roth 2836ffbb1705SMichael Roth /* advertise support for dedicated HP event source to guests */ 2837ffbb1705SMichael Roth if (spapr->use_hotplug_event_source) { 2838ffbb1705SMichael Roth spapr_ovec_set(spapr->ov5, OV5_HP_EVT); 2839ffbb1705SMichael Roth } 2840ffbb1705SMichael Roth 28412772cf6bSDavid Gibson /* advertise support for HPT resizing */ 28422772cf6bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { 28432772cf6bSDavid Gibson spapr_ovec_set(spapr->ov5, OV5_HPT_RESIZE); 28442772cf6bSDavid Gibson } 28452772cf6bSDavid Gibson 2846a324d6f1SBharata B Rao /* advertise support for ibm,dyamic-memory-v2 */ 2847a324d6f1SBharata B Rao spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2); 2848a324d6f1SBharata B Rao 2849db592b5bSCédric Le Goater /* advertise XIVE on POWER9 machines */ 285013db0cd9SCédric Le Goater if (spapr->irq->ov5 & (SPAPR_OV5_XIVE_EXPLOIT | SPAPR_OV5_XIVE_BOTH)) { 2851db592b5bSCédric Le Goater spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT); 2852db592b5bSCédric Le Goater } 2853db592b5bSCédric Le Goater 285453018216SPaolo Bonzini /* init CPUs */ 28550c86d0fdSDavid Gibson spapr_init_cpus(spapr); 285653018216SPaolo Bonzini 2857*58c46efaSLaurent Vivier /* 2858*58c46efaSLaurent Vivier * check we don't have a memory-less/cpu-less NUMA node 2859*58c46efaSLaurent Vivier * Firmware relies on the existing memory/cpu topology to provide the 2860*58c46efaSLaurent Vivier * NUMA topology to the kernel. 2861*58c46efaSLaurent Vivier * And the linux kernel needs to know the NUMA topology at start 2862*58c46efaSLaurent Vivier * to be able to hotplug CPUs later. 2863*58c46efaSLaurent Vivier */ 2864*58c46efaSLaurent Vivier if (machine->numa_state->num_nodes) { 2865*58c46efaSLaurent Vivier for (i = 0; i < machine->numa_state->num_nodes; ++i) { 2866*58c46efaSLaurent Vivier /* check for memory-less node */ 2867*58c46efaSLaurent Vivier if (machine->numa_state->nodes[i].node_mem == 0) { 2868*58c46efaSLaurent Vivier CPUState *cs; 2869*58c46efaSLaurent Vivier int found = 0; 2870*58c46efaSLaurent Vivier /* check for cpu-less node */ 2871*58c46efaSLaurent Vivier CPU_FOREACH(cs) { 2872*58c46efaSLaurent Vivier PowerPCCPU *cpu = POWERPC_CPU(cs); 2873*58c46efaSLaurent Vivier if (cpu->node_id == i) { 2874*58c46efaSLaurent Vivier found = 1; 2875*58c46efaSLaurent Vivier break; 2876*58c46efaSLaurent Vivier } 2877*58c46efaSLaurent Vivier } 2878*58c46efaSLaurent Vivier /* memory-less and cpu-less node */ 2879*58c46efaSLaurent Vivier if (!found) { 2880*58c46efaSLaurent Vivier error_report( 2881*58c46efaSLaurent Vivier "Memory-less/cpu-less nodes are not supported (node %d)", 2882*58c46efaSLaurent Vivier i); 2883*58c46efaSLaurent Vivier exit(1); 2884*58c46efaSLaurent Vivier } 2885*58c46efaSLaurent Vivier } 2886*58c46efaSLaurent Vivier } 2887*58c46efaSLaurent Vivier 2888*58c46efaSLaurent Vivier } 2889*58c46efaSLaurent Vivier 28900550b120SGreg Kurz if ((!kvm_enabled() || kvmppc_has_cap_mmu_radix()) && 2891ad99d04cSDavid Gibson ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, 28920550b120SGreg Kurz spapr->max_compat_pvr)) { 28930550b120SGreg Kurz /* KVM and TCG always allow GTSE with radix... */ 28940550b120SGreg Kurz spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE); 28950550b120SGreg Kurz } 28960550b120SGreg Kurz /* ... but not with hash (currently). */ 28970550b120SGreg Kurz 2898026bfd89SDavid Gibson if (kvm_enabled()) { 2899026bfd89SDavid Gibson /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ 2900026bfd89SDavid Gibson kvmppc_enable_logical_ci_hcalls(); 2901ef9971ddSAlexey Kardashevskiy kvmppc_enable_set_mode_hcall(); 29025145ad4fSNathan Whitehorn 29035145ad4fSNathan Whitehorn /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */ 29045145ad4fSNathan Whitehorn kvmppc_enable_clear_ref_mod_hcalls(); 290568f9f708SSuraj Jitindar Singh 290668f9f708SSuraj Jitindar Singh /* Enable H_PAGE_INIT */ 290768f9f708SSuraj Jitindar Singh kvmppc_enable_h_page_init(); 2908026bfd89SDavid Gibson } 2909026bfd89SDavid Gibson 291053018216SPaolo Bonzini /* allocate RAM */ 2911f92f5da1SAlexey Kardashevskiy memory_region_allocate_system_memory(ram, NULL, "ppc_spapr.ram", 2912fb164994SDavid Gibson machine->ram_size); 2913f92f5da1SAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, ram); 291453018216SPaolo Bonzini 2915b0c14ec4SDavid Hildenbrand /* always allocate the device memory information */ 2916b0c14ec4SDavid Hildenbrand machine->device_memory = g_malloc0(sizeof(*machine->device_memory)); 2917b0c14ec4SDavid Hildenbrand 29184a1c9cf0SBharata B Rao /* initialize hotplug memory address space */ 29194a1c9cf0SBharata B Rao if (machine->ram_size < machine->maxram_size) { 29200c9269a5SDavid Hildenbrand ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size; 292171c9a3ddSBharata B Rao /* 292271c9a3ddSBharata B Rao * Limit the number of hotpluggable memory slots to half the number 292371c9a3ddSBharata B Rao * slots that KVM supports, leaving the other half for PCI and other 292471c9a3ddSBharata B Rao * devices. However ensure that number of slots doesn't drop below 32. 292571c9a3ddSBharata B Rao */ 292671c9a3ddSBharata B Rao int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 : 292771c9a3ddSBharata B Rao SPAPR_MAX_RAM_SLOTS; 29284a1c9cf0SBharata B Rao 292971c9a3ddSBharata B Rao if (max_memslots < SPAPR_MAX_RAM_SLOTS) { 293071c9a3ddSBharata B Rao max_memslots = SPAPR_MAX_RAM_SLOTS; 293171c9a3ddSBharata B Rao } 293271c9a3ddSBharata B Rao if (machine->ram_slots > max_memslots) { 2933d54e4d76SDavid Gibson error_report("Specified number of memory slots %" 2934d54e4d76SDavid Gibson PRIu64" exceeds max supported %d", 293571c9a3ddSBharata B Rao machine->ram_slots, max_memslots); 2936d54e4d76SDavid Gibson exit(1); 29374a1c9cf0SBharata B Rao } 29384a1c9cf0SBharata B Rao 2939b0c14ec4SDavid Hildenbrand machine->device_memory->base = ROUND_UP(machine->ram_size, 29400c9269a5SDavid Hildenbrand SPAPR_DEVICE_MEM_ALIGN); 2941b0c14ec4SDavid Hildenbrand memory_region_init(&machine->device_memory->mr, OBJECT(spapr), 29420c9269a5SDavid Hildenbrand "device-memory", device_mem_size); 2943b0c14ec4SDavid Hildenbrand memory_region_add_subregion(sysmem, machine->device_memory->base, 2944b0c14ec4SDavid Hildenbrand &machine->device_memory->mr); 29454a1c9cf0SBharata B Rao } 29464a1c9cf0SBharata B Rao 2947224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2948224245bfSDavid Gibson spapr_create_lmb_dr_connectors(spapr); 2949224245bfSDavid Gibson } 2950224245bfSDavid Gibson 295153018216SPaolo Bonzini filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin"); 29524c56440dSStefan Weil if (!filename) { 2953730fce59SThomas Huth error_report("Could not find LPAR rtas '%s'", "spapr-rtas.bin"); 29544c56440dSStefan Weil exit(1); 29554c56440dSStefan Weil } 2956b7d1f77aSBenjamin Herrenschmidt spapr->rtas_size = get_image_size(filename); 29578afc22a2SZhou Jie if (spapr->rtas_size < 0) { 29588afc22a2SZhou Jie error_report("Could not get size of LPAR rtas '%s'", filename); 29598afc22a2SZhou Jie exit(1); 29608afc22a2SZhou Jie } 2961b7d1f77aSBenjamin Herrenschmidt spapr->rtas_blob = g_malloc(spapr->rtas_size); 2962b7d1f77aSBenjamin Herrenschmidt if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) { 2963730fce59SThomas Huth error_report("Could not load LPAR rtas '%s'", filename); 296453018216SPaolo Bonzini exit(1); 296553018216SPaolo Bonzini } 296653018216SPaolo Bonzini if (spapr->rtas_size > RTAS_MAX_SIZE) { 2967730fce59SThomas Huth error_report("RTAS too big ! 0x%zx bytes (max is 0x%x)", 29682f285bddSPeter Maydell (size_t)spapr->rtas_size, RTAS_MAX_SIZE); 296953018216SPaolo Bonzini exit(1); 297053018216SPaolo Bonzini } 297153018216SPaolo Bonzini g_free(filename); 297253018216SPaolo Bonzini 2973ffbb1705SMichael Roth /* Set up RTAS event infrastructure */ 297453018216SPaolo Bonzini spapr_events_init(spapr); 297553018216SPaolo Bonzini 297612f42174SDavid Gibson /* Set up the RTC RTAS interfaces */ 297728df36a1SDavid Gibson spapr_rtc_create(spapr); 297812f42174SDavid Gibson 297953018216SPaolo Bonzini /* Set up VIO bus */ 298053018216SPaolo Bonzini spapr->vio_bus = spapr_vio_bus_init(); 298153018216SPaolo Bonzini 2982b8846a4dSPeter Maydell for (i = 0; i < serial_max_hds(); i++) { 29839bca0edbSPeter Maydell if (serial_hd(i)) { 29849bca0edbSPeter Maydell spapr_vty_create(spapr->vio_bus, serial_hd(i)); 298553018216SPaolo Bonzini } 298653018216SPaolo Bonzini } 298753018216SPaolo Bonzini 298853018216SPaolo Bonzini /* We always have at least the nvram device on VIO */ 298953018216SPaolo Bonzini spapr_create_nvram(spapr); 299053018216SPaolo Bonzini 2991962b6c36SMichael Roth /* 2992962b6c36SMichael Roth * Setup hotplug / dynamic-reconfiguration connectors. top-level 2993962b6c36SMichael Roth * connectors (described in root DT node's "ibm,drc-types" property) 2994962b6c36SMichael Roth * are pre-initialized here. additional child connectors (such as 2995962b6c36SMichael Roth * connectors for a PHBs PCI slots) are added as needed during their 2996962b6c36SMichael Roth * parent's realization. 2997962b6c36SMichael Roth */ 2998962b6c36SMichael Roth if (smc->dr_phb_enabled) { 2999962b6c36SMichael Roth for (i = 0; i < SPAPR_MAX_PHBS; i++) { 3000962b6c36SMichael Roth spapr_dr_connector_new(OBJECT(machine), TYPE_SPAPR_DRC_PHB, i); 3001962b6c36SMichael Roth } 3002962b6c36SMichael Roth } 3003962b6c36SMichael Roth 300453018216SPaolo Bonzini /* Set up PCI */ 300553018216SPaolo Bonzini spapr_pci_rtas_init(); 300653018216SPaolo Bonzini 3007999c9cafSGreg Kurz phb = spapr_create_default_phb(); 300853018216SPaolo Bonzini 300953018216SPaolo Bonzini for (i = 0; i < nb_nics; i++) { 301053018216SPaolo Bonzini NICInfo *nd = &nd_table[i]; 301153018216SPaolo Bonzini 301253018216SPaolo Bonzini if (!nd->model) { 30133c3a4e7aSThomas Huth nd->model = g_strdup("spapr-vlan"); 301453018216SPaolo Bonzini } 301553018216SPaolo Bonzini 30163c3a4e7aSThomas Huth if (g_str_equal(nd->model, "spapr-vlan") || 30173c3a4e7aSThomas Huth g_str_equal(nd->model, "ibmveth")) { 301853018216SPaolo Bonzini spapr_vlan_create(spapr->vio_bus, nd); 301953018216SPaolo Bonzini } else { 302029b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL); 302153018216SPaolo Bonzini } 302253018216SPaolo Bonzini } 302353018216SPaolo Bonzini 302453018216SPaolo Bonzini for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { 302553018216SPaolo Bonzini spapr_vscsi_create(spapr->vio_bus); 302653018216SPaolo Bonzini } 302753018216SPaolo Bonzini 302853018216SPaolo Bonzini /* Graphics */ 302914c6a894SDavid Gibson if (spapr_vga_init(phb->bus, &error_fatal)) { 303053018216SPaolo Bonzini spapr->has_graphics = true; 3031c6e76503SPaolo Bonzini machine->usb |= defaults_enabled() && !machine->usb_disabled; 303253018216SPaolo Bonzini } 303353018216SPaolo Bonzini 30344ee9ced9SMarcel Apfelbaum if (machine->usb) { 303557040d45SThomas Huth if (smc->use_ohci_by_default) { 303653018216SPaolo Bonzini pci_create_simple(phb->bus, -1, "pci-ohci"); 303757040d45SThomas Huth } else { 303857040d45SThomas Huth pci_create_simple(phb->bus, -1, "nec-usb-xhci"); 303957040d45SThomas Huth } 3040c86580b8SMarkus Armbruster 304153018216SPaolo Bonzini if (spapr->has_graphics) { 3042c86580b8SMarkus Armbruster USBBus *usb_bus = usb_bus_find(-1); 3043c86580b8SMarkus Armbruster 3044c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-kbd"); 3045c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-mouse"); 304653018216SPaolo Bonzini } 304753018216SPaolo Bonzini } 304853018216SPaolo Bonzini 3049ab3dd749SPhilippe Mathieu-Daudé if (spapr->rma_size < (MIN_RMA_SLOF * MiB)) { 3050d54e4d76SDavid Gibson error_report( 3051d54e4d76SDavid Gibson "pSeries SLOF firmware requires >= %ldM guest RMA (Real Mode Area memory)", 3052d54e4d76SDavid Gibson MIN_RMA_SLOF); 305353018216SPaolo Bonzini exit(1); 305453018216SPaolo Bonzini } 305553018216SPaolo Bonzini 305653018216SPaolo Bonzini if (kernel_filename) { 305753018216SPaolo Bonzini uint64_t lowaddr = 0; 305853018216SPaolo Bonzini 30594366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL, 30604366e1dbSLiam Merwick translate_kernel_address, NULL, 30614366e1dbSLiam Merwick NULL, &lowaddr, NULL, 1, 3062a19f7fb0SDavid Gibson PPC_ELF_MACHINE, 0, 0); 3063a19f7fb0SDavid Gibson if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) { 30644366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL, 3065a19f7fb0SDavid Gibson translate_kernel_address, NULL, NULL, 3066a19f7fb0SDavid Gibson &lowaddr, NULL, 0, PPC_ELF_MACHINE, 30677ef295eaSPeter Crosthwaite 0, 0); 3068a19f7fb0SDavid Gibson spapr->kernel_le = spapr->kernel_size > 0; 306916457e7fSBenjamin Herrenschmidt } 3070a19f7fb0SDavid Gibson if (spapr->kernel_size < 0) { 3071a19f7fb0SDavid Gibson error_report("error loading %s: %s", kernel_filename, 3072a19f7fb0SDavid Gibson load_elf_strerror(spapr->kernel_size)); 307353018216SPaolo Bonzini exit(1); 307453018216SPaolo Bonzini } 307553018216SPaolo Bonzini 307653018216SPaolo Bonzini /* load initrd */ 307753018216SPaolo Bonzini if (initrd_filename) { 307853018216SPaolo Bonzini /* Try to locate the initrd in the gap between the kernel 307953018216SPaolo Bonzini * and the firmware. Add a bit of space just in case 308053018216SPaolo Bonzini */ 3081a19f7fb0SDavid Gibson spapr->initrd_base = (KERNEL_LOAD_ADDR + spapr->kernel_size 3082a19f7fb0SDavid Gibson + 0x1ffff) & ~0xffff; 3083a19f7fb0SDavid Gibson spapr->initrd_size = load_image_targphys(initrd_filename, 3084a19f7fb0SDavid Gibson spapr->initrd_base, 3085a19f7fb0SDavid Gibson load_limit 3086a19f7fb0SDavid Gibson - spapr->initrd_base); 3087a19f7fb0SDavid Gibson if (spapr->initrd_size < 0) { 3088d54e4d76SDavid Gibson error_report("could not load initial ram disk '%s'", 308953018216SPaolo Bonzini initrd_filename); 309053018216SPaolo Bonzini exit(1); 309153018216SPaolo Bonzini } 309253018216SPaolo Bonzini } 309353018216SPaolo Bonzini } 309453018216SPaolo Bonzini 30958e7ea787SAndreas Färber if (bios_name == NULL) { 30968e7ea787SAndreas Färber bios_name = FW_FILE_NAME; 30978e7ea787SAndreas Färber } 30988e7ea787SAndreas Färber filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 30994c56440dSStefan Weil if (!filename) { 310068fea5a0SThomas Huth error_report("Could not find LPAR firmware '%s'", bios_name); 31014c56440dSStefan Weil exit(1); 31024c56440dSStefan Weil } 310353018216SPaolo Bonzini fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); 310468fea5a0SThomas Huth if (fw_size <= 0) { 310568fea5a0SThomas Huth error_report("Could not load LPAR firmware '%s'", filename); 310653018216SPaolo Bonzini exit(1); 310753018216SPaolo Bonzini } 310853018216SPaolo Bonzini g_free(filename); 310953018216SPaolo Bonzini 311028e02042SDavid Gibson /* FIXME: Should register things through the MachineState's qdev 311128e02042SDavid Gibson * interface, this is a legacy from the sPAPREnvironment structure 311228e02042SDavid Gibson * which predated MachineState but had a similar function */ 31134be21d56SDavid Gibson vmstate_register(NULL, 0, &vmstate_spapr, spapr); 3114ce62df53SDr. David Alan Gilbert register_savevm_live("spapr/htab", -1, 1, 31154be21d56SDavid Gibson &savevm_htab_handlers, spapr); 31164be21d56SDavid Gibson 3117bb2bdd81SGreg Kurz qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine), 3118bb2bdd81SGreg Kurz &error_fatal); 3119bb2bdd81SGreg Kurz 31205b2128d2SAlexander Graf qemu_register_boot_set(spapr_boot_set, spapr); 312142043e4fSLaurent Vivier 312293eac7b8SNicholas Piggin /* 312393eac7b8SNicholas Piggin * Nothing needs to be done to resume a suspended guest because 312493eac7b8SNicholas Piggin * suspending does not change the machine state, so no need for 312593eac7b8SNicholas Piggin * a ->wakeup method. 312693eac7b8SNicholas Piggin */ 312793eac7b8SNicholas Piggin qemu_register_wakeup_support(); 312893eac7b8SNicholas Piggin 312942043e4fSLaurent Vivier if (kvm_enabled()) { 31303dc410aeSAlexey Kardashevskiy /* to stop and start vmclock */ 313142043e4fSLaurent Vivier qemu_add_vm_change_state_handler(cpu_ppc_clock_vm_state_change, 313242043e4fSLaurent Vivier &spapr->tb); 31333dc410aeSAlexey Kardashevskiy 31343dc410aeSAlexey Kardashevskiy kvmppc_spapr_enable_inkernel_multitce(); 313542043e4fSLaurent Vivier } 313653018216SPaolo Bonzini } 313753018216SPaolo Bonzini 3138dc0ca80eSEric Auger static int spapr_kvm_type(MachineState *machine, const char *vm_type) 3139135a129aSAneesh Kumar K.V { 3140135a129aSAneesh Kumar K.V if (!vm_type) { 3141135a129aSAneesh Kumar K.V return 0; 3142135a129aSAneesh Kumar K.V } 3143135a129aSAneesh Kumar K.V 3144135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "HV")) { 3145135a129aSAneesh Kumar K.V return 1; 3146135a129aSAneesh Kumar K.V } 3147135a129aSAneesh Kumar K.V 3148135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "PR")) { 3149135a129aSAneesh Kumar K.V return 2; 3150135a129aSAneesh Kumar K.V } 3151135a129aSAneesh Kumar K.V 3152135a129aSAneesh Kumar K.V error_report("Unknown kvm-type specified '%s'", vm_type); 3153135a129aSAneesh Kumar K.V exit(1); 3154135a129aSAneesh Kumar K.V } 3155135a129aSAneesh Kumar K.V 315671461b0fSAlexey Kardashevskiy /* 3157627b84f4SGonglei * Implementation of an interface to adjust firmware path 315871461b0fSAlexey Kardashevskiy * for the bootindex property handling. 315971461b0fSAlexey Kardashevskiy */ 316071461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, 316171461b0fSAlexey Kardashevskiy DeviceState *dev) 316271461b0fSAlexey Kardashevskiy { 316371461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \ 316471461b0fSAlexey Kardashevskiy ((type *)object_dynamic_cast(OBJECT(obj), (name))) 316571461b0fSAlexey Kardashevskiy SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); 3166ce2918cbSDavid Gibson SpaprPhbState *phb = CAST(SpaprPhbState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); 3167c4e13492SFelipe Franciosi VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON); 316871461b0fSAlexey Kardashevskiy 316971461b0fSAlexey Kardashevskiy if (d) { 317071461b0fSAlexey Kardashevskiy void *spapr = CAST(void, bus->parent, "spapr-vscsi"); 317171461b0fSAlexey Kardashevskiy VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); 317271461b0fSAlexey Kardashevskiy USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); 317371461b0fSAlexey Kardashevskiy 317471461b0fSAlexey Kardashevskiy if (spapr) { 317571461b0fSAlexey Kardashevskiy /* 317671461b0fSAlexey Kardashevskiy * Replace "channel@0/disk@0,0" with "disk@8000000000000000": 31771ac24c91SThomas Huth * In the top 16 bits of the 64-bit LUN, we use SRP luns of the form 31781ac24c91SThomas Huth * 0x8000 | (target << 8) | (bus << 5) | lun 31791ac24c91SThomas Huth * (see the "Logical unit addressing format" table in SAM5) 318071461b0fSAlexey Kardashevskiy */ 31811ac24c91SThomas Huth unsigned id = 0x8000 | (d->id << 8) | (d->channel << 5) | d->lun; 318271461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 318371461b0fSAlexey Kardashevskiy (uint64_t)id << 48); 318471461b0fSAlexey Kardashevskiy } else if (virtio) { 318571461b0fSAlexey Kardashevskiy /* 318671461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (target << 8) | lun 318771461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 318871461b0fSAlexey Kardashevskiy * Note: the quote above is from SLOF and it is wrong, 318971461b0fSAlexey Kardashevskiy * the actual binding is: 319071461b0fSAlexey Kardashevskiy * swap 0100 or 10 << or 20 << ( target lun-id -- srplun ) 319171461b0fSAlexey Kardashevskiy */ 319271461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (d->id << 16) | d->lun; 3193bac658d1SThomas Huth if (d->lun >= 256) { 3194bac658d1SThomas Huth /* Use the LUN "flat space addressing method" */ 3195bac658d1SThomas Huth id |= 0x4000; 3196bac658d1SThomas Huth } 319771461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 319871461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 319971461b0fSAlexey Kardashevskiy } else if (usb) { 320071461b0fSAlexey Kardashevskiy /* 320171461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (usb-port << 16) | lun 320271461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 320371461b0fSAlexey Kardashevskiy */ 320471461b0fSAlexey Kardashevskiy unsigned usb_port = atoi(usb->port->path); 320571461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (usb_port << 16) | d->lun; 320671461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 320771461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 320871461b0fSAlexey Kardashevskiy } 320971461b0fSAlexey Kardashevskiy } 321071461b0fSAlexey Kardashevskiy 3211b99260ebSThomas Huth /* 3212b99260ebSThomas Huth * SLOF probes the USB devices, and if it recognizes that the device is a 3213b99260ebSThomas Huth * storage device, it changes its name to "storage" instead of "usb-host", 3214b99260ebSThomas Huth * and additionally adds a child node for the SCSI LUN, so the correct 3215b99260ebSThomas Huth * boot path in SLOF is something like .../storage@1/disk@xxx" instead. 3216b99260ebSThomas Huth */ 3217b99260ebSThomas Huth if (strcmp("usb-host", qdev_fw_name(dev)) == 0) { 3218b99260ebSThomas Huth USBDevice *usbdev = CAST(USBDevice, dev, TYPE_USB_DEVICE); 3219b99260ebSThomas Huth if (usb_host_dev_is_scsi_storage(usbdev)) { 3220b99260ebSThomas Huth return g_strdup_printf("storage@%s/disk", usbdev->port->path); 3221b99260ebSThomas Huth } 3222b99260ebSThomas Huth } 3223b99260ebSThomas Huth 322471461b0fSAlexey Kardashevskiy if (phb) { 322571461b0fSAlexey Kardashevskiy /* Replace "pci" with "pci@800000020000000" */ 322671461b0fSAlexey Kardashevskiy return g_strdup_printf("pci@%"PRIX64, phb->buid); 322771461b0fSAlexey Kardashevskiy } 322871461b0fSAlexey Kardashevskiy 3229c4e13492SFelipe Franciosi if (vsc) { 3230c4e13492SFelipe Franciosi /* Same logic as virtio above */ 3231c4e13492SFelipe Franciosi unsigned id = 0x1000000 | (vsc->target << 16) | vsc->lun; 3232c4e13492SFelipe Franciosi return g_strdup_printf("disk@%"PRIX64, (uint64_t)id << 32); 3233c4e13492SFelipe Franciosi } 3234c4e13492SFelipe Franciosi 32354871dd4cSThomas Huth if (g_str_equal("pci-bridge", qdev_fw_name(dev))) { 32364871dd4cSThomas Huth /* SLOF uses "pci" instead of "pci-bridge" for PCI bridges */ 32374871dd4cSThomas Huth PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); 32384871dd4cSThomas Huth return g_strdup_printf("pci@%x", PCI_SLOT(pcidev->devfn)); 32394871dd4cSThomas Huth } 32404871dd4cSThomas Huth 324171461b0fSAlexey Kardashevskiy return NULL; 324271461b0fSAlexey Kardashevskiy } 324371461b0fSAlexey Kardashevskiy 324423825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp) 324523825581SEduardo Habkost { 3246ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 324723825581SEduardo Habkost 324828e02042SDavid Gibson return g_strdup(spapr->kvm_type); 324923825581SEduardo Habkost } 325023825581SEduardo Habkost 325123825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp) 325223825581SEduardo Habkost { 3253ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 325423825581SEduardo Habkost 325528e02042SDavid Gibson g_free(spapr->kvm_type); 325628e02042SDavid Gibson spapr->kvm_type = g_strdup(value); 325723825581SEduardo Habkost } 325823825581SEduardo Habkost 3259f6229214SMichael Roth static bool spapr_get_modern_hotplug_events(Object *obj, Error **errp) 3260f6229214SMichael Roth { 3261ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3262f6229214SMichael Roth 3263f6229214SMichael Roth return spapr->use_hotplug_event_source; 3264f6229214SMichael Roth } 3265f6229214SMichael Roth 3266f6229214SMichael Roth static void spapr_set_modern_hotplug_events(Object *obj, bool value, 3267f6229214SMichael Roth Error **errp) 3268f6229214SMichael Roth { 3269ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3270f6229214SMichael Roth 3271f6229214SMichael Roth spapr->use_hotplug_event_source = value; 3272f6229214SMichael Roth } 3273f6229214SMichael Roth 3274fcad0d21SAlexey Kardashevskiy static bool spapr_get_msix_emulation(Object *obj, Error **errp) 3275fcad0d21SAlexey Kardashevskiy { 3276fcad0d21SAlexey Kardashevskiy return true; 3277fcad0d21SAlexey Kardashevskiy } 3278fcad0d21SAlexey Kardashevskiy 327930f4b05bSDavid Gibson static char *spapr_get_resize_hpt(Object *obj, Error **errp) 328030f4b05bSDavid Gibson { 3281ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 328230f4b05bSDavid Gibson 328330f4b05bSDavid Gibson switch (spapr->resize_hpt) { 328430f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DEFAULT: 328530f4b05bSDavid Gibson return g_strdup("default"); 328630f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DISABLED: 328730f4b05bSDavid Gibson return g_strdup("disabled"); 328830f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_ENABLED: 328930f4b05bSDavid Gibson return g_strdup("enabled"); 329030f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_REQUIRED: 329130f4b05bSDavid Gibson return g_strdup("required"); 329230f4b05bSDavid Gibson } 329330f4b05bSDavid Gibson g_assert_not_reached(); 329430f4b05bSDavid Gibson } 329530f4b05bSDavid Gibson 329630f4b05bSDavid Gibson static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp) 329730f4b05bSDavid Gibson { 3298ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 329930f4b05bSDavid Gibson 330030f4b05bSDavid Gibson if (strcmp(value, "default") == 0) { 330130f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DEFAULT; 330230f4b05bSDavid Gibson } else if (strcmp(value, "disabled") == 0) { 330330f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 330430f4b05bSDavid Gibson } else if (strcmp(value, "enabled") == 0) { 330530f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_ENABLED; 330630f4b05bSDavid Gibson } else if (strcmp(value, "required") == 0) { 330730f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_REQUIRED; 330830f4b05bSDavid Gibson } else { 330930f4b05bSDavid Gibson error_setg(errp, "Bad value for \"resize-hpt\" property"); 331030f4b05bSDavid Gibson } 331130f4b05bSDavid Gibson } 331230f4b05bSDavid Gibson 3313fa98fbfcSSam Bobroff static void spapr_get_vsmt(Object *obj, Visitor *v, const char *name, 3314fa98fbfcSSam Bobroff void *opaque, Error **errp) 3315fa98fbfcSSam Bobroff { 3316fa98fbfcSSam Bobroff visit_type_uint32(v, name, (uint32_t *)opaque, errp); 3317fa98fbfcSSam Bobroff } 3318fa98fbfcSSam Bobroff 3319fa98fbfcSSam Bobroff static void spapr_set_vsmt(Object *obj, Visitor *v, const char *name, 3320fa98fbfcSSam Bobroff void *opaque, Error **errp) 3321fa98fbfcSSam Bobroff { 3322fa98fbfcSSam Bobroff visit_type_uint32(v, name, (uint32_t *)opaque, errp); 3323fa98fbfcSSam Bobroff } 3324fa98fbfcSSam Bobroff 33253ba3d0bcSCédric Le Goater static char *spapr_get_ic_mode(Object *obj, Error **errp) 33263ba3d0bcSCédric Le Goater { 3327ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 33283ba3d0bcSCédric Le Goater 33293ba3d0bcSCédric Le Goater if (spapr->irq == &spapr_irq_xics_legacy) { 33303ba3d0bcSCédric Le Goater return g_strdup("legacy"); 33313ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xics) { 33323ba3d0bcSCédric Le Goater return g_strdup("xics"); 33333ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xive) { 33343ba3d0bcSCédric Le Goater return g_strdup("xive"); 333513db0cd9SCédric Le Goater } else if (spapr->irq == &spapr_irq_dual) { 333613db0cd9SCédric Le Goater return g_strdup("dual"); 33373ba3d0bcSCédric Le Goater } 33383ba3d0bcSCédric Le Goater g_assert_not_reached(); 33393ba3d0bcSCédric Le Goater } 33403ba3d0bcSCédric Le Goater 33413ba3d0bcSCédric Le Goater static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp) 33423ba3d0bcSCédric Le Goater { 3343ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 33443ba3d0bcSCédric Le Goater 334521df5e4fSGreg Kurz if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { 334621df5e4fSGreg Kurz error_setg(errp, "This machine only uses the legacy XICS backend, don't pass ic-mode"); 334721df5e4fSGreg Kurz return; 334821df5e4fSGreg Kurz } 334921df5e4fSGreg Kurz 33503ba3d0bcSCédric Le Goater /* The legacy IRQ backend can not be set */ 33513ba3d0bcSCédric Le Goater if (strcmp(value, "xics") == 0) { 33523ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xics; 33533ba3d0bcSCédric Le Goater } else if (strcmp(value, "xive") == 0) { 33543ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xive; 335513db0cd9SCédric Le Goater } else if (strcmp(value, "dual") == 0) { 335613db0cd9SCédric Le Goater spapr->irq = &spapr_irq_dual; 33573ba3d0bcSCédric Le Goater } else { 33583ba3d0bcSCédric Le Goater error_setg(errp, "Bad value for \"ic-mode\" property"); 33593ba3d0bcSCédric Le Goater } 33603ba3d0bcSCédric Le Goater } 33613ba3d0bcSCédric Le Goater 336227461d69SPrasad J Pandit static char *spapr_get_host_model(Object *obj, Error **errp) 336327461d69SPrasad J Pandit { 3364ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 336527461d69SPrasad J Pandit 336627461d69SPrasad J Pandit return g_strdup(spapr->host_model); 336727461d69SPrasad J Pandit } 336827461d69SPrasad J Pandit 336927461d69SPrasad J Pandit static void spapr_set_host_model(Object *obj, const char *value, Error **errp) 337027461d69SPrasad J Pandit { 3371ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 337227461d69SPrasad J Pandit 337327461d69SPrasad J Pandit g_free(spapr->host_model); 337427461d69SPrasad J Pandit spapr->host_model = g_strdup(value); 337527461d69SPrasad J Pandit } 337627461d69SPrasad J Pandit 337727461d69SPrasad J Pandit static char *spapr_get_host_serial(Object *obj, Error **errp) 337827461d69SPrasad J Pandit { 3379ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 338027461d69SPrasad J Pandit 338127461d69SPrasad J Pandit return g_strdup(spapr->host_serial); 338227461d69SPrasad J Pandit } 338327461d69SPrasad J Pandit 338427461d69SPrasad J Pandit static void spapr_set_host_serial(Object *obj, const char *value, Error **errp) 338527461d69SPrasad J Pandit { 3386ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 338727461d69SPrasad J Pandit 338827461d69SPrasad J Pandit g_free(spapr->host_serial); 338927461d69SPrasad J Pandit spapr->host_serial = g_strdup(value); 339027461d69SPrasad J Pandit } 339127461d69SPrasad J Pandit 3392bcb5ce08SDavid Gibson static void spapr_instance_init(Object *obj) 339323825581SEduardo Habkost { 3394ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3395ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 3396715c5407SDavid Gibson 3397715c5407SDavid Gibson spapr->htab_fd = -1; 3398f6229214SMichael Roth spapr->use_hotplug_event_source = true; 339923825581SEduardo Habkost object_property_add_str(obj, "kvm-type", 340023825581SEduardo Habkost spapr_get_kvm_type, spapr_set_kvm_type, NULL); 340149d2e648SMarcel Apfelbaum object_property_set_description(obj, "kvm-type", 340249d2e648SMarcel Apfelbaum "Specifies the KVM virtualization mode (HV, PR)", 340349d2e648SMarcel Apfelbaum NULL); 3404f6229214SMichael Roth object_property_add_bool(obj, "modern-hotplug-events", 3405f6229214SMichael Roth spapr_get_modern_hotplug_events, 3406f6229214SMichael Roth spapr_set_modern_hotplug_events, 3407f6229214SMichael Roth NULL); 3408f6229214SMichael Roth object_property_set_description(obj, "modern-hotplug-events", 3409f6229214SMichael Roth "Use dedicated hotplug event mechanism in" 3410f6229214SMichael Roth " place of standard EPOW events when possible" 3411f6229214SMichael Roth " (required for memory hot-unplug support)", 3412f6229214SMichael Roth NULL); 34137843c0d6SDavid Gibson ppc_compat_add_property(obj, "max-cpu-compat", &spapr->max_compat_pvr, 34147843c0d6SDavid Gibson "Maximum permitted CPU compatibility mode", 34157843c0d6SDavid Gibson &error_fatal); 341630f4b05bSDavid Gibson 341730f4b05bSDavid Gibson object_property_add_str(obj, "resize-hpt", 341830f4b05bSDavid Gibson spapr_get_resize_hpt, spapr_set_resize_hpt, NULL); 341930f4b05bSDavid Gibson object_property_set_description(obj, "resize-hpt", 342030f4b05bSDavid Gibson "Resizing of the Hash Page Table (enabled, disabled, required)", 342130f4b05bSDavid Gibson NULL); 3422fa98fbfcSSam Bobroff object_property_add(obj, "vsmt", "uint32", spapr_get_vsmt, 3423fa98fbfcSSam Bobroff spapr_set_vsmt, NULL, &spapr->vsmt, &error_abort); 3424fa98fbfcSSam Bobroff object_property_set_description(obj, "vsmt", 3425fa98fbfcSSam Bobroff "Virtual SMT: KVM behaves as if this were" 3426fa98fbfcSSam Bobroff " the host's SMT mode", &error_abort); 3427fcad0d21SAlexey Kardashevskiy object_property_add_bool(obj, "vfio-no-msix-emulation", 3428fcad0d21SAlexey Kardashevskiy spapr_get_msix_emulation, NULL, NULL); 34293ba3d0bcSCédric Le Goater 34303ba3d0bcSCédric Le Goater /* The machine class defines the default interrupt controller mode */ 34313ba3d0bcSCédric Le Goater spapr->irq = smc->irq; 34323ba3d0bcSCédric Le Goater object_property_add_str(obj, "ic-mode", spapr_get_ic_mode, 34333ba3d0bcSCédric Le Goater spapr_set_ic_mode, NULL); 34343ba3d0bcSCédric Le Goater object_property_set_description(obj, "ic-mode", 343513db0cd9SCédric Le Goater "Specifies the interrupt controller mode (xics, xive, dual)", 34363ba3d0bcSCédric Le Goater NULL); 343727461d69SPrasad J Pandit 343827461d69SPrasad J Pandit object_property_add_str(obj, "host-model", 343927461d69SPrasad J Pandit spapr_get_host_model, spapr_set_host_model, 344027461d69SPrasad J Pandit &error_abort); 344127461d69SPrasad J Pandit object_property_set_description(obj, "host-model", 34420a794529SDavid Gibson "Host model to advertise in guest device tree", &error_abort); 344327461d69SPrasad J Pandit object_property_add_str(obj, "host-serial", 344427461d69SPrasad J Pandit spapr_get_host_serial, spapr_set_host_serial, 344527461d69SPrasad J Pandit &error_abort); 344627461d69SPrasad J Pandit object_property_set_description(obj, "host-serial", 34470a794529SDavid Gibson "Host serial number to advertise in guest device tree", &error_abort); 344823825581SEduardo Habkost } 344923825581SEduardo Habkost 345087bbdd9cSDavid Gibson static void spapr_machine_finalizefn(Object *obj) 345187bbdd9cSDavid Gibson { 3452ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 345387bbdd9cSDavid Gibson 345487bbdd9cSDavid Gibson g_free(spapr->kvm_type); 345587bbdd9cSDavid Gibson } 345687bbdd9cSDavid Gibson 34571c7ad77eSNicholas Piggin void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg) 345834316482SAlexey Kardashevskiy { 345934316482SAlexey Kardashevskiy cpu_synchronize_state(cs); 346034316482SAlexey Kardashevskiy ppc_cpu_do_system_reset(cs); 346134316482SAlexey Kardashevskiy } 346234316482SAlexey Kardashevskiy 346334316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) 346434316482SAlexey Kardashevskiy { 346534316482SAlexey Kardashevskiy CPUState *cs; 346634316482SAlexey Kardashevskiy 346734316482SAlexey Kardashevskiy CPU_FOREACH(cs) { 34681c7ad77eSNicholas Piggin async_run_on_cpu(cs, spapr_do_system_reset_on_cpu, RUN_ON_CPU_NULL); 346934316482SAlexey Kardashevskiy } 347034316482SAlexey Kardashevskiy } 347134316482SAlexey Kardashevskiy 3472ce2918cbSDavid Gibson int spapr_lmb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 347362d38c9bSGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 347462d38c9bSGreg Kurz { 347562d38c9bSGreg Kurz uint64_t addr; 347662d38c9bSGreg Kurz uint32_t node; 347762d38c9bSGreg Kurz 347862d38c9bSGreg Kurz addr = spapr_drc_index(drc) * SPAPR_MEMORY_BLOCK_SIZE; 347962d38c9bSGreg Kurz node = object_property_get_uint(OBJECT(drc->dev), PC_DIMM_NODE_PROP, 348062d38c9bSGreg Kurz &error_abort); 348162d38c9bSGreg Kurz *fdt_start_offset = spapr_populate_memory_node(fdt, node, addr, 348262d38c9bSGreg Kurz SPAPR_MEMORY_BLOCK_SIZE); 348362d38c9bSGreg Kurz return 0; 348462d38c9bSGreg Kurz } 348562d38c9bSGreg Kurz 348679b78a6bSMichael Roth static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, 348762d38c9bSGreg Kurz bool dedicated_hp_event_source, Error **errp) 3488c20d332aSBharata B Rao { 3489ce2918cbSDavid Gibson SpaprDrc *drc; 3490c20d332aSBharata B Rao uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; 349162d38c9bSGreg Kurz int i; 349279b78a6bSMichael Roth uint64_t addr = addr_start; 349394fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 3494160bb678SGreg Kurz Error *local_err = NULL; 3495c20d332aSBharata B Rao 3496c20d332aSBharata B Rao for (i = 0; i < nr_lmbs; i++) { 3497fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 3498c20d332aSBharata B Rao addr / SPAPR_MEMORY_BLOCK_SIZE); 3499c20d332aSBharata B Rao g_assert(drc); 3500c20d332aSBharata B Rao 350109d876ceSGreg Kurz spapr_drc_attach(drc, dev, &local_err); 3502160bb678SGreg Kurz if (local_err) { 3503160bb678SGreg Kurz while (addr > addr_start) { 3504160bb678SGreg Kurz addr -= SPAPR_MEMORY_BLOCK_SIZE; 3505160bb678SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 3506160bb678SGreg Kurz addr / SPAPR_MEMORY_BLOCK_SIZE); 3507a8dc47fdSDavid Gibson spapr_drc_detach(drc); 3508160bb678SGreg Kurz } 3509160bb678SGreg Kurz error_propagate(errp, local_err); 3510160bb678SGreg Kurz return; 3511160bb678SGreg Kurz } 351294fd9cbaSLaurent Vivier if (!hotplugged) { 351394fd9cbaSLaurent Vivier spapr_drc_reset(drc); 351494fd9cbaSLaurent Vivier } 3515c20d332aSBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE; 3516c20d332aSBharata B Rao } 35175dd5238cSJianjun Duan /* send hotplug notification to the 35185dd5238cSJianjun Duan * guest only in case of hotplugged memory 35195dd5238cSJianjun Duan */ 352094fd9cbaSLaurent Vivier if (hotplugged) { 352179b78a6bSMichael Roth if (dedicated_hp_event_source) { 3522fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 352379b78a6bSMichael Roth addr_start / SPAPR_MEMORY_BLOCK_SIZE); 352479b78a6bSMichael Roth spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 352579b78a6bSMichael Roth nr_lmbs, 35260b55aa91SDavid Gibson spapr_drc_index(drc)); 352779b78a6bSMichael Roth } else { 352879b78a6bSMichael Roth spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, 352979b78a6bSMichael Roth nr_lmbs); 353079b78a6bSMichael Roth } 3531c20d332aSBharata B Rao } 35325dd5238cSJianjun Duan } 3533c20d332aSBharata B Rao 3534c20d332aSBharata B Rao static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 353581985f3bSDavid Hildenbrand Error **errp) 3536c20d332aSBharata B Rao { 3537c20d332aSBharata B Rao Error *local_err = NULL; 3538ce2918cbSDavid Gibson SpaprMachineState *ms = SPAPR_MACHINE(hotplug_dev); 3539c20d332aSBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 3540b0e62443SDavid Hildenbrand uint64_t size, addr; 354104790978SThomas Huth 3542946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dev), &error_abort); 3543df587133SThomas Huth 3544fd3416f5SDavid Hildenbrand pc_dimm_plug(dimm, MACHINE(ms), &local_err); 3545c20d332aSBharata B Rao if (local_err) { 3546c20d332aSBharata B Rao goto out; 3547c20d332aSBharata B Rao } 3548c20d332aSBharata B Rao 35499ed442b8SMarc-André Lureau addr = object_property_get_uint(OBJECT(dimm), 35509ed442b8SMarc-André Lureau PC_DIMM_ADDR_PROP, &local_err); 3551c20d332aSBharata B Rao if (local_err) { 3552160bb678SGreg Kurz goto out_unplug; 3553c20d332aSBharata B Rao } 3554c20d332aSBharata B Rao 355562d38c9bSGreg Kurz spapr_add_lmbs(dev, addr, size, spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), 3556160bb678SGreg Kurz &local_err); 3557160bb678SGreg Kurz if (local_err) { 3558160bb678SGreg Kurz goto out_unplug; 3559160bb678SGreg Kurz } 3560c20d332aSBharata B Rao 3561160bb678SGreg Kurz return; 3562160bb678SGreg Kurz 3563160bb678SGreg Kurz out_unplug: 3564fd3416f5SDavid Hildenbrand pc_dimm_unplug(dimm, MACHINE(ms)); 3565c20d332aSBharata B Rao out: 3566c20d332aSBharata B Rao error_propagate(errp, local_err); 3567c20d332aSBharata B Rao } 3568c20d332aSBharata B Rao 3569c871bc70SLaurent Vivier static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3570c871bc70SLaurent Vivier Error **errp) 3571c871bc70SLaurent Vivier { 3572ce2918cbSDavid Gibson const SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev); 3573ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3574c871bc70SLaurent Vivier PCDIMMDevice *dimm = PC_DIMM(dev); 35758f1ffe5bSDavid Hildenbrand Error *local_err = NULL; 357604790978SThomas Huth uint64_t size; 3577123eec65SDavid Gibson Object *memdev; 3578123eec65SDavid Gibson hwaddr pagesize; 3579c871bc70SLaurent Vivier 35804e8a01bdSDavid Hildenbrand if (!smc->dr_lmb_enabled) { 35814e8a01bdSDavid Hildenbrand error_setg(errp, "Memory hotplug not supported for this machine"); 35824e8a01bdSDavid Hildenbrand return; 35834e8a01bdSDavid Hildenbrand } 35844e8a01bdSDavid Hildenbrand 3585946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &local_err); 3586946d6154SDavid Hildenbrand if (local_err) { 3587946d6154SDavid Hildenbrand error_propagate(errp, local_err); 358804790978SThomas Huth return; 358904790978SThomas Huth } 359004790978SThomas Huth 3591c871bc70SLaurent Vivier if (size % SPAPR_MEMORY_BLOCK_SIZE) { 3592c871bc70SLaurent Vivier error_setg(errp, "Hotplugged memory size must be a multiple of " 3593ab3dd749SPhilippe Mathieu-Daudé "%" PRIu64 " MB", SPAPR_MEMORY_BLOCK_SIZE / MiB); 3594c871bc70SLaurent Vivier return; 3595c871bc70SLaurent Vivier } 3596c871bc70SLaurent Vivier 3597123eec65SDavid Gibson memdev = object_property_get_link(OBJECT(dimm), PC_DIMM_MEMDEV_PROP, 3598123eec65SDavid Gibson &error_abort); 3599123eec65SDavid Gibson pagesize = host_memory_backend_pagesize(MEMORY_BACKEND(memdev)); 36008f1ffe5bSDavid Hildenbrand spapr_check_pagesize(spapr, pagesize, &local_err); 36018f1ffe5bSDavid Hildenbrand if (local_err) { 36028f1ffe5bSDavid Hildenbrand error_propagate(errp, local_err); 36038f1ffe5bSDavid Hildenbrand return; 36048f1ffe5bSDavid Hildenbrand } 36058f1ffe5bSDavid Hildenbrand 3606fd3416f5SDavid Hildenbrand pc_dimm_pre_plug(dimm, MACHINE(hotplug_dev), NULL, errp); 3607c871bc70SLaurent Vivier } 3608c871bc70SLaurent Vivier 3609ce2918cbSDavid Gibson struct SpaprDimmState { 36100cffce56SDavid Gibson PCDIMMDevice *dimm; 3611cf632463SBharata B Rao uint32_t nr_lmbs; 3612ce2918cbSDavid Gibson QTAILQ_ENTRY(SpaprDimmState) next; 36130cffce56SDavid Gibson }; 36140cffce56SDavid Gibson 3615ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_find(SpaprMachineState *s, 36160cffce56SDavid Gibson PCDIMMDevice *dimm) 36170cffce56SDavid Gibson { 3618ce2918cbSDavid Gibson SpaprDimmState *dimm_state = NULL; 36190cffce56SDavid Gibson 36200cffce56SDavid Gibson QTAILQ_FOREACH(dimm_state, &s->pending_dimm_unplugs, next) { 36210cffce56SDavid Gibson if (dimm_state->dimm == dimm) { 36220cffce56SDavid Gibson break; 36230cffce56SDavid Gibson } 36240cffce56SDavid Gibson } 36250cffce56SDavid Gibson return dimm_state; 36260cffce56SDavid Gibson } 36270cffce56SDavid Gibson 3628ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_add(SpaprMachineState *spapr, 36298d5981c4SBharata B Rao uint32_t nr_lmbs, 36308d5981c4SBharata B Rao PCDIMMDevice *dimm) 36310cffce56SDavid Gibson { 3632ce2918cbSDavid Gibson SpaprDimmState *ds = NULL; 36338d5981c4SBharata B Rao 36348d5981c4SBharata B Rao /* 36358d5981c4SBharata B Rao * If this request is for a DIMM whose removal had failed earlier 36368d5981c4SBharata B Rao * (due to guest's refusal to remove the LMBs), we would have this 36378d5981c4SBharata B Rao * dimm already in the pending_dimm_unplugs list. In that 36388d5981c4SBharata B Rao * case don't add again. 36398d5981c4SBharata B Rao */ 36408d5981c4SBharata B Rao ds = spapr_pending_dimm_unplugs_find(spapr, dimm); 36418d5981c4SBharata B Rao if (!ds) { 3642ce2918cbSDavid Gibson ds = g_malloc0(sizeof(SpaprDimmState)); 36438d5981c4SBharata B Rao ds->nr_lmbs = nr_lmbs; 36448d5981c4SBharata B Rao ds->dimm = dimm; 36458d5981c4SBharata B Rao QTAILQ_INSERT_HEAD(&spapr->pending_dimm_unplugs, ds, next); 36468d5981c4SBharata B Rao } 36478d5981c4SBharata B Rao return ds; 36480cffce56SDavid Gibson } 36490cffce56SDavid Gibson 3650ce2918cbSDavid Gibson static void spapr_pending_dimm_unplugs_remove(SpaprMachineState *spapr, 3651ce2918cbSDavid Gibson SpaprDimmState *dimm_state) 36520cffce56SDavid Gibson { 36530cffce56SDavid Gibson QTAILQ_REMOVE(&spapr->pending_dimm_unplugs, dimm_state, next); 36540cffce56SDavid Gibson g_free(dimm_state); 36550cffce56SDavid Gibson } 3656cf632463SBharata B Rao 3657ce2918cbSDavid Gibson static SpaprDimmState *spapr_recover_pending_dimm_state(SpaprMachineState *ms, 365816ee9980SDaniel Henrique Barboza PCDIMMDevice *dimm) 365916ee9980SDaniel Henrique Barboza { 3660ce2918cbSDavid Gibson SpaprDrc *drc; 3661946d6154SDavid Hildenbrand uint64_t size = memory_device_get_region_size(MEMORY_DEVICE(dimm), 3662946d6154SDavid Hildenbrand &error_abort); 366316ee9980SDaniel Henrique Barboza uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 366416ee9980SDaniel Henrique Barboza uint32_t avail_lmbs = 0; 366516ee9980SDaniel Henrique Barboza uint64_t addr_start, addr; 366616ee9980SDaniel Henrique Barboza int i; 366716ee9980SDaniel Henrique Barboza 366816ee9980SDaniel Henrique Barboza addr_start = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, 366916ee9980SDaniel Henrique Barboza &error_abort); 367016ee9980SDaniel Henrique Barboza 367116ee9980SDaniel Henrique Barboza addr = addr_start; 367216ee9980SDaniel Henrique Barboza for (i = 0; i < nr_lmbs; i++) { 3673fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 367416ee9980SDaniel Henrique Barboza addr / SPAPR_MEMORY_BLOCK_SIZE); 367516ee9980SDaniel Henrique Barboza g_assert(drc); 3676454b580aSDavid Gibson if (drc->dev) { 367716ee9980SDaniel Henrique Barboza avail_lmbs++; 367816ee9980SDaniel Henrique Barboza } 367916ee9980SDaniel Henrique Barboza addr += SPAPR_MEMORY_BLOCK_SIZE; 368016ee9980SDaniel Henrique Barboza } 368116ee9980SDaniel Henrique Barboza 36828d5981c4SBharata B Rao return spapr_pending_dimm_unplugs_add(ms, avail_lmbs, dimm); 368316ee9980SDaniel Henrique Barboza } 368416ee9980SDaniel Henrique Barboza 368531834723SDaniel Henrique Barboza /* Callback to be called during DRC release. */ 368631834723SDaniel Henrique Barboza void spapr_lmb_release(DeviceState *dev) 3687cf632463SBharata B Rao { 36883ec71474SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3689ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl); 3690ce2918cbSDavid Gibson SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); 3691cf632463SBharata B Rao 369216ee9980SDaniel Henrique Barboza /* This information will get lost if a migration occurs 369316ee9980SDaniel Henrique Barboza * during the unplug process. In this case recover it. */ 369416ee9980SDaniel Henrique Barboza if (ds == NULL) { 369516ee9980SDaniel Henrique Barboza ds = spapr_recover_pending_dimm_state(spapr, PC_DIMM(dev)); 36968d5981c4SBharata B Rao g_assert(ds); 3697454b580aSDavid Gibson /* The DRC being examined by the caller at least must be counted */ 3698454b580aSDavid Gibson g_assert(ds->nr_lmbs); 369916ee9980SDaniel Henrique Barboza } 3700454b580aSDavid Gibson 3701454b580aSDavid Gibson if (--ds->nr_lmbs) { 3702cf632463SBharata B Rao return; 3703cf632463SBharata B Rao } 3704cf632463SBharata B Rao 3705cf632463SBharata B Rao /* 3706cf632463SBharata B Rao * Now that all the LMBs have been removed by the guest, call the 37073ec71474SDavid Hildenbrand * unplug handler chain. This can never fail. 3708cf632463SBharata B Rao */ 37093ec71474SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 371007578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 37113ec71474SDavid Hildenbrand } 37123ec71474SDavid Hildenbrand 37133ec71474SDavid Hildenbrand static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 37143ec71474SDavid Hildenbrand { 3715ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3716ce2918cbSDavid Gibson SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); 37173ec71474SDavid Hildenbrand 3718fd3416f5SDavid Hildenbrand pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev)); 371907578b0aSDavid Hildenbrand object_property_set_bool(OBJECT(dev), false, "realized", NULL); 37202a129767SDaniel Henrique Barboza spapr_pending_dimm_unplugs_remove(spapr, ds); 3721cf632463SBharata B Rao } 3722cf632463SBharata B Rao 3723cf632463SBharata B Rao static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, 3724cf632463SBharata B Rao DeviceState *dev, Error **errp) 3725cf632463SBharata B Rao { 3726ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3727cf632463SBharata B Rao Error *local_err = NULL; 3728cf632463SBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 372904790978SThomas Huth uint32_t nr_lmbs; 373004790978SThomas Huth uint64_t size, addr_start, addr; 37310cffce56SDavid Gibson int i; 3732ce2918cbSDavid Gibson SpaprDrc *drc; 373304790978SThomas Huth 3734946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &error_abort); 373504790978SThomas Huth nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 373604790978SThomas Huth 37379ed442b8SMarc-André Lureau addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, 37380cffce56SDavid Gibson &local_err); 3739cf632463SBharata B Rao if (local_err) { 3740cf632463SBharata B Rao goto out; 3741cf632463SBharata B Rao } 3742cf632463SBharata B Rao 37432a129767SDaniel Henrique Barboza /* 37442a129767SDaniel Henrique Barboza * An existing pending dimm state for this DIMM means that there is an 37452a129767SDaniel Henrique Barboza * unplug operation in progress, waiting for the spapr_lmb_release 37462a129767SDaniel Henrique Barboza * callback to complete the job (BQL can't cover that far). In this case, 37472a129767SDaniel Henrique Barboza * bail out to avoid detaching DRCs that were already released. 37482a129767SDaniel Henrique Barboza */ 37492a129767SDaniel Henrique Barboza if (spapr_pending_dimm_unplugs_find(spapr, dimm)) { 37502a129767SDaniel Henrique Barboza error_setg(&local_err, 37512a129767SDaniel Henrique Barboza "Memory unplug already in progress for device %s", 37522a129767SDaniel Henrique Barboza dev->id); 37532a129767SDaniel Henrique Barboza goto out; 37542a129767SDaniel Henrique Barboza } 37552a129767SDaniel Henrique Barboza 37568d5981c4SBharata B Rao spapr_pending_dimm_unplugs_add(spapr, nr_lmbs, dimm); 37570cffce56SDavid Gibson 37580cffce56SDavid Gibson addr = addr_start; 37590cffce56SDavid Gibson for (i = 0; i < nr_lmbs; i++) { 3760fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 37610cffce56SDavid Gibson addr / SPAPR_MEMORY_BLOCK_SIZE); 37620cffce56SDavid Gibson g_assert(drc); 37630cffce56SDavid Gibson 3764a8dc47fdSDavid Gibson spapr_drc_detach(drc); 37650cffce56SDavid Gibson addr += SPAPR_MEMORY_BLOCK_SIZE; 37660cffce56SDavid Gibson } 37670cffce56SDavid Gibson 3768fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 37690cffce56SDavid Gibson addr_start / SPAPR_MEMORY_BLOCK_SIZE); 37700cffce56SDavid Gibson spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 37710b55aa91SDavid Gibson nr_lmbs, spapr_drc_index(drc)); 3772cf632463SBharata B Rao out: 3773cf632463SBharata B Rao error_propagate(errp, local_err); 3774cf632463SBharata B Rao } 3775cf632463SBharata B Rao 3776765d1bddSDavid Gibson /* Callback to be called during DRC release. */ 3777765d1bddSDavid Gibson void spapr_core_release(DeviceState *dev) 3778ff9006ddSIgor Mammedov { 3779a4261be1SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3780a4261be1SDavid Hildenbrand 3781a4261be1SDavid Hildenbrand /* Call the unplug handler chain. This can never fail. */ 3782a4261be1SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 378307578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 3784a4261be1SDavid Hildenbrand } 3785a4261be1SDavid Hildenbrand 3786a4261be1SDavid Hildenbrand static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 3787a4261be1SDavid Hildenbrand { 3788a4261be1SDavid Hildenbrand MachineState *ms = MACHINE(hotplug_dev); 3789ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms); 3790ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3791535455fdSIgor Mammedov CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL); 3792ff9006ddSIgor Mammedov 379346f7afa3SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 3794ce2918cbSDavid Gibson SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); 379546f7afa3SGreg Kurz int i; 379646f7afa3SGreg Kurz 379746f7afa3SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 379894ad93bdSGreg Kurz CPUState *cs = CPU(sc->threads[i]); 379946f7afa3SGreg Kurz 380046f7afa3SGreg Kurz pre_2_10_vmstate_register_dummy_icp(cs->cpu_index); 380146f7afa3SGreg Kurz } 380246f7afa3SGreg Kurz } 380346f7afa3SGreg Kurz 380407572c06SGreg Kurz assert(core_slot); 3805535455fdSIgor Mammedov core_slot->cpu = NULL; 380607578b0aSDavid Hildenbrand object_property_set_bool(OBJECT(dev), false, "realized", NULL); 3807ff9006ddSIgor Mammedov } 3808ff9006ddSIgor Mammedov 3809115debf2SIgor Mammedov static 3810115debf2SIgor Mammedov void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, 3811ff9006ddSIgor Mammedov Error **errp) 3812ff9006ddSIgor Mammedov { 3813ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3814535455fdSIgor Mammedov int index; 3815ce2918cbSDavid Gibson SpaprDrc *drc; 3816535455fdSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3817ff9006ddSIgor Mammedov 3818535455fdSIgor Mammedov if (!spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index)) { 3819535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 3820535455fdSIgor Mammedov cc->core_id); 3821535455fdSIgor Mammedov return; 3822535455fdSIgor Mammedov } 3823ff9006ddSIgor Mammedov if (index == 0) { 3824ff9006ddSIgor Mammedov error_setg(errp, "Boot CPU core may not be unplugged"); 3825ff9006ddSIgor Mammedov return; 3826ff9006ddSIgor Mammedov } 3827ff9006ddSIgor Mammedov 38285d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 38295d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 3830ff9006ddSIgor Mammedov g_assert(drc); 3831ff9006ddSIgor Mammedov 3832a8dc47fdSDavid Gibson spapr_drc_detach(drc); 3833ff9006ddSIgor Mammedov 3834ff9006ddSIgor Mammedov spapr_hotplug_req_remove_by_index(drc); 3835ff9006ddSIgor Mammedov } 3836ff9006ddSIgor Mammedov 3837ce2918cbSDavid Gibson int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 3838345b12b9SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 3839345b12b9SGreg Kurz { 3840ce2918cbSDavid Gibson SpaprCpuCore *core = SPAPR_CPU_CORE(drc->dev); 3841345b12b9SGreg Kurz CPUState *cs = CPU(core->threads[0]); 3842345b12b9SGreg Kurz PowerPCCPU *cpu = POWERPC_CPU(cs); 3843345b12b9SGreg Kurz DeviceClass *dc = DEVICE_GET_CLASS(cs); 3844345b12b9SGreg Kurz int id = spapr_get_vcpu_id(cpu); 3845345b12b9SGreg Kurz char *nodename; 3846345b12b9SGreg Kurz int offset; 3847345b12b9SGreg Kurz 3848345b12b9SGreg Kurz nodename = g_strdup_printf("%s@%x", dc->fw_name, id); 3849345b12b9SGreg Kurz offset = fdt_add_subnode(fdt, 0, nodename); 3850345b12b9SGreg Kurz g_free(nodename); 3851345b12b9SGreg Kurz 3852345b12b9SGreg Kurz spapr_populate_cpu_dt(cs, fdt, offset, spapr); 3853345b12b9SGreg Kurz 3854345b12b9SGreg Kurz *fdt_start_offset = offset; 3855345b12b9SGreg Kurz return 0; 3856345b12b9SGreg Kurz } 3857345b12b9SGreg Kurz 3858ff9006ddSIgor Mammedov static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3859ff9006ddSIgor Mammedov Error **errp) 3860ff9006ddSIgor Mammedov { 3861ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3862ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(spapr); 3863ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 3864ce2918cbSDavid Gibson SpaprCpuCore *core = SPAPR_CPU_CORE(OBJECT(dev)); 3865ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3866345b12b9SGreg Kurz CPUState *cs; 3867ce2918cbSDavid Gibson SpaprDrc *drc; 3868ff9006ddSIgor Mammedov Error *local_err = NULL; 3869535455fdSIgor Mammedov CPUArchId *core_slot; 3870535455fdSIgor Mammedov int index; 387194fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 3872b1e81567SGreg Kurz int i; 3873ff9006ddSIgor Mammedov 3874535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 3875535455fdSIgor Mammedov if (!core_slot) { 3876535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 3877535455fdSIgor Mammedov cc->core_id); 3878535455fdSIgor Mammedov return; 3879535455fdSIgor Mammedov } 38805d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 38815d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 3882ff9006ddSIgor Mammedov 3883c5514d0eSIgor Mammedov g_assert(drc || !mc->has_hotpluggable_cpus); 3884ff9006ddSIgor Mammedov 3885e49c63d5SGreg Kurz if (drc) { 388609d876ceSGreg Kurz spapr_drc_attach(drc, dev, &local_err); 3887ff9006ddSIgor Mammedov if (local_err) { 3888ff9006ddSIgor Mammedov error_propagate(errp, local_err); 3889ff9006ddSIgor Mammedov return; 3890ff9006ddSIgor Mammedov } 3891ff9006ddSIgor Mammedov 389294fd9cbaSLaurent Vivier if (hotplugged) { 3893ff9006ddSIgor Mammedov /* 389494fd9cbaSLaurent Vivier * Send hotplug notification interrupt to the guest only 389594fd9cbaSLaurent Vivier * in case of hotplugged CPUs. 3896ff9006ddSIgor Mammedov */ 3897ff9006ddSIgor Mammedov spapr_hotplug_req_add_by_index(drc); 389894fd9cbaSLaurent Vivier } else { 389994fd9cbaSLaurent Vivier spapr_drc_reset(drc); 3900ff9006ddSIgor Mammedov } 390194fd9cbaSLaurent Vivier } 390294fd9cbaSLaurent Vivier 3903535455fdSIgor Mammedov core_slot->cpu = OBJECT(dev); 390446f7afa3SGreg Kurz 390546f7afa3SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 390646f7afa3SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 3907bc877283SGreg Kurz cs = CPU(core->threads[i]); 390846f7afa3SGreg Kurz pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index); 390946f7afa3SGreg Kurz } 391046f7afa3SGreg Kurz } 3911b1e81567SGreg Kurz 3912b1e81567SGreg Kurz /* 3913b1e81567SGreg Kurz * Set compatibility mode to match the boot CPU, which was either set 3914b1e81567SGreg Kurz * by the machine reset code or by CAS. 3915b1e81567SGreg Kurz */ 3916b1e81567SGreg Kurz if (hotplugged) { 3917b1e81567SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 3918b1e81567SGreg Kurz ppc_set_compat(core->threads[i], POWERPC_CPU(first_cpu)->compat_pvr, 3919b1e81567SGreg Kurz &local_err); 3920b1e81567SGreg Kurz if (local_err) { 3921b1e81567SGreg Kurz error_propagate(errp, local_err); 3922b1e81567SGreg Kurz return; 3923b1e81567SGreg Kurz } 3924b1e81567SGreg Kurz } 3925b1e81567SGreg Kurz } 3926ff9006ddSIgor Mammedov } 3927ff9006ddSIgor Mammedov 3928ff9006ddSIgor Mammedov static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3929ff9006ddSIgor Mammedov Error **errp) 3930ff9006ddSIgor Mammedov { 3931ff9006ddSIgor Mammedov MachineState *machine = MACHINE(OBJECT(hotplug_dev)); 3932ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); 3933ff9006ddSIgor Mammedov Error *local_err = NULL; 3934ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 39352e9c10ebSIgor Mammedov const char *base_core_type = spapr_get_cpu_core_type(machine->cpu_type); 3936ff9006ddSIgor Mammedov const char *type = object_get_typename(OBJECT(dev)); 3937535455fdSIgor Mammedov CPUArchId *core_slot; 3938535455fdSIgor Mammedov int index; 3939fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 3940ff9006ddSIgor Mammedov 3941c5514d0eSIgor Mammedov if (dev->hotplugged && !mc->has_hotpluggable_cpus) { 3942ff9006ddSIgor Mammedov error_setg(&local_err, "CPU hotplug not supported for this machine"); 3943ff9006ddSIgor Mammedov goto out; 3944ff9006ddSIgor Mammedov } 3945ff9006ddSIgor Mammedov 3946ff9006ddSIgor Mammedov if (strcmp(base_core_type, type)) { 3947ff9006ddSIgor Mammedov error_setg(&local_err, "CPU core type should be %s", base_core_type); 3948ff9006ddSIgor Mammedov goto out; 3949ff9006ddSIgor Mammedov } 3950ff9006ddSIgor Mammedov 3951ff9006ddSIgor Mammedov if (cc->core_id % smp_threads) { 3952ff9006ddSIgor Mammedov error_setg(&local_err, "invalid core id %d", cc->core_id); 3953ff9006ddSIgor Mammedov goto out; 3954ff9006ddSIgor Mammedov } 3955ff9006ddSIgor Mammedov 3956459264efSDavid Gibson /* 3957459264efSDavid Gibson * In general we should have homogeneous threads-per-core, but old 3958459264efSDavid Gibson * (pre hotplug support) machine types allow the last core to have 3959459264efSDavid Gibson * reduced threads as a compatibility hack for when we allowed 3960459264efSDavid Gibson * total vcpus not a multiple of threads-per-core. 3961459264efSDavid Gibson */ 3962459264efSDavid Gibson if (mc->has_hotpluggable_cpus && (cc->nr_threads != smp_threads)) { 3963df8658deSGreg Kurz error_setg(&local_err, "invalid nr-threads %d, must be %d", 39648149e299SDavid Gibson cc->nr_threads, smp_threads); 3965df8658deSGreg Kurz goto out; 39668149e299SDavid Gibson } 39678149e299SDavid Gibson 3968535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 3969535455fdSIgor Mammedov if (!core_slot) { 3970ff9006ddSIgor Mammedov error_setg(&local_err, "core id %d out of range", cc->core_id); 3971ff9006ddSIgor Mammedov goto out; 3972ff9006ddSIgor Mammedov } 3973ff9006ddSIgor Mammedov 3974535455fdSIgor Mammedov if (core_slot->cpu) { 3975ff9006ddSIgor Mammedov error_setg(&local_err, "core %d already populated", cc->core_id); 3976ff9006ddSIgor Mammedov goto out; 3977ff9006ddSIgor Mammedov } 3978ff9006ddSIgor Mammedov 3979a0ceb640SIgor Mammedov numa_cpu_pre_plug(core_slot, dev, &local_err); 39800b8497f0SIgor Mammedov 3981ff9006ddSIgor Mammedov out: 3982ff9006ddSIgor Mammedov error_propagate(errp, local_err); 3983ff9006ddSIgor Mammedov } 3984ff9006ddSIgor Mammedov 3985ce2918cbSDavid Gibson int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 3986bb2bdd81SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 3987bb2bdd81SGreg Kurz { 3988ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(drc->dev); 3989bb2bdd81SGreg Kurz int intc_phandle; 3990bb2bdd81SGreg Kurz 3991bb2bdd81SGreg Kurz intc_phandle = spapr_irq_get_phandle(spapr, spapr->fdt_blob, errp); 3992bb2bdd81SGreg Kurz if (intc_phandle <= 0) { 3993bb2bdd81SGreg Kurz return -1; 3994bb2bdd81SGreg Kurz } 3995bb2bdd81SGreg Kurz 3996466e8831SDavid Gibson if (spapr_dt_phb(sphb, intc_phandle, fdt, spapr->irq->nr_msis, 3997bb2bdd81SGreg Kurz fdt_start_offset)) { 3998bb2bdd81SGreg Kurz error_setg(errp, "unable to create FDT node for PHB %d", sphb->index); 3999bb2bdd81SGreg Kurz return -1; 4000bb2bdd81SGreg Kurz } 4001bb2bdd81SGreg Kurz 4002bb2bdd81SGreg Kurz /* generally SLOF creates these, for hotplug it's up to QEMU */ 4003bb2bdd81SGreg Kurz _FDT(fdt_setprop_string(fdt, *fdt_start_offset, "name", "pci")); 4004bb2bdd81SGreg Kurz 4005bb2bdd81SGreg Kurz return 0; 4006bb2bdd81SGreg Kurz } 4007bb2bdd81SGreg Kurz 4008bb2bdd81SGreg Kurz static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 4009bb2bdd81SGreg Kurz Error **errp) 4010bb2bdd81SGreg Kurz { 4011ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 4012ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 4013ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 4014bb2bdd81SGreg Kurz const unsigned windows_supported = spapr_phb_windows_supported(sphb); 4015bb2bdd81SGreg Kurz 4016bb2bdd81SGreg Kurz if (dev->hotplugged && !smc->dr_phb_enabled) { 4017bb2bdd81SGreg Kurz error_setg(errp, "PHB hotplug not supported for this machine"); 4018bb2bdd81SGreg Kurz return; 4019bb2bdd81SGreg Kurz } 4020bb2bdd81SGreg Kurz 4021bb2bdd81SGreg Kurz if (sphb->index == (uint32_t)-1) { 4022bb2bdd81SGreg Kurz error_setg(errp, "\"index\" for PAPR PHB is mandatory"); 4023bb2bdd81SGreg Kurz return; 4024bb2bdd81SGreg Kurz } 4025bb2bdd81SGreg Kurz 4026bb2bdd81SGreg Kurz /* 4027bb2bdd81SGreg Kurz * This will check that sphb->index doesn't exceed the maximum number of 4028bb2bdd81SGreg Kurz * PHBs for the current machine type. 4029bb2bdd81SGreg Kurz */ 4030bb2bdd81SGreg Kurz smc->phb_placement(spapr, sphb->index, 4031bb2bdd81SGreg Kurz &sphb->buid, &sphb->io_win_addr, 4032bb2bdd81SGreg Kurz &sphb->mem_win_addr, &sphb->mem64_win_addr, 4033ec132efaSAlexey Kardashevskiy windows_supported, sphb->dma_liobn, 4034ec132efaSAlexey Kardashevskiy &sphb->nv2_gpa_win_addr, &sphb->nv2_atsd_win_addr, 4035ec132efaSAlexey Kardashevskiy errp); 4036bb2bdd81SGreg Kurz } 4037bb2bdd81SGreg Kurz 4038bb2bdd81SGreg Kurz static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 4039bb2bdd81SGreg Kurz Error **errp) 4040bb2bdd81SGreg Kurz { 4041ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 4042ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 4043ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 4044ce2918cbSDavid Gibson SpaprDrc *drc; 4045bb2bdd81SGreg Kurz bool hotplugged = spapr_drc_hotplugged(dev); 4046bb2bdd81SGreg Kurz Error *local_err = NULL; 4047bb2bdd81SGreg Kurz 4048bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) { 4049bb2bdd81SGreg Kurz return; 4050bb2bdd81SGreg Kurz } 4051bb2bdd81SGreg Kurz 4052bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); 4053bb2bdd81SGreg Kurz /* hotplug hooks should check it's enabled before getting this far */ 4054bb2bdd81SGreg Kurz assert(drc); 4055bb2bdd81SGreg Kurz 4056bb2bdd81SGreg Kurz spapr_drc_attach(drc, DEVICE(dev), &local_err); 4057bb2bdd81SGreg Kurz if (local_err) { 4058bb2bdd81SGreg Kurz error_propagate(errp, local_err); 4059bb2bdd81SGreg Kurz return; 4060bb2bdd81SGreg Kurz } 4061bb2bdd81SGreg Kurz 4062bb2bdd81SGreg Kurz if (hotplugged) { 4063bb2bdd81SGreg Kurz spapr_hotplug_req_add_by_index(drc); 4064bb2bdd81SGreg Kurz } else { 4065bb2bdd81SGreg Kurz spapr_drc_reset(drc); 4066bb2bdd81SGreg Kurz } 4067bb2bdd81SGreg Kurz } 4068bb2bdd81SGreg Kurz 4069bb2bdd81SGreg Kurz void spapr_phb_release(DeviceState *dev) 4070bb2bdd81SGreg Kurz { 4071bb2bdd81SGreg Kurz HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 4072bb2bdd81SGreg Kurz 4073bb2bdd81SGreg Kurz hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 407407578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 4075bb2bdd81SGreg Kurz } 4076bb2bdd81SGreg Kurz 4077bb2bdd81SGreg Kurz static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 4078bb2bdd81SGreg Kurz { 407907578b0aSDavid Hildenbrand object_property_set_bool(OBJECT(dev), false, "realized", NULL); 4080bb2bdd81SGreg Kurz } 4081bb2bdd81SGreg Kurz 4082bb2bdd81SGreg Kurz static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev, 4083bb2bdd81SGreg Kurz DeviceState *dev, Error **errp) 4084bb2bdd81SGreg Kurz { 4085ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 4086ce2918cbSDavid Gibson SpaprDrc *drc; 4087bb2bdd81SGreg Kurz 4088bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); 4089bb2bdd81SGreg Kurz assert(drc); 4090bb2bdd81SGreg Kurz 4091bb2bdd81SGreg Kurz if (!spapr_drc_unplug_requested(drc)) { 4092bb2bdd81SGreg Kurz spapr_drc_detach(drc); 4093bb2bdd81SGreg Kurz spapr_hotplug_req_remove_by_index(drc); 4094bb2bdd81SGreg Kurz } 4095bb2bdd81SGreg Kurz } 4096bb2bdd81SGreg Kurz 40970fb6bd07SMichael Roth static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 40980fb6bd07SMichael Roth Error **errp) 40990fb6bd07SMichael Roth { 41000fb6bd07SMichael Roth SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 41010fb6bd07SMichael Roth SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(dev); 41020fb6bd07SMichael Roth 41030fb6bd07SMichael Roth if (spapr->tpm_proxy != NULL) { 41040fb6bd07SMichael Roth error_setg(errp, "Only one TPM proxy can be specified for this machine"); 41050fb6bd07SMichael Roth return; 41060fb6bd07SMichael Roth } 41070fb6bd07SMichael Roth 41080fb6bd07SMichael Roth spapr->tpm_proxy = tpm_proxy; 41090fb6bd07SMichael Roth } 41100fb6bd07SMichael Roth 41110fb6bd07SMichael Roth static void spapr_tpm_proxy_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 41120fb6bd07SMichael Roth { 41130fb6bd07SMichael Roth SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 41140fb6bd07SMichael Roth 41150fb6bd07SMichael Roth object_property_set_bool(OBJECT(dev), false, "realized", NULL); 41160fb6bd07SMichael Roth object_unparent(OBJECT(dev)); 41170fb6bd07SMichael Roth spapr->tpm_proxy = NULL; 41180fb6bd07SMichael Roth } 41190fb6bd07SMichael Roth 4120c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, 4121c20d332aSBharata B Rao DeviceState *dev, Error **errp) 4122c20d332aSBharata B Rao { 4123c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 412481985f3bSDavid Hildenbrand spapr_memory_plug(hotplug_dev, dev, errp); 4125af81cf32SBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4126af81cf32SBharata B Rao spapr_core_plug(hotplug_dev, dev, errp); 4127bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4128bb2bdd81SGreg Kurz spapr_phb_plug(hotplug_dev, dev, errp); 41290fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 41300fb6bd07SMichael Roth spapr_tpm_proxy_plug(hotplug_dev, dev, errp); 4131c20d332aSBharata B Rao } 4132c20d332aSBharata B Rao } 4133c20d332aSBharata B Rao 413488432f44SDavid Hildenbrand static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, 413588432f44SDavid Hildenbrand DeviceState *dev, Error **errp) 413688432f44SDavid Hildenbrand { 41373ec71474SDavid Hildenbrand if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 41383ec71474SDavid Hildenbrand spapr_memory_unplug(hotplug_dev, dev); 4139a4261be1SDavid Hildenbrand } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4140a4261be1SDavid Hildenbrand spapr_core_unplug(hotplug_dev, dev); 4141bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4142bb2bdd81SGreg Kurz spapr_phb_unplug(hotplug_dev, dev); 41430fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 41440fb6bd07SMichael Roth spapr_tpm_proxy_unplug(hotplug_dev, dev); 41453ec71474SDavid Hildenbrand } 414688432f44SDavid Hildenbrand } 414788432f44SDavid Hildenbrand 4148cf632463SBharata B Rao static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev, 4149cf632463SBharata B Rao DeviceState *dev, Error **errp) 4150cf632463SBharata B Rao { 4151ce2918cbSDavid Gibson SpaprMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev)); 4152c86c1affSDaniel Henrique Barboza MachineClass *mc = MACHINE_GET_CLASS(sms); 4153ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4154cf632463SBharata B Rao 4155cf632463SBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 4156cf632463SBharata B Rao if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) { 4157cf632463SBharata B Rao spapr_memory_unplug_request(hotplug_dev, dev, errp); 4158cf632463SBharata B Rao } else { 4159cf632463SBharata B Rao /* NOTE: this means there is a window after guest reset, prior to 4160cf632463SBharata B Rao * CAS negotiation, where unplug requests will fail due to the 4161cf632463SBharata B Rao * capability not being detected yet. This is a bit different than 4162cf632463SBharata B Rao * the case with PCI unplug, where the events will be queued and 4163cf632463SBharata B Rao * eventually handled by the guest after boot 4164cf632463SBharata B Rao */ 4165cf632463SBharata B Rao error_setg(errp, "Memory hot unplug not supported for this guest"); 4166cf632463SBharata B Rao } 41676f4b5c3eSBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4168c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 41696f4b5c3eSBharata B Rao error_setg(errp, "CPU hot unplug not supported on this machine"); 41706f4b5c3eSBharata B Rao return; 41716f4b5c3eSBharata B Rao } 4172115debf2SIgor Mammedov spapr_core_unplug_request(hotplug_dev, dev, errp); 4173bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4174bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) { 4175bb2bdd81SGreg Kurz error_setg(errp, "PHB hot unplug not supported on this machine"); 4176bb2bdd81SGreg Kurz return; 4177bb2bdd81SGreg Kurz } 4178bb2bdd81SGreg Kurz spapr_phb_unplug_request(hotplug_dev, dev, errp); 41790fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 41800fb6bd07SMichael Roth spapr_tpm_proxy_unplug(hotplug_dev, dev); 4181c20d332aSBharata B Rao } 4182c20d332aSBharata B Rao } 4183c20d332aSBharata B Rao 418494a94e4cSBharata B Rao static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, 418594a94e4cSBharata B Rao DeviceState *dev, Error **errp) 418694a94e4cSBharata B Rao { 4187c871bc70SLaurent Vivier if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 4188c871bc70SLaurent Vivier spapr_memory_pre_plug(hotplug_dev, dev, errp); 4189c871bc70SLaurent Vivier } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 419094a94e4cSBharata B Rao spapr_core_pre_plug(hotplug_dev, dev, errp); 4191bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4192bb2bdd81SGreg Kurz spapr_phb_pre_plug(hotplug_dev, dev, errp); 419394a94e4cSBharata B Rao } 419494a94e4cSBharata B Rao } 419594a94e4cSBharata B Rao 41967ebaf795SBharata B Rao static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine, 4197c20d332aSBharata B Rao DeviceState *dev) 4198c20d332aSBharata B Rao { 419994a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || 4200bb2bdd81SGreg Kurz object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE) || 42010fb6bd07SMichael Roth object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE) || 42020fb6bd07SMichael Roth object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 4203c20d332aSBharata B Rao return HOTPLUG_HANDLER(machine); 4204c20d332aSBharata B Rao } 4205cb600087SDavid Gibson if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { 4206cb600087SDavid Gibson PCIDevice *pcidev = PCI_DEVICE(dev); 4207cb600087SDavid Gibson PCIBus *root = pci_device_root_bus(pcidev); 4208cb600087SDavid Gibson SpaprPhbState *phb = 4209cb600087SDavid Gibson (SpaprPhbState *)object_dynamic_cast(OBJECT(BUS(root)->parent), 4210cb600087SDavid Gibson TYPE_SPAPR_PCI_HOST_BRIDGE); 4211cb600087SDavid Gibson 4212cb600087SDavid Gibson if (phb) { 4213cb600087SDavid Gibson return HOTPLUG_HANDLER(phb); 4214cb600087SDavid Gibson } 4215cb600087SDavid Gibson } 4216c20d332aSBharata B Rao return NULL; 4217c20d332aSBharata B Rao } 4218c20d332aSBharata B Rao 4219ea089eebSIgor Mammedov static CpuInstanceProperties 4220ea089eebSIgor Mammedov spapr_cpu_index_to_props(MachineState *machine, unsigned cpu_index) 422120bb648dSDavid Gibson { 4222ea089eebSIgor Mammedov CPUArchId *core_slot; 4223ea089eebSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 4224ea089eebSIgor Mammedov 4225ea089eebSIgor Mammedov /* make sure possible_cpu are intialized */ 4226ea089eebSIgor Mammedov mc->possible_cpu_arch_ids(machine); 4227ea089eebSIgor Mammedov /* get CPU core slot containing thread that matches cpu_index */ 4228ea089eebSIgor Mammedov core_slot = spapr_find_cpu_slot(machine, cpu_index, NULL); 4229ea089eebSIgor Mammedov assert(core_slot); 4230ea089eebSIgor Mammedov return core_slot->props; 423120bb648dSDavid Gibson } 423220bb648dSDavid Gibson 423379e07936SIgor Mammedov static int64_t spapr_get_default_cpu_node_id(const MachineState *ms, int idx) 423479e07936SIgor Mammedov { 4235aa570207STao Xu return idx / ms->smp.cores % ms->numa_state->num_nodes; 423679e07936SIgor Mammedov } 423779e07936SIgor Mammedov 4238535455fdSIgor Mammedov static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine) 4239535455fdSIgor Mammedov { 4240535455fdSIgor Mammedov int i; 4241fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 4242fe6b6346SLike Xu unsigned int smp_cpus = machine->smp.cpus; 4243d342eb76SIgor Mammedov const char *core_type; 4244fe6b6346SLike Xu int spapr_max_cores = machine->smp.max_cpus / smp_threads; 4245535455fdSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 4246535455fdSIgor Mammedov 4247c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 4248535455fdSIgor Mammedov spapr_max_cores = QEMU_ALIGN_UP(smp_cpus, smp_threads) / smp_threads; 4249535455fdSIgor Mammedov } 4250535455fdSIgor Mammedov if (machine->possible_cpus) { 4251535455fdSIgor Mammedov assert(machine->possible_cpus->len == spapr_max_cores); 4252535455fdSIgor Mammedov return machine->possible_cpus; 4253535455fdSIgor Mammedov } 4254535455fdSIgor Mammedov 4255d342eb76SIgor Mammedov core_type = spapr_get_cpu_core_type(machine->cpu_type); 4256d342eb76SIgor Mammedov if (!core_type) { 4257d342eb76SIgor Mammedov error_report("Unable to find sPAPR CPU Core definition"); 4258d342eb76SIgor Mammedov exit(1); 4259d342eb76SIgor Mammedov } 4260d342eb76SIgor Mammedov 4261535455fdSIgor Mammedov machine->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + 4262535455fdSIgor Mammedov sizeof(CPUArchId) * spapr_max_cores); 4263535455fdSIgor Mammedov machine->possible_cpus->len = spapr_max_cores; 4264535455fdSIgor Mammedov for (i = 0; i < machine->possible_cpus->len; i++) { 4265535455fdSIgor Mammedov int core_id = i * smp_threads; 4266535455fdSIgor Mammedov 4267d342eb76SIgor Mammedov machine->possible_cpus->cpus[i].type = core_type; 4268f2d672c2SIgor Mammedov machine->possible_cpus->cpus[i].vcpus_count = smp_threads; 4269535455fdSIgor Mammedov machine->possible_cpus->cpus[i].arch_id = core_id; 4270535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.has_core_id = true; 4271535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.core_id = core_id; 4272535455fdSIgor Mammedov } 4273535455fdSIgor Mammedov return machine->possible_cpus; 4274535455fdSIgor Mammedov } 4275535455fdSIgor Mammedov 4276ce2918cbSDavid Gibson static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index, 4277daa23699SDavid Gibson uint64_t *buid, hwaddr *pio, 4278daa23699SDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 4279ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4280ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 42816737d9adSDavid Gibson { 4282357d1e3bSDavid Gibson /* 4283357d1e3bSDavid Gibson * New-style PHB window placement. 4284357d1e3bSDavid Gibson * 4285357d1e3bSDavid Gibson * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window 4286357d1e3bSDavid Gibson * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO 4287357d1e3bSDavid Gibson * windows. 4288357d1e3bSDavid Gibson * 4289357d1e3bSDavid Gibson * Some guest kernels can't work with MMIO windows above 1<<46 4290357d1e3bSDavid Gibson * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB 4291357d1e3bSDavid Gibson * 4292357d1e3bSDavid Gibson * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each 4293357d1e3bSDavid Gibson * PHB stacked together. (32TiB+2GiB)..(32TiB+64GiB) contains the 4294357d1e3bSDavid Gibson * 2GiB 32-bit MMIO windows for each PHB. Then 33..64TiB has the 4295357d1e3bSDavid Gibson * 1TiB 64-bit MMIO windows for each PHB. 4296357d1e3bSDavid Gibson */ 42976737d9adSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 42986737d9adSDavid Gibson int i; 42996737d9adSDavid Gibson 4300357d1e3bSDavid Gibson /* Sanity check natural alignments */ 4301357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 4302357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 4303357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0); 4304357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0); 4305357d1e3bSDavid Gibson /* Sanity check bounds */ 430625e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_IO_WIN_SIZE) > 430725e6a118SMichael S. Tsirkin SPAPR_PCI_MEM32_WIN_SIZE); 430825e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_MEM32_WIN_SIZE) > 430925e6a118SMichael S. Tsirkin SPAPR_PCI_MEM64_WIN_SIZE); 43102efff1c0SDavid Gibson 431125e6a118SMichael S. Tsirkin if (index >= SPAPR_MAX_PHBS) { 431225e6a118SMichael S. Tsirkin error_setg(errp, "\"index\" for PAPR PHB is too large (max %llu)", 431325e6a118SMichael S. Tsirkin SPAPR_MAX_PHBS - 1); 43146737d9adSDavid Gibson return; 43156737d9adSDavid Gibson } 43166737d9adSDavid Gibson 43176737d9adSDavid Gibson *buid = base_buid + index; 43186737d9adSDavid Gibson for (i = 0; i < n_dma; ++i) { 43196737d9adSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 43206737d9adSDavid Gibson } 43216737d9adSDavid Gibson 4322357d1e3bSDavid Gibson *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE; 4323357d1e3bSDavid Gibson *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE; 4324357d1e3bSDavid Gibson *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE; 4325ec132efaSAlexey Kardashevskiy 4326ec132efaSAlexey Kardashevskiy *nv2gpa = SPAPR_PCI_NV2RAM64_WIN_BASE + index * SPAPR_PCI_NV2RAM64_WIN_SIZE; 4327ec132efaSAlexey Kardashevskiy *nv2atsd = SPAPR_PCI_NV2ATSD_WIN_BASE + index * SPAPR_PCI_NV2ATSD_WIN_SIZE; 43286737d9adSDavid Gibson } 43296737d9adSDavid Gibson 43307844e12bSCédric Le Goater static ICSState *spapr_ics_get(XICSFabric *dev, int irq) 43317844e12bSCédric Le Goater { 4332ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(dev); 43337844e12bSCédric Le Goater 43347844e12bSCédric Le Goater return ics_valid_irq(spapr->ics, irq) ? spapr->ics : NULL; 43357844e12bSCédric Le Goater } 43367844e12bSCédric Le Goater 43377844e12bSCédric Le Goater static void spapr_ics_resend(XICSFabric *dev) 43387844e12bSCédric Le Goater { 4339ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(dev); 43407844e12bSCédric Le Goater 43417844e12bSCédric Le Goater ics_resend(spapr->ics); 43427844e12bSCédric Le Goater } 43437844e12bSCédric Le Goater 434481210c20SSam Bobroff static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id) 4345b2fc59aaSCédric Le Goater { 43462e886fb3SSam Bobroff PowerPCCPU *cpu = spapr_find_cpu(vcpu_id); 4347b2fc59aaSCédric Le Goater 4348a28b9a5aSCédric Le Goater return cpu ? spapr_cpu_state(cpu)->icp : NULL; 4349b2fc59aaSCédric Le Goater } 4350b2fc59aaSCédric Le Goater 43516449da45SCédric Le Goater static void spapr_pic_print_info(InterruptStatsProvider *obj, 43526449da45SCédric Le Goater Monitor *mon) 43536449da45SCédric Le Goater { 4354ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 43556449da45SCédric Le Goater 43563ba3d0bcSCédric Le Goater spapr->irq->print_info(spapr, mon); 43576449da45SCédric Le Goater } 43586449da45SCédric Le Goater 435914bb4486SGreg Kurz int spapr_get_vcpu_id(PowerPCCPU *cpu) 43602e886fb3SSam Bobroff { 4361b1a568c1SGreg Kurz return cpu->vcpu_id; 43622e886fb3SSam Bobroff } 43632e886fb3SSam Bobroff 4364648edb64SGreg Kurz void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp) 4365648edb64SGreg Kurz { 4366ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 4367fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 4368648edb64SGreg Kurz int vcpu_id; 4369648edb64SGreg Kurz 43705d0fb150SGreg Kurz vcpu_id = spapr_vcpu_id(spapr, cpu_index); 4371648edb64SGreg Kurz 4372648edb64SGreg Kurz if (kvm_enabled() && !kvm_vcpu_id_is_valid(vcpu_id)) { 4373648edb64SGreg Kurz error_setg(errp, "Can't create CPU with id %d in KVM", vcpu_id); 4374648edb64SGreg Kurz error_append_hint(errp, "Adjust the number of cpus to %d " 4375648edb64SGreg Kurz "or try to raise the number of threads per core\n", 4376fe6b6346SLike Xu vcpu_id * ms->smp.threads / spapr->vsmt); 4377648edb64SGreg Kurz return; 4378648edb64SGreg Kurz } 4379648edb64SGreg Kurz 4380648edb64SGreg Kurz cpu->vcpu_id = vcpu_id; 4381648edb64SGreg Kurz } 4382648edb64SGreg Kurz 43832e886fb3SSam Bobroff PowerPCCPU *spapr_find_cpu(int vcpu_id) 43842e886fb3SSam Bobroff { 43852e886fb3SSam Bobroff CPUState *cs; 43862e886fb3SSam Bobroff 43872e886fb3SSam Bobroff CPU_FOREACH(cs) { 43882e886fb3SSam Bobroff PowerPCCPU *cpu = POWERPC_CPU(cs); 43892e886fb3SSam Bobroff 439014bb4486SGreg Kurz if (spapr_get_vcpu_id(cpu) == vcpu_id) { 43912e886fb3SSam Bobroff return cpu; 43922e886fb3SSam Bobroff } 43932e886fb3SSam Bobroff } 43942e886fb3SSam Bobroff 43952e886fb3SSam Bobroff return NULL; 43962e886fb3SSam Bobroff } 43972e886fb3SSam Bobroff 439803ef074cSNicholas Piggin static void spapr_cpu_exec_enter(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) 439903ef074cSNicholas Piggin { 440003ef074cSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 440103ef074cSNicholas Piggin 440203ef074cSNicholas Piggin /* These are only called by TCG, KVM maintains dispatch state */ 440303ef074cSNicholas Piggin 44043a6e6224SNicholas Piggin spapr_cpu->prod = false; 440503ef074cSNicholas Piggin if (spapr_cpu->vpa_addr) { 440603ef074cSNicholas Piggin CPUState *cs = CPU(cpu); 440703ef074cSNicholas Piggin uint32_t dispatch; 440803ef074cSNicholas Piggin 440903ef074cSNicholas Piggin dispatch = ldl_be_phys(cs->as, 441003ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER); 441103ef074cSNicholas Piggin dispatch++; 441203ef074cSNicholas Piggin if ((dispatch & 1) != 0) { 441303ef074cSNicholas Piggin qemu_log_mask(LOG_GUEST_ERROR, 441403ef074cSNicholas Piggin "VPA: incorrect dispatch counter value for " 441503ef074cSNicholas Piggin "dispatched partition %u, correcting.\n", dispatch); 441603ef074cSNicholas Piggin dispatch++; 441703ef074cSNicholas Piggin } 441803ef074cSNicholas Piggin stl_be_phys(cs->as, 441903ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch); 442003ef074cSNicholas Piggin } 442103ef074cSNicholas Piggin } 442203ef074cSNicholas Piggin 442303ef074cSNicholas Piggin static void spapr_cpu_exec_exit(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) 442403ef074cSNicholas Piggin { 442503ef074cSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 442603ef074cSNicholas Piggin 442703ef074cSNicholas Piggin if (spapr_cpu->vpa_addr) { 442803ef074cSNicholas Piggin CPUState *cs = CPU(cpu); 442903ef074cSNicholas Piggin uint32_t dispatch; 443003ef074cSNicholas Piggin 443103ef074cSNicholas Piggin dispatch = ldl_be_phys(cs->as, 443203ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER); 443303ef074cSNicholas Piggin dispatch++; 443403ef074cSNicholas Piggin if ((dispatch & 1) != 1) { 443503ef074cSNicholas Piggin qemu_log_mask(LOG_GUEST_ERROR, 443603ef074cSNicholas Piggin "VPA: incorrect dispatch counter value for " 443703ef074cSNicholas Piggin "preempted partition %u, correcting.\n", dispatch); 443803ef074cSNicholas Piggin dispatch++; 443903ef074cSNicholas Piggin } 444003ef074cSNicholas Piggin stl_be_phys(cs->as, 444103ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch); 444203ef074cSNicholas Piggin } 444303ef074cSNicholas Piggin } 444403ef074cSNicholas Piggin 444529ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data) 444653018216SPaolo Bonzini { 444729ee3247SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 4448ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(oc); 444971461b0fSAlexey Kardashevskiy FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); 445034316482SAlexey Kardashevskiy NMIClass *nc = NMI_CLASS(oc); 4451c20d332aSBharata B Rao HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); 44521d1be34dSDavid Gibson PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc); 44537844e12bSCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 44546449da45SCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 445529ee3247SAlexey Kardashevskiy 44560eb9054cSDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant)"; 4457907aac2fSMark Cave-Ayland mc->ignore_boot_device_suffixes = true; 4458fc9f38c3SDavid Gibson 4459fc9f38c3SDavid Gibson /* 4460fc9f38c3SDavid Gibson * We set up the default / latest behaviour here. The class_init 4461fc9f38c3SDavid Gibson * functions for the specific versioned machine types can override 4462fc9f38c3SDavid Gibson * these details for backwards compatibility 4463fc9f38c3SDavid Gibson */ 4464bcb5ce08SDavid Gibson mc->init = spapr_machine_init; 4465bcb5ce08SDavid Gibson mc->reset = spapr_machine_reset; 4466958db90cSMarcel Apfelbaum mc->block_default_type = IF_SCSI; 44676244bb7eSGreg Kurz mc->max_cpus = 1024; 4468958db90cSMarcel Apfelbaum mc->no_parallel = 1; 44695b2128d2SAlexander Graf mc->default_boot_order = ""; 4470d23b6caaSPhilippe Mathieu-Daudé mc->default_ram_size = 512 * MiB; 447129f9cef3SSebastian Bauer mc->default_display = "std"; 4472958db90cSMarcel Apfelbaum mc->kvm_type = spapr_kvm_type; 44737da79a16SEduardo Habkost machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SPAPR_PCI_HOST_BRIDGE); 4474e4024630SLaurent Vivier mc->pci_allow_0_address = true; 4475debbdc00SIgor Mammedov assert(!mc->get_hotplug_handler); 44767ebaf795SBharata B Rao mc->get_hotplug_handler = spapr_get_hotplug_handler; 447794a94e4cSBharata B Rao hc->pre_plug = spapr_machine_device_pre_plug; 4478c20d332aSBharata B Rao hc->plug = spapr_machine_device_plug; 4479ea089eebSIgor Mammedov mc->cpu_index_to_instance_props = spapr_cpu_index_to_props; 448079e07936SIgor Mammedov mc->get_default_cpu_node_id = spapr_get_default_cpu_node_id; 4481535455fdSIgor Mammedov mc->possible_cpu_arch_ids = spapr_possible_cpu_arch_ids; 4482cf632463SBharata B Rao hc->unplug_request = spapr_machine_device_unplug_request; 448388432f44SDavid Hildenbrand hc->unplug = spapr_machine_device_unplug; 448400b4fbe2SMarcel Apfelbaum 4485fc9f38c3SDavid Gibson smc->dr_lmb_enabled = true; 4486fea35ca4SAlexey Kardashevskiy smc->update_dt_enabled = true; 448734a6b015SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 4488c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = true; 448952b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED; 449071461b0fSAlexey Kardashevskiy fwc->get_dev_path = spapr_get_fw_dev_path; 449134316482SAlexey Kardashevskiy nc->nmi_monitor_handler = spapr_nmi; 44926737d9adSDavid Gibson smc->phb_placement = spapr_phb_placement; 44931d1be34dSDavid Gibson vhc->hypercall = emulate_spapr_hypercall; 4494e57ca75cSDavid Gibson vhc->hpt_mask = spapr_hpt_mask; 4495e57ca75cSDavid Gibson vhc->map_hptes = spapr_map_hptes; 4496e57ca75cSDavid Gibson vhc->unmap_hptes = spapr_unmap_hptes; 4497a2dd4e83SBenjamin Herrenschmidt vhc->hpte_set_c = spapr_hpte_set_c; 4498a2dd4e83SBenjamin Herrenschmidt vhc->hpte_set_r = spapr_hpte_set_r; 449979825f4dSBenjamin Herrenschmidt vhc->get_pate = spapr_get_pate; 45001ec26c75SGreg Kurz vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr; 450103ef074cSNicholas Piggin vhc->cpu_exec_enter = spapr_cpu_exec_enter; 450203ef074cSNicholas Piggin vhc->cpu_exec_exit = spapr_cpu_exec_exit; 45037844e12bSCédric Le Goater xic->ics_get = spapr_ics_get; 45047844e12bSCédric Le Goater xic->ics_resend = spapr_ics_resend; 4505b2fc59aaSCédric Le Goater xic->icp_get = spapr_icp_get; 45066449da45SCédric Le Goater ispc->print_info = spapr_pic_print_info; 450755641213SLaurent Vivier /* Force NUMA node memory size to be a multiple of 450855641213SLaurent Vivier * SPAPR_MEMORY_BLOCK_SIZE (256M) since that's the granularity 450955641213SLaurent Vivier * in which LMBs are represented and hot-added 451055641213SLaurent Vivier */ 451155641213SLaurent Vivier mc->numa_mem_align_shift = 28; 4512cd5ff833SIgor Mammedov mc->numa_mem_supported = true; 451333face6bSDavid Gibson 45144e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF; 45154e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON; 45164e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON; 45172782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND; 45182782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND; 45192782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_WORKAROUND; 45202309832aSDavid Gibson smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */ 4521b9a477b7SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF; 4522edaa7995SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON; 45238ff43ee4SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF; 452433face6bSDavid Gibson spapr_caps_add_properties(smc, &error_abort); 4525bd94bc06SCédric Le Goater smc->irq = &spapr_irq_dual; 4526dae5e39aSMichael Roth smc->dr_phb_enabled = true; 45276c3829a2SAlexey Kardashevskiy smc->linux_pci_probe = true; 452853018216SPaolo Bonzini } 452953018216SPaolo Bonzini 453029ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = { 453129ee3247SAlexey Kardashevskiy .name = TYPE_SPAPR_MACHINE, 453229ee3247SAlexey Kardashevskiy .parent = TYPE_MACHINE, 45334aee7362SDavid Gibson .abstract = true, 4534ce2918cbSDavid Gibson .instance_size = sizeof(SpaprMachineState), 4535bcb5ce08SDavid Gibson .instance_init = spapr_instance_init, 453687bbdd9cSDavid Gibson .instance_finalize = spapr_machine_finalizefn, 4537ce2918cbSDavid Gibson .class_size = sizeof(SpaprMachineClass), 453829ee3247SAlexey Kardashevskiy .class_init = spapr_machine_class_init, 453971461b0fSAlexey Kardashevskiy .interfaces = (InterfaceInfo[]) { 454071461b0fSAlexey Kardashevskiy { TYPE_FW_PATH_PROVIDER }, 454134316482SAlexey Kardashevskiy { TYPE_NMI }, 4542c20d332aSBharata B Rao { TYPE_HOTPLUG_HANDLER }, 45431d1be34dSDavid Gibson { TYPE_PPC_VIRTUAL_HYPERVISOR }, 45447844e12bSCédric Le Goater { TYPE_XICS_FABRIC }, 45456449da45SCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 454671461b0fSAlexey Kardashevskiy { } 454771461b0fSAlexey Kardashevskiy }, 454829ee3247SAlexey Kardashevskiy }; 454929ee3247SAlexey Kardashevskiy 4550fccbc785SDavid Gibson #define DEFINE_SPAPR_MACHINE(suffix, verstr, latest) \ 45515013c547SDavid Gibson static void spapr_machine_##suffix##_class_init(ObjectClass *oc, \ 45525013c547SDavid Gibson void *data) \ 45535013c547SDavid Gibson { \ 45545013c547SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); \ 45555013c547SDavid Gibson spapr_machine_##suffix##_class_options(mc); \ 4556fccbc785SDavid Gibson if (latest) { \ 4557fccbc785SDavid Gibson mc->alias = "pseries"; \ 4558fccbc785SDavid Gibson mc->is_default = 1; \ 4559fccbc785SDavid Gibson } \ 45605013c547SDavid Gibson } \ 45615013c547SDavid Gibson static const TypeInfo spapr_machine_##suffix##_info = { \ 45625013c547SDavid Gibson .name = MACHINE_TYPE_NAME("pseries-" verstr), \ 45635013c547SDavid Gibson .parent = TYPE_SPAPR_MACHINE, \ 45645013c547SDavid Gibson .class_init = spapr_machine_##suffix##_class_init, \ 45655013c547SDavid Gibson }; \ 45665013c547SDavid Gibson static void spapr_machine_register_##suffix(void) \ 45675013c547SDavid Gibson { \ 45685013c547SDavid Gibson type_register(&spapr_machine_##suffix##_info); \ 45695013c547SDavid Gibson } \ 45700e6aac87SEduardo Habkost type_init(spapr_machine_register_##suffix) 45715013c547SDavid Gibson 45721c5f29bbSDavid Gibson /* 45739aec2e52SCornelia Huck * pseries-4.2 4574e2676b16SGreg Kurz */ 45759aec2e52SCornelia Huck static void spapr_machine_4_2_class_options(MachineClass *mc) 4576e2676b16SGreg Kurz { 4577e2676b16SGreg Kurz /* Defaults for the latest behaviour inherited from the base class */ 4578e2676b16SGreg Kurz } 4579e2676b16SGreg Kurz 45809aec2e52SCornelia Huck DEFINE_SPAPR_MACHINE(4_2, "4.2", true); 45819aec2e52SCornelia Huck 45829aec2e52SCornelia Huck /* 45839aec2e52SCornelia Huck * pseries-4.1 45849aec2e52SCornelia Huck */ 45859aec2e52SCornelia Huck static void spapr_machine_4_1_class_options(MachineClass *mc) 45869aec2e52SCornelia Huck { 45876c3829a2SAlexey Kardashevskiy SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4588d15d4ad6SDavid Gibson static GlobalProperty compat[] = { 4589d15d4ad6SDavid Gibson /* Only allow 4kiB and 64kiB IOMMU pagesizes */ 4590d15d4ad6SDavid Gibson { TYPE_SPAPR_PCI_HOST_BRIDGE, "pgsz", "0x11000" }, 4591d15d4ad6SDavid Gibson }; 4592d15d4ad6SDavid Gibson 45939aec2e52SCornelia Huck spapr_machine_4_2_class_options(mc); 45946c3829a2SAlexey Kardashevskiy smc->linux_pci_probe = false; 45959aec2e52SCornelia Huck compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len); 4596d15d4ad6SDavid Gibson compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 45979aec2e52SCornelia Huck } 45989aec2e52SCornelia Huck 45999aec2e52SCornelia Huck DEFINE_SPAPR_MACHINE(4_1, "4.1", false); 46009bf2650bSCornelia Huck 46019bf2650bSCornelia Huck /* 46029bf2650bSCornelia Huck * pseries-4.0 46039bf2650bSCornelia Huck */ 4604eb3cba82SDavid Gibson static void phb_placement_4_0(SpaprMachineState *spapr, uint32_t index, 4605ec132efaSAlexey Kardashevskiy uint64_t *buid, hwaddr *pio, 4606ec132efaSAlexey Kardashevskiy hwaddr *mmio32, hwaddr *mmio64, 4607ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4608ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 4609ec132efaSAlexey Kardashevskiy { 4610ec132efaSAlexey Kardashevskiy spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma, liobns, 4611ec132efaSAlexey Kardashevskiy nv2gpa, nv2atsd, errp); 4612ec132efaSAlexey Kardashevskiy *nv2gpa = 0; 4613ec132efaSAlexey Kardashevskiy *nv2atsd = 0; 4614ec132efaSAlexey Kardashevskiy } 4615ec132efaSAlexey Kardashevskiy 4616eb3cba82SDavid Gibson static void spapr_machine_4_0_class_options(MachineClass *mc) 4617eb3cba82SDavid Gibson { 4618eb3cba82SDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4619eb3cba82SDavid Gibson 4620eb3cba82SDavid Gibson spapr_machine_4_1_class_options(mc); 4621eb3cba82SDavid Gibson compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); 4622eb3cba82SDavid Gibson smc->phb_placement = phb_placement_4_0; 4623bd94bc06SCédric Le Goater smc->irq = &spapr_irq_xics; 46243725ef1aSGreg Kurz smc->pre_4_1_migration = true; 4625eb3cba82SDavid Gibson } 4626eb3cba82SDavid Gibson 4627eb3cba82SDavid Gibson DEFINE_SPAPR_MACHINE(4_0, "4.0", false); 4628eb3cba82SDavid Gibson 4629eb3cba82SDavid Gibson /* 4630eb3cba82SDavid Gibson * pseries-3.1 4631eb3cba82SDavid Gibson */ 463288cbe073SMarc-André Lureau static void spapr_machine_3_1_class_options(MachineClass *mc) 463388cbe073SMarc-André Lureau { 4634ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4635fea35ca4SAlexey Kardashevskiy 463684e060bfSAlex Williamson spapr_machine_4_0_class_options(mc); 4637abd93cc7SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len); 463827461d69SPrasad J Pandit 463934a6b015SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 4640fea35ca4SAlexey Kardashevskiy smc->update_dt_enabled = false; 4641dae5e39aSMichael Roth smc->dr_phb_enabled = false; 46420a794529SDavid Gibson smc->broken_host_serial_model = true; 46432782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN; 46442782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN; 46452782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN; 4646edaa7995SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF; 464784e060bfSAlex Williamson } 464884e060bfSAlex Williamson 464984e060bfSAlex Williamson DEFINE_SPAPR_MACHINE(3_1, "3.1", false); 4650d45360d9SCédric Le Goater 4651d45360d9SCédric Le Goater /* 4652d45360d9SCédric Le Goater * pseries-3.0 4653d45360d9SCédric Le Goater */ 4654d45360d9SCédric Le Goater 4655d45360d9SCédric Le Goater static void spapr_machine_3_0_class_options(MachineClass *mc) 4656d45360d9SCédric Le Goater { 4657ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 465882cffa2eSCédric Le Goater 4659d45360d9SCédric Le Goater spapr_machine_3_1_class_options(mc); 4660ddb3235dSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len); 466182cffa2eSCédric Le Goater 466282cffa2eSCédric Le Goater smc->legacy_irq_allocation = true; 4663ae837402SCédric Le Goater smc->irq = &spapr_irq_xics_legacy; 4664d45360d9SCédric Le Goater } 4665d45360d9SCédric Le Goater 4666d45360d9SCédric Le Goater DEFINE_SPAPR_MACHINE(3_0, "3.0", false); 46678a4fd427SDavid Gibson 46688a4fd427SDavid Gibson /* 46698a4fd427SDavid Gibson * pseries-2.12 46708a4fd427SDavid Gibson */ 467188cbe073SMarc-André Lureau static void spapr_machine_2_12_class_options(MachineClass *mc) 467288cbe073SMarc-André Lureau { 4673ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 467488cbe073SMarc-André Lureau static GlobalProperty compat[] = { 46756c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-3.0-migration", "on" }, 46766c36bddfSEduardo Habkost { TYPE_SPAPR_CPU_CORE, "pre-3.0-migration", "on" }, 4677fa386d98SMarc-André Lureau }; 46788a4fd427SDavid Gibson 4679d8c0c7afSPeter Maydell spapr_machine_3_0_class_options(mc); 46800d47310bSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_12, hw_compat_2_12_len); 468188cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 46822309832aSDavid Gibson 4683e8937295SGreg Kurz /* We depend on kvm_enabled() to choose a default value for the 4684e8937295SGreg Kurz * hpt-max-page-size capability. Of course we can't do it here 4685e8937295SGreg Kurz * because this is too early and the HW accelerator isn't initialzed 4686e8937295SGreg Kurz * yet. Postpone this to machine init (see default_caps_with_cpu()). 4687e8937295SGreg Kurz */ 4688e8937295SGreg Kurz smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 0; 46898a4fd427SDavid Gibson } 46908a4fd427SDavid Gibson 46918a4fd427SDavid Gibson DEFINE_SPAPR_MACHINE(2_12, "2.12", false); 46922b615412SDavid Gibson 4693813f3cf6SSuraj Jitindar Singh static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc) 4694813f3cf6SSuraj Jitindar Singh { 4695ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4696813f3cf6SSuraj Jitindar Singh 4697813f3cf6SSuraj Jitindar Singh spapr_machine_2_12_class_options(mc); 4698813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND; 4699813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND; 4700813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_FIXED_CCD; 4701813f3cf6SSuraj Jitindar Singh } 4702813f3cf6SSuraj Jitindar Singh 4703813f3cf6SSuraj Jitindar Singh DEFINE_SPAPR_MACHINE(2_12_sxxm, "2.12-sxxm", false); 4704813f3cf6SSuraj Jitindar Singh 47052b615412SDavid Gibson /* 47062b615412SDavid Gibson * pseries-2.11 47072b615412SDavid Gibson */ 47082b615412SDavid Gibson 47092b615412SDavid Gibson static void spapr_machine_2_11_class_options(MachineClass *mc) 47102b615412SDavid Gibson { 4711ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4712ee76a09fSDavid Gibson 47132b615412SDavid Gibson spapr_machine_2_12_class_options(mc); 47144e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON; 471543df70a9SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len); 47162b615412SDavid Gibson } 47172b615412SDavid Gibson 47182b615412SDavid Gibson DEFINE_SPAPR_MACHINE(2_11, "2.11", false); 4719e2676b16SGreg Kurz 4720e2676b16SGreg Kurz /* 47213fa14fbeSDavid Gibson * pseries-2.10 4722db800b21SDavid Gibson */ 4723e2676b16SGreg Kurz 47243fa14fbeSDavid Gibson static void spapr_machine_2_10_class_options(MachineClass *mc) 4725db800b21SDavid Gibson { 4726e2676b16SGreg Kurz spapr_machine_2_11_class_options(mc); 4727503224f4SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_10, hw_compat_2_10_len); 4728db800b21SDavid Gibson } 4729db800b21SDavid Gibson 4730e2676b16SGreg Kurz DEFINE_SPAPR_MACHINE(2_10, "2.10", false); 47313fa14fbeSDavid Gibson 47323fa14fbeSDavid Gibson /* 47333fa14fbeSDavid Gibson * pseries-2.9 47343fa14fbeSDavid Gibson */ 473588cbe073SMarc-André Lureau 473688cbe073SMarc-André Lureau static void spapr_machine_2_9_class_options(MachineClass *mc) 473788cbe073SMarc-André Lureau { 4738ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 473988cbe073SMarc-André Lureau static GlobalProperty compat[] = { 47406c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-2.10-migration", "on" }, 4741fa386d98SMarc-André Lureau }; 47423fa14fbeSDavid Gibson 47433fa14fbeSDavid Gibson spapr_machine_2_10_class_options(mc); 47443e803152SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len); 474588cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 47463bfe5716SLaurent Vivier mc->numa_auto_assign_ram = numa_legacy_auto_assign_ram; 474746f7afa3SGreg Kurz smc->pre_2_10_has_unused_icps = true; 474852b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED; 47493fa14fbeSDavid Gibson } 47503fa14fbeSDavid Gibson 47513fa14fbeSDavid Gibson DEFINE_SPAPR_MACHINE(2_9, "2.9", false); 4752fa325e6cSDavid Gibson 4753fa325e6cSDavid Gibson /* 4754fa325e6cSDavid Gibson * pseries-2.8 4755fa325e6cSDavid Gibson */ 475688cbe073SMarc-André Lureau 475788cbe073SMarc-André Lureau static void spapr_machine_2_8_class_options(MachineClass *mc) 475888cbe073SMarc-André Lureau { 475988cbe073SMarc-André Lureau static GlobalProperty compat[] = { 47606c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "pcie-extended-configuration-space", "off" }, 4761fa386d98SMarc-André Lureau }; 4762fa325e6cSDavid Gibson 4763fa325e6cSDavid Gibson spapr_machine_2_9_class_options(mc); 4764edc24ccdSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len); 476588cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 476655641213SLaurent Vivier mc->numa_mem_align_shift = 23; 4767fa325e6cSDavid Gibson } 4768fa325e6cSDavid Gibson 4769fa325e6cSDavid Gibson DEFINE_SPAPR_MACHINE(2_8, "2.8", false); 4770db800b21SDavid Gibson 4771db800b21SDavid Gibson /* 47721ea1eefcSBharata B Rao * pseries-2.7 47731ea1eefcSBharata B Rao */ 4774357d1e3bSDavid Gibson 4775ce2918cbSDavid Gibson static void phb_placement_2_7(SpaprMachineState *spapr, uint32_t index, 4776357d1e3bSDavid Gibson uint64_t *buid, hwaddr *pio, 4777357d1e3bSDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 4778ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4779ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 4780357d1e3bSDavid Gibson { 4781357d1e3bSDavid Gibson /* Legacy PHB placement for pseries-2.7 and earlier machine types */ 4782357d1e3bSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 4783357d1e3bSDavid Gibson const hwaddr phb_spacing = 0x1000000000ULL; /* 64 GiB */ 4784357d1e3bSDavid Gibson const hwaddr mmio_offset = 0xa0000000; /* 2 GiB + 512 MiB */ 4785357d1e3bSDavid Gibson const hwaddr pio_offset = 0x80000000; /* 2 GiB */ 4786357d1e3bSDavid Gibson const uint32_t max_index = 255; 4787357d1e3bSDavid Gibson const hwaddr phb0_alignment = 0x10000000000ULL; /* 1 TiB */ 4788357d1e3bSDavid Gibson 4789357d1e3bSDavid Gibson uint64_t ram_top = MACHINE(spapr)->ram_size; 4790357d1e3bSDavid Gibson hwaddr phb0_base, phb_base; 4791357d1e3bSDavid Gibson int i; 4792357d1e3bSDavid Gibson 47930c9269a5SDavid Hildenbrand /* Do we have device memory? */ 4794357d1e3bSDavid Gibson if (MACHINE(spapr)->maxram_size > ram_top) { 4795357d1e3bSDavid Gibson /* Can't just use maxram_size, because there may be an 47960c9269a5SDavid Hildenbrand * alignment gap between normal and device memory regions 47970c9269a5SDavid Hildenbrand */ 4798b0c14ec4SDavid Hildenbrand ram_top = MACHINE(spapr)->device_memory->base + 4799b0c14ec4SDavid Hildenbrand memory_region_size(&MACHINE(spapr)->device_memory->mr); 4800357d1e3bSDavid Gibson } 4801357d1e3bSDavid Gibson 4802357d1e3bSDavid Gibson phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment); 4803357d1e3bSDavid Gibson 4804357d1e3bSDavid Gibson if (index > max_index) { 4805357d1e3bSDavid Gibson error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", 4806357d1e3bSDavid Gibson max_index); 4807357d1e3bSDavid Gibson return; 4808357d1e3bSDavid Gibson } 4809357d1e3bSDavid Gibson 4810357d1e3bSDavid Gibson *buid = base_buid + index; 4811357d1e3bSDavid Gibson for (i = 0; i < n_dma; ++i) { 4812357d1e3bSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 4813357d1e3bSDavid Gibson } 4814357d1e3bSDavid Gibson 4815357d1e3bSDavid Gibson phb_base = phb0_base + index * phb_spacing; 4816357d1e3bSDavid Gibson *pio = phb_base + pio_offset; 4817357d1e3bSDavid Gibson *mmio32 = phb_base + mmio_offset; 4818357d1e3bSDavid Gibson /* 4819357d1e3bSDavid Gibson * We don't set the 64-bit MMIO window, relying on the PHB's 4820357d1e3bSDavid Gibson * fallback behaviour of automatically splitting a large "32-bit" 4821357d1e3bSDavid Gibson * window into contiguous 32-bit and 64-bit windows 4822357d1e3bSDavid Gibson */ 4823ec132efaSAlexey Kardashevskiy 4824ec132efaSAlexey Kardashevskiy *nv2gpa = 0; 4825ec132efaSAlexey Kardashevskiy *nv2atsd = 0; 4826357d1e3bSDavid Gibson } 4827db800b21SDavid Gibson 48281ea1eefcSBharata B Rao static void spapr_machine_2_7_class_options(MachineClass *mc) 48291ea1eefcSBharata B Rao { 4830ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 483188cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48326c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0xf80000000", }, 48336c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem64_win_size", "0", }, 48346c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-2.8-migration", "on", }, 48356c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-2.8-migration", "on", }, 483688cbe073SMarc-André Lureau }; 48373daa4a9fSThomas Huth 4838db800b21SDavid Gibson spapr_machine_2_8_class_options(mc); 48392e9c10ebSIgor Mammedov mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power7_v2.3"); 4840a140c199SEduardo Habkost mc->default_machine_opts = "modern-hotplug-events=off"; 48415a995064SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_7, hw_compat_2_7_len); 484288cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 4843357d1e3bSDavid Gibson smc->phb_placement = phb_placement_2_7; 48441ea1eefcSBharata B Rao } 48451ea1eefcSBharata B Rao 4846db800b21SDavid Gibson DEFINE_SPAPR_MACHINE(2_7, "2.7", false); 48471ea1eefcSBharata B Rao 48481ea1eefcSBharata B Rao /* 48494b23699cSDavid Gibson * pseries-2.6 48504b23699cSDavid Gibson */ 485188cbe073SMarc-André Lureau 485288cbe073SMarc-André Lureau static void spapr_machine_2_6_class_options(MachineClass *mc) 485388cbe073SMarc-André Lureau { 485488cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48556c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "ddw", "off" }, 4856fa386d98SMarc-André Lureau }; 48571ea1eefcSBharata B Rao 48581ea1eefcSBharata B Rao spapr_machine_2_7_class_options(mc); 4859c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = false; 4860ff8f261fSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_6, hw_compat_2_6_len); 486188cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 48624b23699cSDavid Gibson } 48634b23699cSDavid Gibson 48641ea1eefcSBharata B Rao DEFINE_SPAPR_MACHINE(2_6, "2.6", false); 48654b23699cSDavid Gibson 48664b23699cSDavid Gibson /* 48671c5f29bbSDavid Gibson * pseries-2.5 48681c5f29bbSDavid Gibson */ 486988cbe073SMarc-André Lureau 487088cbe073SMarc-André Lureau static void spapr_machine_2_5_class_options(MachineClass *mc) 487188cbe073SMarc-André Lureau { 4872ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 487388cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48746c36bddfSEduardo Habkost { "spapr-vlan", "use-rx-buffer-pools", "off" }, 4875fa386d98SMarc-André Lureau }; 48764b23699cSDavid Gibson 48774b23699cSDavid Gibson spapr_machine_2_6_class_options(mc); 487857040d45SThomas Huth smc->use_ohci_by_default = true; 4879fe759610SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_5, hw_compat_2_5_len); 488088cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 48811c5f29bbSDavid Gibson } 48821c5f29bbSDavid Gibson 48834b23699cSDavid Gibson DEFINE_SPAPR_MACHINE(2_5, "2.5", false); 48841c5f29bbSDavid Gibson 48851c5f29bbSDavid Gibson /* 48861c5f29bbSDavid Gibson * pseries-2.4 48871c5f29bbSDavid Gibson */ 488880fd50f9SCornelia Huck 48895013c547SDavid Gibson static void spapr_machine_2_4_class_options(MachineClass *mc) 48905013c547SDavid Gibson { 4891ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4892fc9f38c3SDavid Gibson 4893fc9f38c3SDavid Gibson spapr_machine_2_5_class_options(mc); 4894fc9f38c3SDavid Gibson smc->dr_lmb_enabled = false; 48952f99b9c2SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_4, hw_compat_2_4_len); 48961c5f29bbSDavid Gibson } 48971c5f29bbSDavid Gibson 4898fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_4, "2.4", false); 48991c5f29bbSDavid Gibson 49001c5f29bbSDavid Gibson /* 49011c5f29bbSDavid Gibson * pseries-2.3 49021c5f29bbSDavid Gibson */ 490388cbe073SMarc-André Lureau 490488cbe073SMarc-André Lureau static void spapr_machine_2_3_class_options(MachineClass *mc) 490588cbe073SMarc-André Lureau { 490688cbe073SMarc-André Lureau static GlobalProperty compat[] = { 49076c36bddfSEduardo Habkost { "spapr-pci-host-bridge", "dynamic-reconfiguration", "off" }, 4908fa386d98SMarc-André Lureau }; 4909fc9f38c3SDavid Gibson spapr_machine_2_4_class_options(mc); 49108995dd90SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_3, hw_compat_2_3_len); 491188cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 49121c5f29bbSDavid Gibson } 4913fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_3, "2.3", false); 49141c5f29bbSDavid Gibson 49151c5f29bbSDavid Gibson /* 49161c5f29bbSDavid Gibson * pseries-2.2 49171c5f29bbSDavid Gibson */ 491888cbe073SMarc-André Lureau 491988cbe073SMarc-André Lureau static void spapr_machine_2_2_class_options(MachineClass *mc) 492088cbe073SMarc-André Lureau { 492188cbe073SMarc-André Lureau static GlobalProperty compat[] = { 49226c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0x20000000" }, 4923fa386d98SMarc-André Lureau }; 4924b194df47SAlexey Kardashevskiy 4925fc9f38c3SDavid Gibson spapr_machine_2_3_class_options(mc); 49261c30044eSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_2, hw_compat_2_2_len); 492788cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 4928f6d0656bSEduardo Habkost mc->default_machine_opts = "modern-hotplug-events=off,suppress-vmdesc=on"; 49291c5f29bbSDavid Gibson } 4930fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_2, "2.2", false); 49311c5f29bbSDavid Gibson 49321c5f29bbSDavid Gibson /* 49331c5f29bbSDavid Gibson * pseries-2.1 49341c5f29bbSDavid Gibson */ 49351c5f29bbSDavid Gibson 49365013c547SDavid Gibson static void spapr_machine_2_1_class_options(MachineClass *mc) 4937b0e966d0SJason Wang { 4938fc9f38c3SDavid Gibson spapr_machine_2_2_class_options(mc); 4939c4fc5695SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_1, hw_compat_2_1_len); 49406026db45SAlexey Kardashevskiy } 4941fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_1, "2.1", false); 49426026db45SAlexey Kardashevskiy 494329ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void) 494429ee3247SAlexey Kardashevskiy { 494529ee3247SAlexey Kardashevskiy type_register_static(&spapr_machine_info); 494629ee3247SAlexey Kardashevskiy } 494729ee3247SAlexey Kardashevskiy 494829ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types) 4949