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 84f041d6afSGreg Kurz #include "monitor/monitor.h" 85f041d6afSGreg Kurz 8653018216SPaolo Bonzini #include <libfdt.h> 8753018216SPaolo Bonzini 8853018216SPaolo Bonzini /* SLOF memory layout: 8953018216SPaolo Bonzini * 9053018216SPaolo Bonzini * SLOF raw image loaded at 0, copies its romfs right below the flat 9153018216SPaolo Bonzini * device-tree, then position SLOF itself 31M below that 9253018216SPaolo Bonzini * 9353018216SPaolo Bonzini * So we set FW_OVERHEAD to 40MB which should account for all of that 9453018216SPaolo Bonzini * and more 9553018216SPaolo Bonzini * 9653018216SPaolo Bonzini * We load our kernel at 4M, leaving space for SLOF initial image 9753018216SPaolo Bonzini */ 9838b02bd8SAlexey Kardashevskiy #define FDT_MAX_SIZE 0x100000 9953018216SPaolo Bonzini #define RTAS_MAX_SIZE 0x10000 100b7d1f77aSBenjamin Herrenschmidt #define RTAS_MAX_ADDR 0x80000000 /* RTAS must stay below that */ 10153018216SPaolo Bonzini #define FW_MAX_SIZE 0x400000 10253018216SPaolo Bonzini #define FW_FILE_NAME "slof.bin" 10353018216SPaolo Bonzini #define FW_OVERHEAD 0x2800000 10453018216SPaolo Bonzini #define KERNEL_LOAD_ADDR FW_MAX_SIZE 10553018216SPaolo Bonzini 10653018216SPaolo Bonzini #define MIN_RMA_SLOF 128UL 10753018216SPaolo Bonzini 1085c7adcf4SGreg Kurz #define PHANDLE_INTC 0x00001111 10953018216SPaolo Bonzini 1105d0fb150SGreg Kurz /* These two functions implement the VCPU id numbering: one to compute them 1115d0fb150SGreg Kurz * all and one to identify thread 0 of a VCORE. Any change to the first one 1125d0fb150SGreg Kurz * is likely to have an impact on the second one, so let's keep them close. 1135d0fb150SGreg Kurz */ 114ce2918cbSDavid Gibson static int spapr_vcpu_id(SpaprMachineState *spapr, int cpu_index) 1155d0fb150SGreg Kurz { 116fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 117fe6b6346SLike Xu unsigned int smp_threads = ms->smp.threads; 118fe6b6346SLike Xu 1191a5008fcSGreg Kurz assert(spapr->vsmt); 1205d0fb150SGreg Kurz return 1215d0fb150SGreg Kurz (cpu_index / smp_threads) * spapr->vsmt + cpu_index % smp_threads; 1225d0fb150SGreg Kurz } 123ce2918cbSDavid Gibson static bool spapr_is_thread0_in_vcore(SpaprMachineState *spapr, 1245d0fb150SGreg Kurz PowerPCCPU *cpu) 1255d0fb150SGreg Kurz { 1261a5008fcSGreg Kurz assert(spapr->vsmt); 1275d0fb150SGreg Kurz return spapr_get_vcpu_id(cpu) % spapr->vsmt == 0; 1285d0fb150SGreg Kurz } 1295d0fb150SGreg Kurz 13046f7afa3SGreg Kurz static bool pre_2_10_vmstate_dummy_icp_needed(void *opaque) 13146f7afa3SGreg Kurz { 13246f7afa3SGreg Kurz /* Dummy entries correspond to unused ICPState objects in older QEMUs, 13346f7afa3SGreg Kurz * and newer QEMUs don't even have them. In both cases, we don't want 13446f7afa3SGreg Kurz * to send anything on the wire. 13546f7afa3SGreg Kurz */ 13646f7afa3SGreg Kurz return false; 13746f7afa3SGreg Kurz } 13846f7afa3SGreg Kurz 13946f7afa3SGreg Kurz static const VMStateDescription pre_2_10_vmstate_dummy_icp = { 14046f7afa3SGreg Kurz .name = "icp/server", 14146f7afa3SGreg Kurz .version_id = 1, 14246f7afa3SGreg Kurz .minimum_version_id = 1, 14346f7afa3SGreg Kurz .needed = pre_2_10_vmstate_dummy_icp_needed, 14446f7afa3SGreg Kurz .fields = (VMStateField[]) { 14546f7afa3SGreg Kurz VMSTATE_UNUSED(4), /* uint32_t xirr */ 14646f7afa3SGreg Kurz VMSTATE_UNUSED(1), /* uint8_t pending_priority */ 14746f7afa3SGreg Kurz VMSTATE_UNUSED(1), /* uint8_t mfrr */ 14846f7afa3SGreg Kurz VMSTATE_END_OF_LIST() 14946f7afa3SGreg Kurz }, 15046f7afa3SGreg Kurz }; 15146f7afa3SGreg Kurz 15246f7afa3SGreg Kurz static void pre_2_10_vmstate_register_dummy_icp(int i) 15346f7afa3SGreg Kurz { 15446f7afa3SGreg Kurz vmstate_register(NULL, i, &pre_2_10_vmstate_dummy_icp, 15546f7afa3SGreg Kurz (void *)(uintptr_t) i); 15646f7afa3SGreg Kurz } 15746f7afa3SGreg Kurz 15846f7afa3SGreg Kurz static void pre_2_10_vmstate_unregister_dummy_icp(int i) 15946f7afa3SGreg Kurz { 16046f7afa3SGreg Kurz vmstate_unregister(NULL, &pre_2_10_vmstate_dummy_icp, 16146f7afa3SGreg Kurz (void *)(uintptr_t) i); 16246f7afa3SGreg Kurz } 16346f7afa3SGreg Kurz 164ce2918cbSDavid Gibson int spapr_max_server_number(SpaprMachineState *spapr) 16546f7afa3SGreg Kurz { 166fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 167fe6b6346SLike Xu 1681a5008fcSGreg Kurz assert(spapr->vsmt); 169fe6b6346SLike Xu return DIV_ROUND_UP(ms->smp.max_cpus * spapr->vsmt, ms->smp.threads); 17046f7afa3SGreg Kurz } 17146f7afa3SGreg Kurz 172833d4668SAlexey Kardashevskiy static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, 173833d4668SAlexey Kardashevskiy int smt_threads) 174833d4668SAlexey Kardashevskiy { 175833d4668SAlexey Kardashevskiy int i, ret = 0; 176833d4668SAlexey Kardashevskiy uint32_t servers_prop[smt_threads]; 177833d4668SAlexey Kardashevskiy uint32_t gservers_prop[smt_threads * 2]; 17814bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 179833d4668SAlexey Kardashevskiy 180d6e166c0SDavid Gibson if (cpu->compat_pvr) { 181d6e166c0SDavid Gibson ret = fdt_setprop_cell(fdt, offset, "cpu-version", cpu->compat_pvr); 1826d9412eaSAlexey Kardashevskiy if (ret < 0) { 1836d9412eaSAlexey Kardashevskiy return ret; 1846d9412eaSAlexey Kardashevskiy } 1856d9412eaSAlexey Kardashevskiy } 1866d9412eaSAlexey Kardashevskiy 187833d4668SAlexey Kardashevskiy /* Build interrupt servers and gservers properties */ 188833d4668SAlexey Kardashevskiy for (i = 0; i < smt_threads; i++) { 189833d4668SAlexey Kardashevskiy servers_prop[i] = cpu_to_be32(index + i); 190833d4668SAlexey Kardashevskiy /* Hack, direct the group queues back to cpu 0 */ 191833d4668SAlexey Kardashevskiy gservers_prop[i*2] = cpu_to_be32(index + i); 192833d4668SAlexey Kardashevskiy gservers_prop[i*2 + 1] = 0; 193833d4668SAlexey Kardashevskiy } 194833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 195833d4668SAlexey Kardashevskiy servers_prop, sizeof(servers_prop)); 196833d4668SAlexey Kardashevskiy if (ret < 0) { 197833d4668SAlexey Kardashevskiy return ret; 198833d4668SAlexey Kardashevskiy } 199833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-gserver#s", 200833d4668SAlexey Kardashevskiy gservers_prop, sizeof(gservers_prop)); 201833d4668SAlexey Kardashevskiy 202833d4668SAlexey Kardashevskiy return ret; 203833d4668SAlexey Kardashevskiy } 204833d4668SAlexey Kardashevskiy 20599861ecbSIgor Mammedov static int spapr_fixup_cpu_numa_dt(void *fdt, int offset, PowerPCCPU *cpu) 2060da6f3feSBharata B Rao { 20714bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 2080da6f3feSBharata B Rao uint32_t associativity[] = {cpu_to_be32(0x5), 2090da6f3feSBharata B Rao cpu_to_be32(0x0), 2100da6f3feSBharata B Rao cpu_to_be32(0x0), 2110da6f3feSBharata B Rao cpu_to_be32(0x0), 21215f8b142SIgor Mammedov cpu_to_be32(cpu->node_id), 2130da6f3feSBharata B Rao cpu_to_be32(index)}; 2140da6f3feSBharata B Rao 2150da6f3feSBharata B Rao /* Advertise NUMA via ibm,associativity */ 21699861ecbSIgor Mammedov return fdt_setprop(fdt, offset, "ibm,associativity", associativity, 2170da6f3feSBharata B Rao sizeof(associativity)); 2180da6f3feSBharata B Rao } 2190da6f3feSBharata B Rao 22086d5771aSSam Bobroff /* Populate the "ibm,pa-features" property */ 221ce2918cbSDavid Gibson static void spapr_populate_pa_features(SpaprMachineState *spapr, 222ee76a09fSDavid Gibson PowerPCCPU *cpu, 223daa36379SDavid Gibson void *fdt, int offset) 22486d5771aSSam Bobroff { 22586d5771aSSam Bobroff uint8_t pa_features_206[] = { 6, 0, 22686d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 }; 22786d5771aSSam Bobroff uint8_t pa_features_207[] = { 24, 0, 22886d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, 22986d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 23086d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 23186d5771aSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 }; 2329fb4541fSSam Bobroff uint8_t pa_features_300[] = { 66, 0, 2339fb4541fSSam Bobroff /* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */ 2349fb4541fSSam Bobroff /* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, SSO, 5: LE|CFAR|EB|LSQ */ 23586d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, /* 0 - 5 */ 2369fb4541fSSam Bobroff /* 6: DS207 */ 23786d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */ 2389fb4541fSSam Bobroff /* 16: Vector */ 23986d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */ 2409fb4541fSSam Bobroff /* 18: Vec. Scalar, 20: Vec. XOR, 22: HTM */ 2419bf502feSDavid Gibson 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */ 2429fb4541fSSam Bobroff /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */ 2439fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */ 2449fb4541fSSam Bobroff /* 30: MMR, 32: LE atomic, 34: EBB + ext EBB */ 2459fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */ 2469fb4541fSSam Bobroff /* 36: SPR SO, 38: Copy/Paste, 40: Radix MMU */ 2479fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 36 - 41 */ 2489fb4541fSSam Bobroff /* 42: PM, 44: PC RA, 46: SC vec'd */ 2499fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */ 2509fb4541fSSam Bobroff /* 48: SIMD, 50: QP BFP, 52: String */ 2519fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */ 2529fb4541fSSam Bobroff /* 54: DecFP, 56: DecI, 58: SHA */ 2539fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */ 2549fb4541fSSam Bobroff /* 60: NM atomic, 62: RNG */ 2559fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */ 2569fb4541fSSam Bobroff }; 2577abd43baSSuraj Jitindar Singh uint8_t *pa_features = NULL; 25886d5771aSSam Bobroff size_t pa_size; 25986d5771aSSam Bobroff 2607abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06, 0, cpu->compat_pvr)) { 26186d5771aSSam Bobroff pa_features = pa_features_206; 26286d5771aSSam Bobroff pa_size = sizeof(pa_features_206); 2637abd43baSSuraj Jitindar Singh } 2647abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07, 0, cpu->compat_pvr)) { 26586d5771aSSam Bobroff pa_features = pa_features_207; 26686d5771aSSam Bobroff pa_size = sizeof(pa_features_207); 2677abd43baSSuraj Jitindar Singh } 2687abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0, cpu->compat_pvr)) { 26986d5771aSSam Bobroff pa_features = pa_features_300; 27086d5771aSSam Bobroff pa_size = sizeof(pa_features_300); 2717abd43baSSuraj Jitindar Singh } 2727abd43baSSuraj Jitindar Singh if (!pa_features) { 27386d5771aSSam Bobroff return; 27486d5771aSSam Bobroff } 27586d5771aSSam Bobroff 27626cd35b8SDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_CI_LARGEPAGE)) { 27786d5771aSSam Bobroff /* 27886d5771aSSam Bobroff * Note: we keep CI large pages off by default because a 64K capable 27986d5771aSSam Bobroff * guest provisioned with large pages might otherwise try to map a qemu 28086d5771aSSam Bobroff * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages 28186d5771aSSam Bobroff * even if that qemu runs on a 4k host. 28286d5771aSSam Bobroff * We dd this bit back here if we are confident this is not an issue 28386d5771aSSam Bobroff */ 28486d5771aSSam Bobroff pa_features[3] |= 0x20; 28586d5771aSSam Bobroff } 2864e5fe368SSuraj Jitindar Singh if ((spapr_get_cap(spapr, SPAPR_CAP_HTM) != 0) && pa_size > 24) { 28786d5771aSSam Bobroff pa_features[24] |= 0x80; /* Transactional memory support */ 28886d5771aSSam Bobroff } 289daa36379SDavid Gibson if (spapr->cas_pre_isa3_guest && pa_size > 40) { 290e957f6a9SSam Bobroff /* Workaround for broken kernels that attempt (guest) radix 291e957f6a9SSam Bobroff * mode when they can't handle it, if they see the radix bit set 292e957f6a9SSam Bobroff * in pa-features. So hide it from them. */ 293e957f6a9SSam Bobroff pa_features[40 + 2] &= ~0x80; /* Radix MMU */ 294e957f6a9SSam Bobroff } 29586d5771aSSam Bobroff 29686d5771aSSam Bobroff _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size))); 29786d5771aSSam Bobroff } 29886d5771aSSam Bobroff 299ce2918cbSDavid Gibson static int spapr_fixup_cpu_dt(void *fdt, SpaprMachineState *spapr) 30053018216SPaolo Bonzini { 301fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 30282677ed2SAlexey Kardashevskiy int ret = 0, offset, cpus_offset; 30382677ed2SAlexey Kardashevskiy CPUState *cs; 30453018216SPaolo Bonzini char cpu_model[32]; 30553018216SPaolo Bonzini uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 30653018216SPaolo Bonzini 30782677ed2SAlexey Kardashevskiy CPU_FOREACH(cs) { 30882677ed2SAlexey Kardashevskiy PowerPCCPU *cpu = POWERPC_CPU(cs); 30982677ed2SAlexey Kardashevskiy DeviceClass *dc = DEVICE_GET_CLASS(cs); 31014bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 311fe6b6346SLike Xu int compat_smt = MIN(ms->smp.threads, ppc_compat_max_vthreads(cpu)); 31253018216SPaolo Bonzini 3135d0fb150SGreg Kurz if (!spapr_is_thread0_in_vcore(spapr, cpu)) { 31453018216SPaolo Bonzini continue; 31553018216SPaolo Bonzini } 31653018216SPaolo Bonzini 31782677ed2SAlexey Kardashevskiy snprintf(cpu_model, 32, "%s@%x", dc->fw_name, index); 31853018216SPaolo Bonzini 31982677ed2SAlexey Kardashevskiy cpus_offset = fdt_path_offset(fdt, "/cpus"); 32082677ed2SAlexey Kardashevskiy if (cpus_offset < 0) { 321a4f3885cSGreg Kurz cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 32282677ed2SAlexey Kardashevskiy if (cpus_offset < 0) { 32382677ed2SAlexey Kardashevskiy return cpus_offset; 32482677ed2SAlexey Kardashevskiy } 32582677ed2SAlexey Kardashevskiy } 32682677ed2SAlexey Kardashevskiy offset = fdt_subnode_offset(fdt, cpus_offset, cpu_model); 32782677ed2SAlexey Kardashevskiy if (offset < 0) { 32882677ed2SAlexey Kardashevskiy offset = fdt_add_subnode(fdt, cpus_offset, cpu_model); 32953018216SPaolo Bonzini if (offset < 0) { 33053018216SPaolo Bonzini return offset; 33153018216SPaolo Bonzini } 33282677ed2SAlexey Kardashevskiy } 33353018216SPaolo Bonzini 3340da6f3feSBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,pft-size", 3350da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)); 33653018216SPaolo Bonzini if (ret < 0) { 33753018216SPaolo Bonzini return ret; 33853018216SPaolo Bonzini } 33953018216SPaolo Bonzini 340aa570207STao Xu if (ms->numa_state->num_nodes > 1) { 34199861ecbSIgor Mammedov ret = spapr_fixup_cpu_numa_dt(fdt, offset, cpu); 34253018216SPaolo Bonzini if (ret < 0) { 34353018216SPaolo Bonzini return ret; 34453018216SPaolo Bonzini } 34599861ecbSIgor Mammedov } 346833d4668SAlexey Kardashevskiy 34712dbeb16SDavid Gibson ret = spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt); 348833d4668SAlexey Kardashevskiy if (ret < 0) { 349833d4668SAlexey Kardashevskiy return ret; 350833d4668SAlexey Kardashevskiy } 351e957f6a9SSam Bobroff 352daa36379SDavid Gibson spapr_populate_pa_features(spapr, cpu, fdt, offset); 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 554daa36379SDavid Gibson spapr_populate_pa_features(spapr, cpu, fdt, offset); 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 174225c9780dSDavid Gibson qemu_devices_reset(); 174325c9780dSDavid Gibson 174425c9780dSDavid Gibson /* 174579825f4dSBenjamin Herrenschmidt * If this reset wasn't generated by CAS, we should reset our 174679825f4dSBenjamin Herrenschmidt * negotiated options and start from scratch 174779825f4dSBenjamin Herrenschmidt */ 17489012a53fSGreg Kurz if (!spapr->cas_reboot) { 17499012a53fSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas); 17509012a53fSGreg Kurz spapr->ov5_cas = spapr_ovec_new(); 17519012a53fSGreg Kurz 1752ce03a193SLaurent Vivier ppc_set_compat_all(spapr->max_compat_pvr, &error_fatal); 17539012a53fSGreg Kurz } 17549012a53fSGreg Kurz 1755ec132efaSAlexey Kardashevskiy /* 1756b2e22477SCédric Le Goater * This is fixing some of the default configuration of the XIVE 1757b2e22477SCédric Le Goater * devices. To be called after the reset of the machine devices. 1758b2e22477SCédric Le Goater */ 1759b2e22477SCédric Le Goater spapr_irq_reset(spapr, &error_fatal); 1760b2e22477SCédric Le Goater 176123ff81bdSGreg Kurz /* 176223ff81bdSGreg Kurz * There is no CAS under qtest. Simulate one to please the code that 176323ff81bdSGreg Kurz * depends on spapr->ov5_cas. This is especially needed to test device 176423ff81bdSGreg Kurz * unplug, so we do that before resetting the DRCs. 176523ff81bdSGreg Kurz */ 176623ff81bdSGreg Kurz if (qtest_enabled()) { 176723ff81bdSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas); 176823ff81bdSGreg Kurz spapr->ov5_cas = spapr_ovec_clone(spapr->ov5); 176923ff81bdSGreg Kurz } 177023ff81bdSGreg Kurz 177182512483SGreg Kurz /* DRC reset may cause a device to be unplugged. This will cause troubles 177282512483SGreg Kurz * if this device is used by another device (eg, a running vhost backend 177382512483SGreg Kurz * will crash QEMU if the DIMM holding the vring goes away). To avoid such 177482512483SGreg Kurz * situations, we reset DRCs after all devices have been reset. 177582512483SGreg Kurz */ 177682512483SGreg Kurz object_child_foreach_recursive(object_get_root(), spapr_reset_drcs, NULL); 177782512483SGreg Kurz 177856258174SDaniel Henrique Barboza spapr_clear_pending_events(spapr); 177953018216SPaolo Bonzini 1780b7d1f77aSBenjamin Herrenschmidt /* 1781b7d1f77aSBenjamin Herrenschmidt * We place the device tree and RTAS just below either the top of the RMA, 1782df269271SAlexey Kardashevskiy * or just below 2GB, whichever is lower, so that it can be 1783b7d1f77aSBenjamin Herrenschmidt * processed with 32-bit real mode code if necessary 1784b7d1f77aSBenjamin Herrenschmidt */ 1785b7d1f77aSBenjamin Herrenschmidt rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR); 1786cae172abSDavid Gibson rtas_addr = rtas_limit - RTAS_MAX_SIZE; 1787cae172abSDavid Gibson fdt_addr = rtas_addr - FDT_MAX_SIZE; 1788b7d1f77aSBenjamin Herrenschmidt 1789df269271SAlexey Kardashevskiy fdt = spapr_build_fdt(spapr); 179053018216SPaolo Bonzini 17912cac78c1SDavid Gibson spapr_load_rtas(spapr, fdt, rtas_addr); 1792b7d1f77aSBenjamin Herrenschmidt 1793997b6cfcSDavid Gibson rc = fdt_pack(fdt); 1794997b6cfcSDavid Gibson 1795997b6cfcSDavid Gibson /* Should only fail if we've built a corrupted tree */ 1796997b6cfcSDavid Gibson assert(rc == 0); 1797997b6cfcSDavid Gibson 1798997b6cfcSDavid Gibson if (fdt_totalsize(fdt) > FDT_MAX_SIZE) { 1799997b6cfcSDavid Gibson error_report("FDT too big ! 0x%x bytes (max is 0x%x)", 1800997b6cfcSDavid Gibson fdt_totalsize(fdt), FDT_MAX_SIZE); 1801997b6cfcSDavid Gibson exit(1); 1802997b6cfcSDavid Gibson } 1803997b6cfcSDavid Gibson 1804997b6cfcSDavid Gibson /* Load the fdt */ 1805997b6cfcSDavid Gibson qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 1806cae172abSDavid Gibson cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); 1807fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob); 1808fea35ca4SAlexey Kardashevskiy spapr->fdt_size = fdt_totalsize(fdt); 1809fea35ca4SAlexey Kardashevskiy spapr->fdt_initial_size = spapr->fdt_size; 1810fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = fdt; 1811997b6cfcSDavid Gibson 181253018216SPaolo Bonzini /* Set up the entry state */ 181384369f63SDavid Gibson spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT, fdt_addr); 1814182735efSAndreas Färber first_ppc_cpu->env.gpr[5] = 0; 181553018216SPaolo Bonzini 18166787d27bSMichael Roth spapr->cas_reboot = false; 181753018216SPaolo Bonzini } 181853018216SPaolo Bonzini 1819ce2918cbSDavid Gibson static void spapr_create_nvram(SpaprMachineState *spapr) 182053018216SPaolo Bonzini { 18212ff3de68SMarkus Armbruster DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); 18223978b863SPaolo Bonzini DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); 182353018216SPaolo Bonzini 18243978b863SPaolo Bonzini if (dinfo) { 18256231a6daSMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo), 18266231a6daSMarkus Armbruster &error_fatal); 182753018216SPaolo Bonzini } 182853018216SPaolo Bonzini 182953018216SPaolo Bonzini qdev_init_nofail(dev); 183053018216SPaolo Bonzini 1831ce2918cbSDavid Gibson spapr->nvram = (struct SpaprNvram *)dev; 183253018216SPaolo Bonzini } 183353018216SPaolo Bonzini 1834ce2918cbSDavid Gibson static void spapr_rtc_create(SpaprMachineState *spapr) 183528df36a1SDavid Gibson { 1836f6d4dca8SThomas Huth object_initialize_child(OBJECT(spapr), "rtc", 1837f6d4dca8SThomas Huth &spapr->rtc, sizeof(spapr->rtc), TYPE_SPAPR_RTC, 1838f6d4dca8SThomas Huth &error_fatal, NULL); 1839147ff807SCédric Le Goater object_property_set_bool(OBJECT(&spapr->rtc), true, "realized", 1840147ff807SCédric Le Goater &error_fatal); 1841147ff807SCédric Le Goater object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc), 1842147ff807SCédric Le Goater "date", &error_fatal); 184328df36a1SDavid Gibson } 184428df36a1SDavid Gibson 184553018216SPaolo Bonzini /* Returns whether we want to use VGA or not */ 184614c6a894SDavid Gibson static bool spapr_vga_init(PCIBus *pci_bus, Error **errp) 184753018216SPaolo Bonzini { 184853018216SPaolo Bonzini switch (vga_interface_type) { 184953018216SPaolo Bonzini case VGA_NONE: 18507effdaa3SMark Wu return false; 18517effdaa3SMark Wu case VGA_DEVICE: 18527effdaa3SMark Wu return true; 185353018216SPaolo Bonzini case VGA_STD: 1854b798c190SBenjamin Herrenschmidt case VGA_VIRTIO: 18556e66d0c6SThomas Huth case VGA_CIRRUS: 185653018216SPaolo Bonzini return pci_vga_init(pci_bus) != NULL; 185753018216SPaolo Bonzini default: 185814c6a894SDavid Gibson error_setg(errp, 185914c6a894SDavid Gibson "Unsupported VGA mode, only -vga std or -vga virtio is supported"); 186014c6a894SDavid Gibson return false; 186153018216SPaolo Bonzini } 186253018216SPaolo Bonzini } 186353018216SPaolo Bonzini 18644e5fe368SSuraj Jitindar Singh static int spapr_pre_load(void *opaque) 18654e5fe368SSuraj Jitindar Singh { 18664e5fe368SSuraj Jitindar Singh int rc; 18674e5fe368SSuraj Jitindar Singh 18684e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_load(opaque); 18694e5fe368SSuraj Jitindar Singh if (rc) { 18704e5fe368SSuraj Jitindar Singh return rc; 18714e5fe368SSuraj Jitindar Singh } 18724e5fe368SSuraj Jitindar Singh 18734e5fe368SSuraj Jitindar Singh return 0; 18744e5fe368SSuraj Jitindar Singh } 18754e5fe368SSuraj Jitindar Singh 1876880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id) 1877880ae7deSDavid Gibson { 1878ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 1879880ae7deSDavid Gibson int err = 0; 1880880ae7deSDavid Gibson 1881be85537dSDavid Gibson err = spapr_caps_post_migration(spapr); 1882be85537dSDavid Gibson if (err) { 1883be85537dSDavid Gibson return err; 1884be85537dSDavid Gibson } 1885be85537dSDavid Gibson 1886e502202cSCédric Le Goater /* 1887e502202cSCédric Le Goater * In earlier versions, there was no separate qdev for the PAPR 1888880ae7deSDavid Gibson * RTC, so the RTC offset was stored directly in sPAPREnvironment. 1889880ae7deSDavid Gibson * So when migrating from those versions, poke the incoming offset 1890e502202cSCédric Le Goater * value into the RTC device 1891e502202cSCédric Le Goater */ 1892880ae7deSDavid Gibson if (version_id < 3) { 1893147ff807SCédric Le Goater err = spapr_rtc_import_offset(&spapr->rtc, spapr->rtc_offset); 1894e502202cSCédric Le Goater if (err) { 1895e502202cSCédric Le Goater return err; 1896e502202cSCédric Le Goater } 1897880ae7deSDavid Gibson } 1898880ae7deSDavid Gibson 18990c86b2dfSLaurent Vivier if (kvm_enabled() && spapr->patb_entry) { 1900d39c90f5SBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(first_cpu); 190179825f4dSBenjamin Herrenschmidt bool radix = !!(spapr->patb_entry & PATE1_GR); 1902d39c90f5SBharata B Rao bool gtse = !!(cpu->env.spr[SPR_LPCR] & LPCR_GTSE); 1903d39c90f5SBharata B Rao 190400fd075eSBenjamin Herrenschmidt /* 190500fd075eSBenjamin Herrenschmidt * Update LPCR:HR and UPRT as they may not be set properly in 190600fd075eSBenjamin Herrenschmidt * the stream 190700fd075eSBenjamin Herrenschmidt */ 190800fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(radix ? (LPCR_HR | LPCR_UPRT) : 0, 190900fd075eSBenjamin Herrenschmidt LPCR_HR | LPCR_UPRT); 191000fd075eSBenjamin Herrenschmidt 1911d39c90f5SBharata B Rao err = kvmppc_configure_v3_mmu(cpu, radix, gtse, spapr->patb_entry); 1912d39c90f5SBharata B Rao if (err) { 1913d39c90f5SBharata B Rao error_report("Process table config unsupported by the host"); 1914d39c90f5SBharata B Rao return -EINVAL; 1915d39c90f5SBharata B Rao } 1916d39c90f5SBharata B Rao } 1917d39c90f5SBharata B Rao 19181c53b06cSCédric Le Goater err = spapr_irq_post_load(spapr, version_id); 19191c53b06cSCédric Le Goater if (err) { 19201c53b06cSCédric Le Goater return err; 19211c53b06cSCédric Le Goater } 19221c53b06cSCédric Le Goater 1923880ae7deSDavid Gibson return err; 1924880ae7deSDavid Gibson } 1925880ae7deSDavid Gibson 19264e5fe368SSuraj Jitindar Singh static int spapr_pre_save(void *opaque) 19274e5fe368SSuraj Jitindar Singh { 19284e5fe368SSuraj Jitindar Singh int rc; 19294e5fe368SSuraj Jitindar Singh 19304e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_save(opaque); 19314e5fe368SSuraj Jitindar Singh if (rc) { 19324e5fe368SSuraj Jitindar Singh return rc; 19334e5fe368SSuraj Jitindar Singh } 19344e5fe368SSuraj Jitindar Singh 19354e5fe368SSuraj Jitindar Singh return 0; 19364e5fe368SSuraj Jitindar Singh } 19374e5fe368SSuraj Jitindar Singh 1938880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id) 1939880ae7deSDavid Gibson { 1940880ae7deSDavid Gibson return version_id < 3; 1941880ae7deSDavid Gibson } 1942880ae7deSDavid Gibson 1943fd38804bSDaniel Henrique Barboza static bool spapr_pending_events_needed(void *opaque) 1944fd38804bSDaniel Henrique Barboza { 1945ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 1946fd38804bSDaniel Henrique Barboza return !QTAILQ_EMPTY(&spapr->pending_events); 1947fd38804bSDaniel Henrique Barboza } 1948fd38804bSDaniel Henrique Barboza 1949fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_event_entry = { 1950fd38804bSDaniel Henrique Barboza .name = "spapr_event_log_entry", 1951fd38804bSDaniel Henrique Barboza .version_id = 1, 1952fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1953fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 1954ce2918cbSDavid Gibson VMSTATE_UINT32(summary, SpaprEventLogEntry), 1955ce2918cbSDavid Gibson VMSTATE_UINT32(extended_length, SpaprEventLogEntry), 1956ce2918cbSDavid Gibson VMSTATE_VBUFFER_ALLOC_UINT32(extended_log, SpaprEventLogEntry, 0, 19575341258eSDavid Gibson NULL, extended_length), 1958fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1959fd38804bSDaniel Henrique Barboza }, 1960fd38804bSDaniel Henrique Barboza }; 1961fd38804bSDaniel Henrique Barboza 1962fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_pending_events = { 1963fd38804bSDaniel Henrique Barboza .name = "spapr_pending_events", 1964fd38804bSDaniel Henrique Barboza .version_id = 1, 1965fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1966fd38804bSDaniel Henrique Barboza .needed = spapr_pending_events_needed, 1967fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 1968ce2918cbSDavid Gibson VMSTATE_QTAILQ_V(pending_events, SpaprMachineState, 1, 1969ce2918cbSDavid Gibson vmstate_spapr_event_entry, SpaprEventLogEntry, next), 1970fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1971fd38804bSDaniel Henrique Barboza }, 1972fd38804bSDaniel Henrique Barboza }; 1973fd38804bSDaniel Henrique Barboza 197462ef3760SMichael Roth static bool spapr_ov5_cas_needed(void *opaque) 197562ef3760SMichael Roth { 1976ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 1977ce2918cbSDavid Gibson SpaprOptionVector *ov5_mask = spapr_ovec_new(); 1978ce2918cbSDavid Gibson SpaprOptionVector *ov5_legacy = spapr_ovec_new(); 1979ce2918cbSDavid Gibson SpaprOptionVector *ov5_removed = spapr_ovec_new(); 198062ef3760SMichael Roth bool cas_needed; 198162ef3760SMichael Roth 1982ce2918cbSDavid Gibson /* Prior to the introduction of SpaprOptionVector, we had two option 198362ef3760SMichael Roth * vectors we dealt with: OV5_FORM1_AFFINITY, and OV5_DRCONF_MEMORY. 198462ef3760SMichael Roth * Both of these options encode machine topology into the device-tree 198562ef3760SMichael Roth * in such a way that the now-booted OS should still be able to interact 198662ef3760SMichael Roth * appropriately with QEMU regardless of what options were actually 198762ef3760SMichael Roth * negotiatied on the source side. 198862ef3760SMichael Roth * 198962ef3760SMichael Roth * As such, we can avoid migrating the CAS-negotiated options if these 199062ef3760SMichael Roth * are the only options available on the current machine/platform. 199162ef3760SMichael Roth * Since these are the only options available for pseries-2.7 and 199262ef3760SMichael Roth * earlier, this allows us to maintain old->new/new->old migration 199362ef3760SMichael Roth * compatibility. 199462ef3760SMichael Roth * 199562ef3760SMichael Roth * For QEMU 2.8+, there are additional CAS-negotiatable options available 199662ef3760SMichael Roth * via default pseries-2.8 machines and explicit command-line parameters. 199762ef3760SMichael Roth * Some of these options, like OV5_HP_EVT, *do* require QEMU to be aware 199862ef3760SMichael Roth * of the actual CAS-negotiated values to continue working properly. For 199962ef3760SMichael Roth * example, availability of memory unplug depends on knowing whether 200062ef3760SMichael Roth * OV5_HP_EVT was negotiated via CAS. 200162ef3760SMichael Roth * 200262ef3760SMichael Roth * Thus, for any cases where the set of available CAS-negotiatable 200362ef3760SMichael Roth * options extends beyond OV5_FORM1_AFFINITY and OV5_DRCONF_MEMORY, we 2004aef19c04SGreg Kurz * include the CAS-negotiated options in the migration stream, unless 2005aef19c04SGreg Kurz * if they affect boot time behaviour only. 200662ef3760SMichael Roth */ 200762ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_FORM1_AFFINITY); 200862ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_DRCONF_MEMORY); 2009aef19c04SGreg Kurz spapr_ovec_set(ov5_mask, OV5_DRMEM_V2); 201062ef3760SMichael Roth 201162ef3760SMichael Roth /* spapr_ovec_diff returns true if bits were removed. we avoid using 201262ef3760SMichael Roth * the mask itself since in the future it's possible "legacy" bits may be 201362ef3760SMichael Roth * removed via machine options, which could generate a false positive 201462ef3760SMichael Roth * that breaks migration. 201562ef3760SMichael Roth */ 201662ef3760SMichael Roth spapr_ovec_intersect(ov5_legacy, spapr->ov5, ov5_mask); 201762ef3760SMichael Roth cas_needed = spapr_ovec_diff(ov5_removed, spapr->ov5, ov5_legacy); 201862ef3760SMichael Roth 201962ef3760SMichael Roth spapr_ovec_cleanup(ov5_mask); 202062ef3760SMichael Roth spapr_ovec_cleanup(ov5_legacy); 202162ef3760SMichael Roth spapr_ovec_cleanup(ov5_removed); 202262ef3760SMichael Roth 202362ef3760SMichael Roth return cas_needed; 202462ef3760SMichael Roth } 202562ef3760SMichael Roth 202662ef3760SMichael Roth static const VMStateDescription vmstate_spapr_ov5_cas = { 202762ef3760SMichael Roth .name = "spapr_option_vector_ov5_cas", 202862ef3760SMichael Roth .version_id = 1, 202962ef3760SMichael Roth .minimum_version_id = 1, 203062ef3760SMichael Roth .needed = spapr_ov5_cas_needed, 203162ef3760SMichael Roth .fields = (VMStateField[]) { 2032ce2918cbSDavid Gibson VMSTATE_STRUCT_POINTER_V(ov5_cas, SpaprMachineState, 1, 2033ce2918cbSDavid Gibson vmstate_spapr_ovec, SpaprOptionVector), 203462ef3760SMichael Roth VMSTATE_END_OF_LIST() 203562ef3760SMichael Roth }, 203662ef3760SMichael Roth }; 203762ef3760SMichael Roth 20389861bb3eSSuraj Jitindar Singh static bool spapr_patb_entry_needed(void *opaque) 20399861bb3eSSuraj Jitindar Singh { 2040ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 20419861bb3eSSuraj Jitindar Singh 20429861bb3eSSuraj Jitindar Singh return !!spapr->patb_entry; 20439861bb3eSSuraj Jitindar Singh } 20449861bb3eSSuraj Jitindar Singh 20459861bb3eSSuraj Jitindar Singh static const VMStateDescription vmstate_spapr_patb_entry = { 20469861bb3eSSuraj Jitindar Singh .name = "spapr_patb_entry", 20479861bb3eSSuraj Jitindar Singh .version_id = 1, 20489861bb3eSSuraj Jitindar Singh .minimum_version_id = 1, 20499861bb3eSSuraj Jitindar Singh .needed = spapr_patb_entry_needed, 20509861bb3eSSuraj Jitindar Singh .fields = (VMStateField[]) { 2051ce2918cbSDavid Gibson VMSTATE_UINT64(patb_entry, SpaprMachineState), 20529861bb3eSSuraj Jitindar Singh VMSTATE_END_OF_LIST() 20539861bb3eSSuraj Jitindar Singh }, 20549861bb3eSSuraj Jitindar Singh }; 20559861bb3eSSuraj Jitindar Singh 205682cffa2eSCédric Le Goater static bool spapr_irq_map_needed(void *opaque) 205782cffa2eSCédric Le Goater { 2058ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 205982cffa2eSCédric Le Goater 206082cffa2eSCédric Le Goater return spapr->irq_map && !bitmap_empty(spapr->irq_map, spapr->irq_map_nr); 206182cffa2eSCédric Le Goater } 206282cffa2eSCédric Le Goater 206382cffa2eSCédric Le Goater static const VMStateDescription vmstate_spapr_irq_map = { 206482cffa2eSCédric Le Goater .name = "spapr_irq_map", 206582cffa2eSCédric Le Goater .version_id = 1, 206682cffa2eSCédric Le Goater .minimum_version_id = 1, 206782cffa2eSCédric Le Goater .needed = spapr_irq_map_needed, 206882cffa2eSCédric Le Goater .fields = (VMStateField[]) { 2069ce2918cbSDavid Gibson VMSTATE_BITMAP(irq_map, SpaprMachineState, 0, irq_map_nr), 207082cffa2eSCédric Le Goater VMSTATE_END_OF_LIST() 207182cffa2eSCédric Le Goater }, 207282cffa2eSCédric Le Goater }; 207382cffa2eSCédric Le Goater 2074fea35ca4SAlexey Kardashevskiy static bool spapr_dtb_needed(void *opaque) 2075fea35ca4SAlexey Kardashevskiy { 2076ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(opaque); 2077fea35ca4SAlexey Kardashevskiy 2078fea35ca4SAlexey Kardashevskiy return smc->update_dt_enabled; 2079fea35ca4SAlexey Kardashevskiy } 2080fea35ca4SAlexey Kardashevskiy 2081fea35ca4SAlexey Kardashevskiy static int spapr_dtb_pre_load(void *opaque) 2082fea35ca4SAlexey Kardashevskiy { 2083ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 2084fea35ca4SAlexey Kardashevskiy 2085fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob); 2086fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = NULL; 2087fea35ca4SAlexey Kardashevskiy spapr->fdt_size = 0; 2088fea35ca4SAlexey Kardashevskiy 2089fea35ca4SAlexey Kardashevskiy return 0; 2090fea35ca4SAlexey Kardashevskiy } 2091fea35ca4SAlexey Kardashevskiy 2092fea35ca4SAlexey Kardashevskiy static const VMStateDescription vmstate_spapr_dtb = { 2093fea35ca4SAlexey Kardashevskiy .name = "spapr_dtb", 2094fea35ca4SAlexey Kardashevskiy .version_id = 1, 2095fea35ca4SAlexey Kardashevskiy .minimum_version_id = 1, 2096fea35ca4SAlexey Kardashevskiy .needed = spapr_dtb_needed, 2097fea35ca4SAlexey Kardashevskiy .pre_load = spapr_dtb_pre_load, 2098fea35ca4SAlexey Kardashevskiy .fields = (VMStateField[]) { 2099ce2918cbSDavid Gibson VMSTATE_UINT32(fdt_initial_size, SpaprMachineState), 2100ce2918cbSDavid Gibson VMSTATE_UINT32(fdt_size, SpaprMachineState), 2101ce2918cbSDavid Gibson VMSTATE_VBUFFER_ALLOC_UINT32(fdt_blob, SpaprMachineState, 0, NULL, 2102fea35ca4SAlexey Kardashevskiy fdt_size), 2103fea35ca4SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 2104fea35ca4SAlexey Kardashevskiy }, 2105fea35ca4SAlexey Kardashevskiy }; 2106fea35ca4SAlexey Kardashevskiy 21074be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = { 21084be21d56SDavid Gibson .name = "spapr", 2109880ae7deSDavid Gibson .version_id = 3, 21104be21d56SDavid Gibson .minimum_version_id = 1, 21114e5fe368SSuraj Jitindar Singh .pre_load = spapr_pre_load, 2112880ae7deSDavid Gibson .post_load = spapr_post_load, 21134e5fe368SSuraj Jitindar Singh .pre_save = spapr_pre_save, 21144be21d56SDavid Gibson .fields = (VMStateField[]) { 2115880ae7deSDavid Gibson /* used to be @next_irq */ 2116880ae7deSDavid Gibson VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4), 21174be21d56SDavid Gibson 21184be21d56SDavid Gibson /* RTC offset */ 2119ce2918cbSDavid Gibson VMSTATE_UINT64_TEST(rtc_offset, SpaprMachineState, version_before_3), 2120880ae7deSDavid Gibson 2121ce2918cbSDavid Gibson VMSTATE_PPC_TIMEBASE_V(tb, SpaprMachineState, 2), 21224be21d56SDavid Gibson VMSTATE_END_OF_LIST() 21234be21d56SDavid Gibson }, 212462ef3760SMichael Roth .subsections = (const VMStateDescription*[]) { 212562ef3760SMichael Roth &vmstate_spapr_ov5_cas, 21269861bb3eSSuraj Jitindar Singh &vmstate_spapr_patb_entry, 2127fd38804bSDaniel Henrique Barboza &vmstate_spapr_pending_events, 21284e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_htm, 21294e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_vsx, 21304e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_dfp, 21318f38eaf8SSuraj Jitindar Singh &vmstate_spapr_cap_cfpc, 213209114fd8SSuraj Jitindar Singh &vmstate_spapr_cap_sbbc, 21334be8d4e7SSuraj Jitindar Singh &vmstate_spapr_cap_ibs, 213464d4a534SDavid Gibson &vmstate_spapr_cap_hpt_maxpagesize, 213582cffa2eSCédric Le Goater &vmstate_spapr_irq_map, 2136b9a477b7SSuraj Jitindar Singh &vmstate_spapr_cap_nested_kvm_hv, 2137fea35ca4SAlexey Kardashevskiy &vmstate_spapr_dtb, 2138c982f5cfSSuraj Jitindar Singh &vmstate_spapr_cap_large_decr, 21398ff43ee4SSuraj Jitindar Singh &vmstate_spapr_cap_ccf_assist, 214062ef3760SMichael Roth NULL 214162ef3760SMichael Roth } 21424be21d56SDavid Gibson }; 21434be21d56SDavid Gibson 21444be21d56SDavid Gibson static int htab_save_setup(QEMUFile *f, void *opaque) 21454be21d56SDavid Gibson { 2146ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 21474be21d56SDavid Gibson 21484be21d56SDavid Gibson /* "Iteration" header */ 21493a384297SBharata B Rao if (!spapr->htab_shift) { 21503a384297SBharata B Rao qemu_put_be32(f, -1); 21513a384297SBharata B Rao } else { 21524be21d56SDavid Gibson qemu_put_be32(f, spapr->htab_shift); 21533a384297SBharata B Rao } 21544be21d56SDavid Gibson 2155e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 2156e68cb8b4SAlexey Kardashevskiy spapr->htab_save_index = 0; 2157e68cb8b4SAlexey Kardashevskiy spapr->htab_first_pass = true; 2158e68cb8b4SAlexey Kardashevskiy } else { 21593a384297SBharata B Rao if (spapr->htab_shift) { 2160e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 21614be21d56SDavid Gibson } 21623a384297SBharata B Rao } 21634be21d56SDavid Gibson 2164e68cb8b4SAlexey Kardashevskiy 2165e68cb8b4SAlexey Kardashevskiy return 0; 2166e68cb8b4SAlexey Kardashevskiy } 21674be21d56SDavid Gibson 2168ce2918cbSDavid Gibson static void htab_save_chunk(QEMUFile *f, SpaprMachineState *spapr, 2169332f7721SGreg Kurz int chunkstart, int n_valid, int n_invalid) 2170332f7721SGreg Kurz { 2171332f7721SGreg Kurz qemu_put_be32(f, chunkstart); 2172332f7721SGreg Kurz qemu_put_be16(f, n_valid); 2173332f7721SGreg Kurz qemu_put_be16(f, n_invalid); 2174332f7721SGreg Kurz qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 2175332f7721SGreg Kurz HASH_PTE_SIZE_64 * n_valid); 2176332f7721SGreg Kurz } 2177332f7721SGreg Kurz 2178332f7721SGreg Kurz static void htab_save_end_marker(QEMUFile *f) 2179332f7721SGreg Kurz { 2180332f7721SGreg Kurz qemu_put_be32(f, 0); 2181332f7721SGreg Kurz qemu_put_be16(f, 0); 2182332f7721SGreg Kurz qemu_put_be16(f, 0); 2183332f7721SGreg Kurz } 2184332f7721SGreg Kurz 2185ce2918cbSDavid Gibson static void htab_save_first_pass(QEMUFile *f, SpaprMachineState *spapr, 21864be21d56SDavid Gibson int64_t max_ns) 21874be21d56SDavid Gibson { 2188378bc217SDavid Gibson bool has_timeout = max_ns != -1; 21894be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 21904be21d56SDavid Gibson int index = spapr->htab_save_index; 2191bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 21924be21d56SDavid Gibson 21934be21d56SDavid Gibson assert(spapr->htab_first_pass); 21944be21d56SDavid Gibson 21954be21d56SDavid Gibson do { 21964be21d56SDavid Gibson int chunkstart; 21974be21d56SDavid Gibson 21984be21d56SDavid Gibson /* Consume invalid HPTEs */ 21994be21d56SDavid Gibson while ((index < htabslots) 22004be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 22014be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 220224ec2863SMarc-André Lureau index++; 22034be21d56SDavid Gibson } 22044be21d56SDavid Gibson 22054be21d56SDavid Gibson /* Consume valid HPTEs */ 22064be21d56SDavid Gibson chunkstart = index; 2207338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 22084be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 22094be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 221024ec2863SMarc-André Lureau index++; 22114be21d56SDavid Gibson } 22124be21d56SDavid Gibson 22134be21d56SDavid Gibson if (index > chunkstart) { 22144be21d56SDavid Gibson int n_valid = index - chunkstart; 22154be21d56SDavid Gibson 2216332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, 0); 22174be21d56SDavid Gibson 2218378bc217SDavid Gibson if (has_timeout && 2219378bc217SDavid Gibson (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 22204be21d56SDavid Gibson break; 22214be21d56SDavid Gibson } 22224be21d56SDavid Gibson } 22234be21d56SDavid Gibson } while ((index < htabslots) && !qemu_file_rate_limit(f)); 22244be21d56SDavid Gibson 22254be21d56SDavid Gibson if (index >= htabslots) { 22264be21d56SDavid Gibson assert(index == htabslots); 22274be21d56SDavid Gibson index = 0; 22284be21d56SDavid Gibson spapr->htab_first_pass = false; 22294be21d56SDavid Gibson } 22304be21d56SDavid Gibson spapr->htab_save_index = index; 22314be21d56SDavid Gibson } 22324be21d56SDavid Gibson 2233ce2918cbSDavid Gibson static int htab_save_later_pass(QEMUFile *f, SpaprMachineState *spapr, 22344be21d56SDavid Gibson int64_t max_ns) 22354be21d56SDavid Gibson { 22364be21d56SDavid Gibson bool final = max_ns < 0; 22374be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 22384be21d56SDavid Gibson int examined = 0, sent = 0; 22394be21d56SDavid Gibson int index = spapr->htab_save_index; 2240bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 22414be21d56SDavid Gibson 22424be21d56SDavid Gibson assert(!spapr->htab_first_pass); 22434be21d56SDavid Gibson 22444be21d56SDavid Gibson do { 22454be21d56SDavid Gibson int chunkstart, invalidstart; 22464be21d56SDavid Gibson 22474be21d56SDavid Gibson /* Consume non-dirty HPTEs */ 22484be21d56SDavid Gibson while ((index < htabslots) 22494be21d56SDavid Gibson && !HPTE_DIRTY(HPTE(spapr->htab, index))) { 22504be21d56SDavid Gibson index++; 22514be21d56SDavid Gibson examined++; 22524be21d56SDavid Gibson } 22534be21d56SDavid Gibson 22544be21d56SDavid Gibson chunkstart = index; 22554be21d56SDavid Gibson /* Consume valid dirty HPTEs */ 2256338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 22574be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 22584be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 22594be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 22604be21d56SDavid Gibson index++; 22614be21d56SDavid Gibson examined++; 22624be21d56SDavid Gibson } 22634be21d56SDavid Gibson 22644be21d56SDavid Gibson invalidstart = index; 22654be21d56SDavid Gibson /* Consume invalid dirty HPTEs */ 2266338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - invalidstart < 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 if (index > chunkstart) { 22754be21d56SDavid Gibson int n_valid = invalidstart - chunkstart; 22764be21d56SDavid Gibson int n_invalid = index - invalidstart; 22774be21d56SDavid Gibson 2278332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, n_invalid); 22794be21d56SDavid Gibson sent += index - chunkstart; 22804be21d56SDavid Gibson 2281bc72ad67SAlex Bligh if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 22824be21d56SDavid Gibson break; 22834be21d56SDavid Gibson } 22844be21d56SDavid Gibson } 22854be21d56SDavid Gibson 22864be21d56SDavid Gibson if (examined >= htabslots) { 22874be21d56SDavid Gibson break; 22884be21d56SDavid Gibson } 22894be21d56SDavid Gibson 22904be21d56SDavid Gibson if (index >= htabslots) { 22914be21d56SDavid Gibson assert(index == htabslots); 22924be21d56SDavid Gibson index = 0; 22934be21d56SDavid Gibson } 22944be21d56SDavid Gibson } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final)); 22954be21d56SDavid Gibson 22964be21d56SDavid Gibson if (index >= htabslots) { 22974be21d56SDavid Gibson assert(index == htabslots); 22984be21d56SDavid Gibson index = 0; 22994be21d56SDavid Gibson } 23004be21d56SDavid Gibson 23014be21d56SDavid Gibson spapr->htab_save_index = index; 23024be21d56SDavid Gibson 2303e68cb8b4SAlexey Kardashevskiy return (examined >= htabslots) && (sent == 0) ? 1 : 0; 23044be21d56SDavid Gibson } 23054be21d56SDavid Gibson 2306e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS 5000000 /* 5 ms */ 2307e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE 2048 2308e68cb8b4SAlexey Kardashevskiy 23094be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque) 23104be21d56SDavid Gibson { 2311ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2312715c5407SDavid Gibson int fd; 2313e68cb8b4SAlexey Kardashevskiy int rc = 0; 23144be21d56SDavid Gibson 23154be21d56SDavid Gibson /* Iteration header */ 23163a384297SBharata B Rao if (!spapr->htab_shift) { 23173a384297SBharata B Rao qemu_put_be32(f, -1); 2318e8cd4247SLaurent Vivier return 1; 23193a384297SBharata B Rao } else { 23204be21d56SDavid Gibson qemu_put_be32(f, 0); 23213a384297SBharata B Rao } 23224be21d56SDavid Gibson 2323e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2324e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2325e68cb8b4SAlexey Kardashevskiy 2326715c5407SDavid Gibson fd = get_htab_fd(spapr); 2327715c5407SDavid Gibson if (fd < 0) { 2328715c5407SDavid Gibson return fd; 232901a57972SSamuel Mendoza-Jonas } 233001a57972SSamuel Mendoza-Jonas 2331715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); 2332e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2333e68cb8b4SAlexey Kardashevskiy return rc; 2334e68cb8b4SAlexey Kardashevskiy } 2335e68cb8b4SAlexey Kardashevskiy } else if (spapr->htab_first_pass) { 23364be21d56SDavid Gibson htab_save_first_pass(f, spapr, MAX_ITERATION_NS); 23374be21d56SDavid Gibson } else { 2338e68cb8b4SAlexey Kardashevskiy rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS); 23394be21d56SDavid Gibson } 23404be21d56SDavid Gibson 2341332f7721SGreg Kurz htab_save_end_marker(f); 23424be21d56SDavid Gibson 2343e68cb8b4SAlexey Kardashevskiy return rc; 23444be21d56SDavid Gibson } 23454be21d56SDavid Gibson 23464be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque) 23474be21d56SDavid Gibson { 2348ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2349715c5407SDavid Gibson int fd; 23504be21d56SDavid Gibson 23514be21d56SDavid Gibson /* Iteration header */ 23523a384297SBharata B Rao if (!spapr->htab_shift) { 23533a384297SBharata B Rao qemu_put_be32(f, -1); 23543a384297SBharata B Rao return 0; 23553a384297SBharata B Rao } else { 23564be21d56SDavid Gibson qemu_put_be32(f, 0); 23573a384297SBharata B Rao } 23584be21d56SDavid Gibson 2359e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2360e68cb8b4SAlexey Kardashevskiy int rc; 2361e68cb8b4SAlexey Kardashevskiy 2362e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2363e68cb8b4SAlexey Kardashevskiy 2364715c5407SDavid Gibson fd = get_htab_fd(spapr); 2365715c5407SDavid Gibson if (fd < 0) { 2366715c5407SDavid Gibson return fd; 236701a57972SSamuel Mendoza-Jonas } 236801a57972SSamuel Mendoza-Jonas 2369715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1); 2370e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2371e68cb8b4SAlexey Kardashevskiy return rc; 2372e68cb8b4SAlexey Kardashevskiy } 2373e68cb8b4SAlexey Kardashevskiy } else { 2374378bc217SDavid Gibson if (spapr->htab_first_pass) { 2375378bc217SDavid Gibson htab_save_first_pass(f, spapr, -1); 2376378bc217SDavid Gibson } 23774be21d56SDavid Gibson htab_save_later_pass(f, spapr, -1); 2378e68cb8b4SAlexey Kardashevskiy } 23794be21d56SDavid Gibson 23804be21d56SDavid Gibson /* End marker */ 2381332f7721SGreg Kurz htab_save_end_marker(f); 23824be21d56SDavid Gibson 23834be21d56SDavid Gibson return 0; 23844be21d56SDavid Gibson } 23854be21d56SDavid Gibson 23864be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id) 23874be21d56SDavid Gibson { 2388ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 23894be21d56SDavid Gibson uint32_t section_hdr; 2390e68cb8b4SAlexey Kardashevskiy int fd = -1; 239114b0d748SGreg Kurz Error *local_err = NULL; 23924be21d56SDavid Gibson 23934be21d56SDavid Gibson if (version_id < 1 || version_id > 1) { 239498a5d100SDavid Gibson error_report("htab_load() bad version"); 23954be21d56SDavid Gibson return -EINVAL; 23964be21d56SDavid Gibson } 23974be21d56SDavid Gibson 23984be21d56SDavid Gibson section_hdr = qemu_get_be32(f); 23994be21d56SDavid Gibson 24003a384297SBharata B Rao if (section_hdr == -1) { 24013a384297SBharata B Rao spapr_free_hpt(spapr); 24023a384297SBharata B Rao return 0; 24033a384297SBharata B Rao } 24043a384297SBharata B Rao 24054be21d56SDavid Gibson if (section_hdr) { 2406c5f54f3eSDavid Gibson /* First section gives the htab size */ 2407c5f54f3eSDavid Gibson spapr_reallocate_hpt(spapr, section_hdr, &local_err); 2408c5f54f3eSDavid Gibson if (local_err) { 2409c5f54f3eSDavid Gibson error_report_err(local_err); 24104be21d56SDavid Gibson return -EINVAL; 24114be21d56SDavid Gibson } 24124be21d56SDavid Gibson return 0; 24134be21d56SDavid Gibson } 24144be21d56SDavid Gibson 2415e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2416e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2417e68cb8b4SAlexey Kardashevskiy 241814b0d748SGreg Kurz fd = kvmppc_get_htab_fd(true, 0, &local_err); 2419e68cb8b4SAlexey Kardashevskiy if (fd < 0) { 242014b0d748SGreg Kurz error_report_err(local_err); 242182be8e73SGreg Kurz return fd; 2422e68cb8b4SAlexey Kardashevskiy } 2423e68cb8b4SAlexey Kardashevskiy } 2424e68cb8b4SAlexey Kardashevskiy 24254be21d56SDavid Gibson while (true) { 24264be21d56SDavid Gibson uint32_t index; 24274be21d56SDavid Gibson uint16_t n_valid, n_invalid; 24284be21d56SDavid Gibson 24294be21d56SDavid Gibson index = qemu_get_be32(f); 24304be21d56SDavid Gibson n_valid = qemu_get_be16(f); 24314be21d56SDavid Gibson n_invalid = qemu_get_be16(f); 24324be21d56SDavid Gibson 24334be21d56SDavid Gibson if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) { 24344be21d56SDavid Gibson /* End of Stream */ 24354be21d56SDavid Gibson break; 24364be21d56SDavid Gibson } 24374be21d56SDavid Gibson 2438e68cb8b4SAlexey Kardashevskiy if ((index + n_valid + n_invalid) > 24394be21d56SDavid Gibson (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) { 24404be21d56SDavid Gibson /* Bad index in stream */ 244198a5d100SDavid Gibson error_report( 244298a5d100SDavid Gibson "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)", 244398a5d100SDavid Gibson index, n_valid, n_invalid, spapr->htab_shift); 24444be21d56SDavid Gibson return -EINVAL; 24454be21d56SDavid Gibson } 24464be21d56SDavid Gibson 2447e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 24484be21d56SDavid Gibson if (n_valid) { 24494be21d56SDavid Gibson qemu_get_buffer(f, HPTE(spapr->htab, index), 24504be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 24514be21d56SDavid Gibson } 24524be21d56SDavid Gibson if (n_invalid) { 24534be21d56SDavid Gibson memset(HPTE(spapr->htab, index + n_valid), 0, 24544be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_invalid); 24554be21d56SDavid Gibson } 2456e68cb8b4SAlexey Kardashevskiy } else { 2457e68cb8b4SAlexey Kardashevskiy int rc; 2458e68cb8b4SAlexey Kardashevskiy 2459e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2460e68cb8b4SAlexey Kardashevskiy 2461e68cb8b4SAlexey Kardashevskiy rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid); 2462e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2463e68cb8b4SAlexey Kardashevskiy return rc; 2464e68cb8b4SAlexey Kardashevskiy } 2465e68cb8b4SAlexey Kardashevskiy } 2466e68cb8b4SAlexey Kardashevskiy } 2467e68cb8b4SAlexey Kardashevskiy 2468e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2469e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2470e68cb8b4SAlexey Kardashevskiy close(fd); 24714be21d56SDavid Gibson } 24724be21d56SDavid Gibson 24734be21d56SDavid Gibson return 0; 24744be21d56SDavid Gibson } 24754be21d56SDavid Gibson 247670f794fcSJuan Quintela static void htab_save_cleanup(void *opaque) 2477c573fc03SThomas Huth { 2478ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2479c573fc03SThomas Huth 2480c573fc03SThomas Huth close_htab_fd(spapr); 2481c573fc03SThomas Huth } 2482c573fc03SThomas Huth 24834be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = { 24849907e842SJuan Quintela .save_setup = htab_save_setup, 24854be21d56SDavid Gibson .save_live_iterate = htab_save_iterate, 2486a3e06c3dSDr. David Alan Gilbert .save_live_complete_precopy = htab_save_complete, 248770f794fcSJuan Quintela .save_cleanup = htab_save_cleanup, 24884be21d56SDavid Gibson .load_state = htab_load, 24894be21d56SDavid Gibson }; 24904be21d56SDavid Gibson 24915b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device, 24925b2128d2SAlexander Graf Error **errp) 24935b2128d2SAlexander Graf { 2494c86c1affSDaniel Henrique Barboza MachineState *machine = MACHINE(opaque); 24955b2128d2SAlexander Graf machine->boot_order = g_strdup(boot_device); 24965b2128d2SAlexander Graf } 24975b2128d2SAlexander Graf 2498ce2918cbSDavid Gibson static void spapr_create_lmb_dr_connectors(SpaprMachineState *spapr) 2499224245bfSDavid Gibson { 2500224245bfSDavid Gibson MachineState *machine = MACHINE(spapr); 2501224245bfSDavid Gibson uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 2502e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 2503224245bfSDavid Gibson int i; 2504224245bfSDavid Gibson 2505224245bfSDavid Gibson for (i = 0; i < nr_lmbs; i++) { 2506224245bfSDavid Gibson uint64_t addr; 2507224245bfSDavid Gibson 2508b0c14ec4SDavid Hildenbrand addr = i * lmb_size + machine->device_memory->base; 25096caf3ac6SDavid Gibson spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_LMB, 2510224245bfSDavid Gibson addr / lmb_size); 2511224245bfSDavid Gibson } 2512224245bfSDavid Gibson } 2513224245bfSDavid Gibson 2514224245bfSDavid Gibson /* 2515224245bfSDavid Gibson * If RAM size, maxmem size and individual node mem sizes aren't aligned 2516224245bfSDavid Gibson * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest 2517224245bfSDavid Gibson * since we can't support such unaligned sizes with DRCONF_MEMORY. 2518224245bfSDavid Gibson */ 25197c150d6fSDavid Gibson static void spapr_validate_node_memory(MachineState *machine, Error **errp) 2520224245bfSDavid Gibson { 2521224245bfSDavid Gibson int i; 2522224245bfSDavid Gibson 25237c150d6fSDavid Gibson if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) { 25247c150d6fSDavid Gibson error_setg(errp, "Memory size 0x" RAM_ADDR_FMT 2525ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 25267c150d6fSDavid Gibson machine->ram_size, 2527d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 25287c150d6fSDavid Gibson return; 25297c150d6fSDavid Gibson } 25307c150d6fSDavid Gibson 25317c150d6fSDavid Gibson if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) { 25327c150d6fSDavid Gibson error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT 2533ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 25347c150d6fSDavid Gibson machine->ram_size, 2535d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 25367c150d6fSDavid Gibson return; 2537224245bfSDavid Gibson } 2538224245bfSDavid Gibson 2539aa570207STao Xu for (i = 0; i < machine->numa_state->num_nodes; i++) { 25407e721e7bSTao Xu if (machine->numa_state->nodes[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) { 25417c150d6fSDavid Gibson error_setg(errp, 25427c150d6fSDavid Gibson "Node %d memory size 0x%" PRIx64 2543ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 25447e721e7bSTao Xu i, machine->numa_state->nodes[i].node_mem, 2545d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 25467c150d6fSDavid Gibson return; 2547224245bfSDavid Gibson } 2548224245bfSDavid Gibson } 2549224245bfSDavid Gibson } 2550224245bfSDavid Gibson 2551535455fdSIgor Mammedov /* find cpu slot in machine->possible_cpus by core_id */ 2552535455fdSIgor Mammedov static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx) 2553535455fdSIgor Mammedov { 2554fe6b6346SLike Xu int index = id / ms->smp.threads; 2555535455fdSIgor Mammedov 2556535455fdSIgor Mammedov if (index >= ms->possible_cpus->len) { 2557535455fdSIgor Mammedov return NULL; 2558535455fdSIgor Mammedov } 2559535455fdSIgor Mammedov if (idx) { 2560535455fdSIgor Mammedov *idx = index; 2561535455fdSIgor Mammedov } 2562535455fdSIgor Mammedov return &ms->possible_cpus->cpus[index]; 2563535455fdSIgor Mammedov } 2564535455fdSIgor Mammedov 2565ce2918cbSDavid Gibson static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp) 2566fa98fbfcSSam Bobroff { 2567fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 2568fa98fbfcSSam Bobroff Error *local_err = NULL; 2569fa98fbfcSSam Bobroff bool vsmt_user = !!spapr->vsmt; 2570fa98fbfcSSam Bobroff int kvm_smt = kvmppc_smt_threads(); 2571fa98fbfcSSam Bobroff int ret; 2572fe6b6346SLike Xu unsigned int smp_threads = ms->smp.threads; 2573fa98fbfcSSam Bobroff 2574fa98fbfcSSam Bobroff if (!kvm_enabled() && (smp_threads > 1)) { 2575fa98fbfcSSam Bobroff error_setg(&local_err, "TCG cannot support more than 1 thread/core " 2576fa98fbfcSSam Bobroff "on a pseries machine"); 2577fa98fbfcSSam Bobroff goto out; 2578fa98fbfcSSam Bobroff } 2579fa98fbfcSSam Bobroff if (!is_power_of_2(smp_threads)) { 2580fa98fbfcSSam Bobroff error_setg(&local_err, "Cannot support %d threads/core on a pseries " 2581fa98fbfcSSam Bobroff "machine because it must be a power of 2", smp_threads); 2582fa98fbfcSSam Bobroff goto out; 2583fa98fbfcSSam Bobroff } 2584fa98fbfcSSam Bobroff 2585fa98fbfcSSam Bobroff /* Detemine the VSMT mode to use: */ 2586fa98fbfcSSam Bobroff if (vsmt_user) { 2587fa98fbfcSSam Bobroff if (spapr->vsmt < smp_threads) { 2588fa98fbfcSSam Bobroff error_setg(&local_err, "Cannot support VSMT mode %d" 2589fa98fbfcSSam Bobroff " because it must be >= threads/core (%d)", 2590fa98fbfcSSam Bobroff spapr->vsmt, smp_threads); 2591fa98fbfcSSam Bobroff goto out; 2592fa98fbfcSSam Bobroff } 2593fa98fbfcSSam Bobroff /* In this case, spapr->vsmt has been set by the command line */ 2594fa98fbfcSSam Bobroff } else { 25958904e5a7SDavid Gibson /* 25968904e5a7SDavid Gibson * Default VSMT value is tricky, because we need it to be as 25978904e5a7SDavid Gibson * consistent as possible (for migration), but this requires 25988904e5a7SDavid Gibson * changing it for at least some existing cases. We pick 8 as 25998904e5a7SDavid Gibson * the value that we'd get with KVM on POWER8, the 26008904e5a7SDavid Gibson * overwhelmingly common case in production systems. 26018904e5a7SDavid Gibson */ 26024ad64cbdSLaurent Vivier spapr->vsmt = MAX(8, smp_threads); 2603fa98fbfcSSam Bobroff } 2604fa98fbfcSSam Bobroff 2605fa98fbfcSSam Bobroff /* KVM: If necessary, set the SMT mode: */ 2606fa98fbfcSSam Bobroff if (kvm_enabled() && (spapr->vsmt != kvm_smt)) { 2607fa98fbfcSSam Bobroff ret = kvmppc_set_smt_threads(spapr->vsmt); 2608fa98fbfcSSam Bobroff if (ret) { 26091f20f2e0SDavid Gibson /* Looks like KVM isn't able to change VSMT mode */ 2610fa98fbfcSSam Bobroff error_setg(&local_err, 2611fa98fbfcSSam Bobroff "Failed to set KVM's VSMT mode to %d (errno %d)", 2612fa98fbfcSSam Bobroff spapr->vsmt, ret); 26131f20f2e0SDavid Gibson /* We can live with that if the default one is big enough 26141f20f2e0SDavid Gibson * for the number of threads, and a submultiple of the one 26151f20f2e0SDavid Gibson * we want. In this case we'll waste some vcpu ids, but 26161f20f2e0SDavid Gibson * behaviour will be correct */ 26171f20f2e0SDavid Gibson if ((kvm_smt >= smp_threads) && ((spapr->vsmt % kvm_smt) == 0)) { 26181f20f2e0SDavid Gibson warn_report_err(local_err); 26191f20f2e0SDavid Gibson local_err = NULL; 26201f20f2e0SDavid Gibson goto out; 26211f20f2e0SDavid Gibson } else { 2622fa98fbfcSSam Bobroff if (!vsmt_user) { 26231f20f2e0SDavid Gibson error_append_hint(&local_err, 26241f20f2e0SDavid Gibson "On PPC, a VM with %d threads/core" 26251f20f2e0SDavid Gibson " on a host with %d threads/core" 26261f20f2e0SDavid Gibson " requires the use of VSMT mode %d.\n", 2627fa98fbfcSSam Bobroff smp_threads, kvm_smt, spapr->vsmt); 2628fa98fbfcSSam Bobroff } 2629fa98fbfcSSam Bobroff kvmppc_hint_smt_possible(&local_err); 2630fa98fbfcSSam Bobroff goto out; 2631fa98fbfcSSam Bobroff } 2632fa98fbfcSSam Bobroff } 26331f20f2e0SDavid Gibson } 2634fa98fbfcSSam Bobroff /* else TCG: nothing to do currently */ 2635fa98fbfcSSam Bobroff out: 2636fa98fbfcSSam Bobroff error_propagate(errp, local_err); 2637fa98fbfcSSam Bobroff } 2638fa98fbfcSSam Bobroff 2639ce2918cbSDavid Gibson static void spapr_init_cpus(SpaprMachineState *spapr) 26401a5008fcSGreg Kurz { 26411a5008fcSGreg Kurz MachineState *machine = MACHINE(spapr); 26421a5008fcSGreg Kurz MachineClass *mc = MACHINE_GET_CLASS(machine); 2643ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 26441a5008fcSGreg Kurz const char *type = spapr_get_cpu_core_type(machine->cpu_type); 26451a5008fcSGreg Kurz const CPUArchIdList *possible_cpus; 2646fe6b6346SLike Xu unsigned int smp_cpus = machine->smp.cpus; 2647fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 2648fe6b6346SLike Xu unsigned int max_cpus = machine->smp.max_cpus; 26491a5008fcSGreg Kurz int boot_cores_nr = smp_cpus / smp_threads; 26501a5008fcSGreg Kurz int i; 26511a5008fcSGreg Kurz 26521a5008fcSGreg Kurz possible_cpus = mc->possible_cpu_arch_ids(machine); 26531a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 26541a5008fcSGreg Kurz if (smp_cpus % smp_threads) { 26551a5008fcSGreg Kurz error_report("smp_cpus (%u) must be multiple of threads (%u)", 26561a5008fcSGreg Kurz smp_cpus, smp_threads); 26571a5008fcSGreg Kurz exit(1); 26581a5008fcSGreg Kurz } 26591a5008fcSGreg Kurz if (max_cpus % smp_threads) { 26601a5008fcSGreg Kurz error_report("max_cpus (%u) must be multiple of threads (%u)", 26611a5008fcSGreg Kurz max_cpus, smp_threads); 26621a5008fcSGreg Kurz exit(1); 26631a5008fcSGreg Kurz } 26641a5008fcSGreg Kurz } else { 26651a5008fcSGreg Kurz if (max_cpus != smp_cpus) { 26661a5008fcSGreg Kurz error_report("This machine version does not support CPU hotplug"); 26671a5008fcSGreg Kurz exit(1); 26681a5008fcSGreg Kurz } 26691a5008fcSGreg Kurz boot_cores_nr = possible_cpus->len; 26701a5008fcSGreg Kurz } 26711a5008fcSGreg Kurz 26721a5008fcSGreg Kurz if (smc->pre_2_10_has_unused_icps) { 26731a5008fcSGreg Kurz int i; 26741a5008fcSGreg Kurz 26751a518e76SCédric Le Goater for (i = 0; i < spapr_max_server_number(spapr); i++) { 26761a5008fcSGreg Kurz /* Dummy entries get deregistered when real ICPState objects 26771a5008fcSGreg Kurz * are registered during CPU core hotplug. 26781a5008fcSGreg Kurz */ 26791a5008fcSGreg Kurz pre_2_10_vmstate_register_dummy_icp(i); 26801a5008fcSGreg Kurz } 26811a5008fcSGreg Kurz } 26821a5008fcSGreg Kurz 26831a5008fcSGreg Kurz for (i = 0; i < possible_cpus->len; i++) { 26841a5008fcSGreg Kurz int core_id = i * smp_threads; 26851a5008fcSGreg Kurz 26861a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 26871a5008fcSGreg Kurz spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU, 26881a5008fcSGreg Kurz spapr_vcpu_id(spapr, core_id)); 26891a5008fcSGreg Kurz } 26901a5008fcSGreg Kurz 26911a5008fcSGreg Kurz if (i < boot_cores_nr) { 26921a5008fcSGreg Kurz Object *core = object_new(type); 26931a5008fcSGreg Kurz int nr_threads = smp_threads; 26941a5008fcSGreg Kurz 26951a5008fcSGreg Kurz /* Handle the partially filled core for older machine types */ 26961a5008fcSGreg Kurz if ((i + 1) * smp_threads >= smp_cpus) { 26971a5008fcSGreg Kurz nr_threads = smp_cpus - i * smp_threads; 26981a5008fcSGreg Kurz } 26991a5008fcSGreg Kurz 27001a5008fcSGreg Kurz object_property_set_int(core, nr_threads, "nr-threads", 27011a5008fcSGreg Kurz &error_fatal); 27021a5008fcSGreg Kurz object_property_set_int(core, core_id, CPU_CORE_PROP_CORE_ID, 27031a5008fcSGreg Kurz &error_fatal); 27041a5008fcSGreg Kurz object_property_set_bool(core, true, "realized", &error_fatal); 2705ecda255eSSam Bobroff 2706ecda255eSSam Bobroff object_unref(core); 27071a5008fcSGreg Kurz } 27081a5008fcSGreg Kurz } 27091a5008fcSGreg Kurz } 27101a5008fcSGreg Kurz 2711999c9cafSGreg Kurz static PCIHostState *spapr_create_default_phb(void) 2712999c9cafSGreg Kurz { 2713999c9cafSGreg Kurz DeviceState *dev; 2714999c9cafSGreg Kurz 2715999c9cafSGreg Kurz dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE); 2716999c9cafSGreg Kurz qdev_prop_set_uint32(dev, "index", 0); 2717999c9cafSGreg Kurz qdev_init_nofail(dev); 2718999c9cafSGreg Kurz 2719999c9cafSGreg Kurz return PCI_HOST_BRIDGE(dev); 2720999c9cafSGreg Kurz } 2721999c9cafSGreg Kurz 272253018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */ 2723bcb5ce08SDavid Gibson static void spapr_machine_init(MachineState *machine) 272453018216SPaolo Bonzini { 2725ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(machine); 2726ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 27273ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 27283ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 272953018216SPaolo Bonzini PCIHostState *phb; 273053018216SPaolo Bonzini int i; 273153018216SPaolo Bonzini MemoryRegion *sysmem = get_system_memory(); 273253018216SPaolo Bonzini MemoryRegion *ram = g_new(MemoryRegion, 1); 2733c86c1affSDaniel Henrique Barboza hwaddr node0_size = spapr_node0_size(machine); 2734b7d1f77aSBenjamin Herrenschmidt long load_limit, fw_size; 273553018216SPaolo Bonzini char *filename; 273630f4b05bSDavid Gibson Error *resize_hpt_err = NULL; 273753018216SPaolo Bonzini 2738226419d6SMichael S. Tsirkin msi_nonbroken = true; 273953018216SPaolo Bonzini 274053018216SPaolo Bonzini QLIST_INIT(&spapr->phbs); 27410cffce56SDavid Gibson QTAILQ_INIT(&spapr->pending_dimm_unplugs); 274253018216SPaolo Bonzini 27439f6edd06SDavid Gibson /* Determine capabilities to run with */ 27449f6edd06SDavid Gibson spapr_caps_init(spapr); 27459f6edd06SDavid Gibson 274630f4b05bSDavid Gibson kvmppc_check_papr_resize_hpt(&resize_hpt_err); 274730f4b05bSDavid Gibson if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) { 274830f4b05bSDavid Gibson /* 274930f4b05bSDavid Gibson * If the user explicitly requested a mode we should either 275030f4b05bSDavid Gibson * supply it, or fail completely (which we do below). But if 275130f4b05bSDavid Gibson * it's not set explicitly, we reset our mode to something 275230f4b05bSDavid Gibson * that works 275330f4b05bSDavid Gibson */ 275430f4b05bSDavid Gibson if (resize_hpt_err) { 275530f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 275630f4b05bSDavid Gibson error_free(resize_hpt_err); 275730f4b05bSDavid Gibson resize_hpt_err = NULL; 275830f4b05bSDavid Gibson } else { 275930f4b05bSDavid Gibson spapr->resize_hpt = smc->resize_hpt_default; 276030f4b05bSDavid Gibson } 276130f4b05bSDavid Gibson } 276230f4b05bSDavid Gibson 276330f4b05bSDavid Gibson assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT); 276430f4b05bSDavid Gibson 276530f4b05bSDavid Gibson if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && resize_hpt_err) { 276630f4b05bSDavid Gibson /* 276730f4b05bSDavid Gibson * User requested HPT resize, but this host can't supply it. Bail out 276830f4b05bSDavid Gibson */ 276930f4b05bSDavid Gibson error_report_err(resize_hpt_err); 277030f4b05bSDavid Gibson exit(1); 277130f4b05bSDavid Gibson } 277230f4b05bSDavid Gibson 2773c4177479SAlexey Kardashevskiy spapr->rma_size = node0_size; 277453018216SPaolo Bonzini 277553018216SPaolo Bonzini /* With KVM, we don't actually know whether KVM supports an 277653018216SPaolo Bonzini * unbounded RMA (PR KVM) or is limited by the hash table size 277753018216SPaolo Bonzini * (HV KVM using VRMA), so we always assume the latter 277853018216SPaolo Bonzini * 277953018216SPaolo Bonzini * In that case, we also limit the initial allocations for RTAS 278053018216SPaolo Bonzini * etc... to 256M since we have no way to know what the VRMA size 278153018216SPaolo Bonzini * is going to be as it depends on the size of the hash table 2782090052aaSDavid Gibson * which isn't determined yet. 278353018216SPaolo Bonzini */ 278453018216SPaolo Bonzini if (kvm_enabled()) { 278553018216SPaolo Bonzini spapr->vrma_adjust = 1; 278653018216SPaolo Bonzini spapr->rma_size = MIN(spapr->rma_size, 0x10000000); 278753018216SPaolo Bonzini } 2788912acdf4SBenjamin Herrenschmidt 2789090052aaSDavid Gibson /* Actually we don't support unbounded RMA anymore since we added 2790090052aaSDavid Gibson * proper emulation of HV mode. The max we can get is 16G which 2791090052aaSDavid Gibson * also happens to be what we configure for PAPR mode so make sure 2792090052aaSDavid Gibson * we don't do anything bigger than that 2793912acdf4SBenjamin Herrenschmidt */ 2794912acdf4SBenjamin Herrenschmidt spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull); 279553018216SPaolo Bonzini 2796c4177479SAlexey Kardashevskiy if (spapr->rma_size > node0_size) { 2797d54e4d76SDavid Gibson error_report("Numa node 0 has to span the RMA (%#08"HWADDR_PRIx")", 2798c4177479SAlexey Kardashevskiy spapr->rma_size); 2799c4177479SAlexey Kardashevskiy exit(1); 2800c4177479SAlexey Kardashevskiy } 2801c4177479SAlexey Kardashevskiy 2802b7d1f77aSBenjamin Herrenschmidt /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */ 2803b7d1f77aSBenjamin Herrenschmidt load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; 280453018216SPaolo Bonzini 2805482969d6SCédric Le Goater /* 2806482969d6SCédric Le Goater * VSMT must be set in order to be able to compute VCPU ids, ie to 28071a518e76SCédric Le Goater * call spapr_max_server_number() or spapr_vcpu_id(). 2808482969d6SCédric Le Goater */ 2809482969d6SCédric Le Goater spapr_set_vsmt_mode(spapr, &error_fatal); 2810482969d6SCédric Le Goater 28117b565160SDavid Gibson /* Set up Interrupt Controller before we create the VCPUs */ 2812fab397d8SCédric Le Goater spapr_irq_init(spapr, &error_fatal); 28137b565160SDavid Gibson 2814dc1b5eeeSGreg Kurz /* Set up containers for ibm,client-architecture-support negotiated options 2815dc1b5eeeSGreg Kurz */ 2816facdb8b6SMichael Roth spapr->ov5 = spapr_ovec_new(); 2817facdb8b6SMichael Roth spapr->ov5_cas = spapr_ovec_new(); 2818facdb8b6SMichael Roth 2819224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2820facdb8b6SMichael Roth spapr_ovec_set(spapr->ov5, OV5_DRCONF_MEMORY); 28217c150d6fSDavid Gibson spapr_validate_node_memory(machine, &error_fatal); 2822224245bfSDavid Gibson } 2823224245bfSDavid Gibson 2824417ece33SMichael Roth spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY); 2825417ece33SMichael Roth 2826ffbb1705SMichael Roth /* advertise support for dedicated HP event source to guests */ 2827ffbb1705SMichael Roth if (spapr->use_hotplug_event_source) { 2828ffbb1705SMichael Roth spapr_ovec_set(spapr->ov5, OV5_HP_EVT); 2829ffbb1705SMichael Roth } 2830ffbb1705SMichael Roth 28312772cf6bSDavid Gibson /* advertise support for HPT resizing */ 28322772cf6bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { 28332772cf6bSDavid Gibson spapr_ovec_set(spapr->ov5, OV5_HPT_RESIZE); 28342772cf6bSDavid Gibson } 28352772cf6bSDavid Gibson 2836a324d6f1SBharata B Rao /* advertise support for ibm,dyamic-memory-v2 */ 2837a324d6f1SBharata B Rao spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2); 2838a324d6f1SBharata B Rao 2839db592b5bSCédric Le Goater /* advertise XIVE on POWER9 machines */ 284013db0cd9SCédric Le Goater if (spapr->irq->ov5 & (SPAPR_OV5_XIVE_EXPLOIT | SPAPR_OV5_XIVE_BOTH)) { 2841db592b5bSCédric Le Goater spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT); 2842db592b5bSCédric Le Goater } 2843db592b5bSCédric Le Goater 284453018216SPaolo Bonzini /* init CPUs */ 28450c86d0fdSDavid Gibson spapr_init_cpus(spapr); 284653018216SPaolo Bonzini 284758c46efaSLaurent Vivier /* 284858c46efaSLaurent Vivier * check we don't have a memory-less/cpu-less NUMA node 284958c46efaSLaurent Vivier * Firmware relies on the existing memory/cpu topology to provide the 285058c46efaSLaurent Vivier * NUMA topology to the kernel. 285158c46efaSLaurent Vivier * And the linux kernel needs to know the NUMA topology at start 285258c46efaSLaurent Vivier * to be able to hotplug CPUs later. 285358c46efaSLaurent Vivier */ 285458c46efaSLaurent Vivier if (machine->numa_state->num_nodes) { 285558c46efaSLaurent Vivier for (i = 0; i < machine->numa_state->num_nodes; ++i) { 285658c46efaSLaurent Vivier /* check for memory-less node */ 285758c46efaSLaurent Vivier if (machine->numa_state->nodes[i].node_mem == 0) { 285858c46efaSLaurent Vivier CPUState *cs; 285958c46efaSLaurent Vivier int found = 0; 286058c46efaSLaurent Vivier /* check for cpu-less node */ 286158c46efaSLaurent Vivier CPU_FOREACH(cs) { 286258c46efaSLaurent Vivier PowerPCCPU *cpu = POWERPC_CPU(cs); 286358c46efaSLaurent Vivier if (cpu->node_id == i) { 286458c46efaSLaurent Vivier found = 1; 286558c46efaSLaurent Vivier break; 286658c46efaSLaurent Vivier } 286758c46efaSLaurent Vivier } 286858c46efaSLaurent Vivier /* memory-less and cpu-less node */ 286958c46efaSLaurent Vivier if (!found) { 287058c46efaSLaurent Vivier error_report( 287158c46efaSLaurent Vivier "Memory-less/cpu-less nodes are not supported (node %d)", 287258c46efaSLaurent Vivier i); 287358c46efaSLaurent Vivier exit(1); 287458c46efaSLaurent Vivier } 287558c46efaSLaurent Vivier } 287658c46efaSLaurent Vivier } 287758c46efaSLaurent Vivier 287858c46efaSLaurent Vivier } 287958c46efaSLaurent Vivier 2880*db5127b2SDavid Gibson /* 2881*db5127b2SDavid Gibson * NVLink2-connected GPU RAM needs to be placed on a separate NUMA node. 2882*db5127b2SDavid Gibson * We assign a new numa ID per GPU in spapr_pci_collect_nvgpu() which is 2883*db5127b2SDavid Gibson * called from vPHB reset handler so we initialize the counter here. 2884*db5127b2SDavid Gibson * If no NUMA is configured from the QEMU side, we start from 1 as GPU RAM 2885*db5127b2SDavid Gibson * must be equally distant from any other node. 2886*db5127b2SDavid Gibson * The final value of spapr->gpu_numa_id is going to be written to 2887*db5127b2SDavid Gibson * max-associativity-domains in spapr_build_fdt(). 2888*db5127b2SDavid Gibson */ 2889*db5127b2SDavid Gibson spapr->gpu_numa_id = MAX(1, machine->numa_state->num_nodes); 2890*db5127b2SDavid Gibson 28910550b120SGreg Kurz if ((!kvm_enabled() || kvmppc_has_cap_mmu_radix()) && 2892ad99d04cSDavid Gibson ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, 28930550b120SGreg Kurz spapr->max_compat_pvr)) { 28940550b120SGreg Kurz /* KVM and TCG always allow GTSE with radix... */ 28950550b120SGreg Kurz spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE); 28960550b120SGreg Kurz } 28970550b120SGreg Kurz /* ... but not with hash (currently). */ 28980550b120SGreg Kurz 2899026bfd89SDavid Gibson if (kvm_enabled()) { 2900026bfd89SDavid Gibson /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ 2901026bfd89SDavid Gibson kvmppc_enable_logical_ci_hcalls(); 2902ef9971ddSAlexey Kardashevskiy kvmppc_enable_set_mode_hcall(); 29035145ad4fSNathan Whitehorn 29045145ad4fSNathan Whitehorn /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */ 29055145ad4fSNathan Whitehorn kvmppc_enable_clear_ref_mod_hcalls(); 290668f9f708SSuraj Jitindar Singh 290768f9f708SSuraj Jitindar Singh /* Enable H_PAGE_INIT */ 290868f9f708SSuraj Jitindar Singh kvmppc_enable_h_page_init(); 2909026bfd89SDavid Gibson } 2910026bfd89SDavid Gibson 291153018216SPaolo Bonzini /* allocate RAM */ 2912f92f5da1SAlexey Kardashevskiy memory_region_allocate_system_memory(ram, NULL, "ppc_spapr.ram", 2913fb164994SDavid Gibson machine->ram_size); 2914f92f5da1SAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, ram); 291553018216SPaolo Bonzini 2916b0c14ec4SDavid Hildenbrand /* always allocate the device memory information */ 2917b0c14ec4SDavid Hildenbrand machine->device_memory = g_malloc0(sizeof(*machine->device_memory)); 2918b0c14ec4SDavid Hildenbrand 29194a1c9cf0SBharata B Rao /* initialize hotplug memory address space */ 29204a1c9cf0SBharata B Rao if (machine->ram_size < machine->maxram_size) { 29210c9269a5SDavid Hildenbrand ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size; 292271c9a3ddSBharata B Rao /* 292371c9a3ddSBharata B Rao * Limit the number of hotpluggable memory slots to half the number 292471c9a3ddSBharata B Rao * slots that KVM supports, leaving the other half for PCI and other 292571c9a3ddSBharata B Rao * devices. However ensure that number of slots doesn't drop below 32. 292671c9a3ddSBharata B Rao */ 292771c9a3ddSBharata B Rao int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 : 292871c9a3ddSBharata B Rao SPAPR_MAX_RAM_SLOTS; 29294a1c9cf0SBharata B Rao 293071c9a3ddSBharata B Rao if (max_memslots < SPAPR_MAX_RAM_SLOTS) { 293171c9a3ddSBharata B Rao max_memslots = SPAPR_MAX_RAM_SLOTS; 293271c9a3ddSBharata B Rao } 293371c9a3ddSBharata B Rao if (machine->ram_slots > max_memslots) { 2934d54e4d76SDavid Gibson error_report("Specified number of memory slots %" 2935d54e4d76SDavid Gibson PRIu64" exceeds max supported %d", 293671c9a3ddSBharata B Rao machine->ram_slots, max_memslots); 2937d54e4d76SDavid Gibson exit(1); 29384a1c9cf0SBharata B Rao } 29394a1c9cf0SBharata B Rao 2940b0c14ec4SDavid Hildenbrand machine->device_memory->base = ROUND_UP(machine->ram_size, 29410c9269a5SDavid Hildenbrand SPAPR_DEVICE_MEM_ALIGN); 2942b0c14ec4SDavid Hildenbrand memory_region_init(&machine->device_memory->mr, OBJECT(spapr), 29430c9269a5SDavid Hildenbrand "device-memory", device_mem_size); 2944b0c14ec4SDavid Hildenbrand memory_region_add_subregion(sysmem, machine->device_memory->base, 2945b0c14ec4SDavid Hildenbrand &machine->device_memory->mr); 29464a1c9cf0SBharata B Rao } 29474a1c9cf0SBharata B Rao 2948224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2949224245bfSDavid Gibson spapr_create_lmb_dr_connectors(spapr); 2950224245bfSDavid Gibson } 2951224245bfSDavid Gibson 295253018216SPaolo Bonzini filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin"); 29534c56440dSStefan Weil if (!filename) { 2954730fce59SThomas Huth error_report("Could not find LPAR rtas '%s'", "spapr-rtas.bin"); 29554c56440dSStefan Weil exit(1); 29564c56440dSStefan Weil } 2957b7d1f77aSBenjamin Herrenschmidt spapr->rtas_size = get_image_size(filename); 29588afc22a2SZhou Jie if (spapr->rtas_size < 0) { 29598afc22a2SZhou Jie error_report("Could not get size of LPAR rtas '%s'", filename); 29608afc22a2SZhou Jie exit(1); 29618afc22a2SZhou Jie } 2962b7d1f77aSBenjamin Herrenschmidt spapr->rtas_blob = g_malloc(spapr->rtas_size); 2963b7d1f77aSBenjamin Herrenschmidt if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) { 2964730fce59SThomas Huth error_report("Could not load LPAR rtas '%s'", filename); 296553018216SPaolo Bonzini exit(1); 296653018216SPaolo Bonzini } 296753018216SPaolo Bonzini if (spapr->rtas_size > RTAS_MAX_SIZE) { 2968730fce59SThomas Huth error_report("RTAS too big ! 0x%zx bytes (max is 0x%x)", 29692f285bddSPeter Maydell (size_t)spapr->rtas_size, RTAS_MAX_SIZE); 297053018216SPaolo Bonzini exit(1); 297153018216SPaolo Bonzini } 297253018216SPaolo Bonzini g_free(filename); 297353018216SPaolo Bonzini 2974ffbb1705SMichael Roth /* Set up RTAS event infrastructure */ 297553018216SPaolo Bonzini spapr_events_init(spapr); 297653018216SPaolo Bonzini 297712f42174SDavid Gibson /* Set up the RTC RTAS interfaces */ 297828df36a1SDavid Gibson spapr_rtc_create(spapr); 297912f42174SDavid Gibson 298053018216SPaolo Bonzini /* Set up VIO bus */ 298153018216SPaolo Bonzini spapr->vio_bus = spapr_vio_bus_init(); 298253018216SPaolo Bonzini 2983b8846a4dSPeter Maydell for (i = 0; i < serial_max_hds(); i++) { 29849bca0edbSPeter Maydell if (serial_hd(i)) { 29859bca0edbSPeter Maydell spapr_vty_create(spapr->vio_bus, serial_hd(i)); 298653018216SPaolo Bonzini } 298753018216SPaolo Bonzini } 298853018216SPaolo Bonzini 298953018216SPaolo Bonzini /* We always have at least the nvram device on VIO */ 299053018216SPaolo Bonzini spapr_create_nvram(spapr); 299153018216SPaolo Bonzini 2992962b6c36SMichael Roth /* 2993962b6c36SMichael Roth * Setup hotplug / dynamic-reconfiguration connectors. top-level 2994962b6c36SMichael Roth * connectors (described in root DT node's "ibm,drc-types" property) 2995962b6c36SMichael Roth * are pre-initialized here. additional child connectors (such as 2996962b6c36SMichael Roth * connectors for a PHBs PCI slots) are added as needed during their 2997962b6c36SMichael Roth * parent's realization. 2998962b6c36SMichael Roth */ 2999962b6c36SMichael Roth if (smc->dr_phb_enabled) { 3000962b6c36SMichael Roth for (i = 0; i < SPAPR_MAX_PHBS; i++) { 3001962b6c36SMichael Roth spapr_dr_connector_new(OBJECT(machine), TYPE_SPAPR_DRC_PHB, i); 3002962b6c36SMichael Roth } 3003962b6c36SMichael Roth } 3004962b6c36SMichael Roth 300553018216SPaolo Bonzini /* Set up PCI */ 300653018216SPaolo Bonzini spapr_pci_rtas_init(); 300753018216SPaolo Bonzini 3008999c9cafSGreg Kurz phb = spapr_create_default_phb(); 300953018216SPaolo Bonzini 301053018216SPaolo Bonzini for (i = 0; i < nb_nics; i++) { 301153018216SPaolo Bonzini NICInfo *nd = &nd_table[i]; 301253018216SPaolo Bonzini 301353018216SPaolo Bonzini if (!nd->model) { 30143c3a4e7aSThomas Huth nd->model = g_strdup("spapr-vlan"); 301553018216SPaolo Bonzini } 301653018216SPaolo Bonzini 30173c3a4e7aSThomas Huth if (g_str_equal(nd->model, "spapr-vlan") || 30183c3a4e7aSThomas Huth g_str_equal(nd->model, "ibmveth")) { 301953018216SPaolo Bonzini spapr_vlan_create(spapr->vio_bus, nd); 302053018216SPaolo Bonzini } else { 302129b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL); 302253018216SPaolo Bonzini } 302353018216SPaolo Bonzini } 302453018216SPaolo Bonzini 302553018216SPaolo Bonzini for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { 302653018216SPaolo Bonzini spapr_vscsi_create(spapr->vio_bus); 302753018216SPaolo Bonzini } 302853018216SPaolo Bonzini 302953018216SPaolo Bonzini /* Graphics */ 303014c6a894SDavid Gibson if (spapr_vga_init(phb->bus, &error_fatal)) { 303153018216SPaolo Bonzini spapr->has_graphics = true; 3032c6e76503SPaolo Bonzini machine->usb |= defaults_enabled() && !machine->usb_disabled; 303353018216SPaolo Bonzini } 303453018216SPaolo Bonzini 30354ee9ced9SMarcel Apfelbaum if (machine->usb) { 303657040d45SThomas Huth if (smc->use_ohci_by_default) { 303753018216SPaolo Bonzini pci_create_simple(phb->bus, -1, "pci-ohci"); 303857040d45SThomas Huth } else { 303957040d45SThomas Huth pci_create_simple(phb->bus, -1, "nec-usb-xhci"); 304057040d45SThomas Huth } 3041c86580b8SMarkus Armbruster 304253018216SPaolo Bonzini if (spapr->has_graphics) { 3043c86580b8SMarkus Armbruster USBBus *usb_bus = usb_bus_find(-1); 3044c86580b8SMarkus Armbruster 3045c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-kbd"); 3046c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-mouse"); 304753018216SPaolo Bonzini } 304853018216SPaolo Bonzini } 304953018216SPaolo Bonzini 3050ab3dd749SPhilippe Mathieu-Daudé if (spapr->rma_size < (MIN_RMA_SLOF * MiB)) { 3051d54e4d76SDavid Gibson error_report( 3052d54e4d76SDavid Gibson "pSeries SLOF firmware requires >= %ldM guest RMA (Real Mode Area memory)", 3053d54e4d76SDavid Gibson MIN_RMA_SLOF); 305453018216SPaolo Bonzini exit(1); 305553018216SPaolo Bonzini } 305653018216SPaolo Bonzini 305753018216SPaolo Bonzini if (kernel_filename) { 305853018216SPaolo Bonzini uint64_t lowaddr = 0; 305953018216SPaolo Bonzini 30604366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL, 30614366e1dbSLiam Merwick translate_kernel_address, NULL, 30624366e1dbSLiam Merwick NULL, &lowaddr, NULL, 1, 3063a19f7fb0SDavid Gibson PPC_ELF_MACHINE, 0, 0); 3064a19f7fb0SDavid Gibson if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) { 30654366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL, 3066a19f7fb0SDavid Gibson translate_kernel_address, NULL, NULL, 3067a19f7fb0SDavid Gibson &lowaddr, NULL, 0, PPC_ELF_MACHINE, 30687ef295eaSPeter Crosthwaite 0, 0); 3069a19f7fb0SDavid Gibson spapr->kernel_le = spapr->kernel_size > 0; 307016457e7fSBenjamin Herrenschmidt } 3071a19f7fb0SDavid Gibson if (spapr->kernel_size < 0) { 3072a19f7fb0SDavid Gibson error_report("error loading %s: %s", kernel_filename, 3073a19f7fb0SDavid Gibson load_elf_strerror(spapr->kernel_size)); 307453018216SPaolo Bonzini exit(1); 307553018216SPaolo Bonzini } 307653018216SPaolo Bonzini 307753018216SPaolo Bonzini /* load initrd */ 307853018216SPaolo Bonzini if (initrd_filename) { 307953018216SPaolo Bonzini /* Try to locate the initrd in the gap between the kernel 308053018216SPaolo Bonzini * and the firmware. Add a bit of space just in case 308153018216SPaolo Bonzini */ 3082a19f7fb0SDavid Gibson spapr->initrd_base = (KERNEL_LOAD_ADDR + spapr->kernel_size 3083a19f7fb0SDavid Gibson + 0x1ffff) & ~0xffff; 3084a19f7fb0SDavid Gibson spapr->initrd_size = load_image_targphys(initrd_filename, 3085a19f7fb0SDavid Gibson spapr->initrd_base, 3086a19f7fb0SDavid Gibson load_limit 3087a19f7fb0SDavid Gibson - spapr->initrd_base); 3088a19f7fb0SDavid Gibson if (spapr->initrd_size < 0) { 3089d54e4d76SDavid Gibson error_report("could not load initial ram disk '%s'", 309053018216SPaolo Bonzini initrd_filename); 309153018216SPaolo Bonzini exit(1); 309253018216SPaolo Bonzini } 309353018216SPaolo Bonzini } 309453018216SPaolo Bonzini } 309553018216SPaolo Bonzini 30968e7ea787SAndreas Färber if (bios_name == NULL) { 30978e7ea787SAndreas Färber bios_name = FW_FILE_NAME; 30988e7ea787SAndreas Färber } 30998e7ea787SAndreas Färber filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 31004c56440dSStefan Weil if (!filename) { 310168fea5a0SThomas Huth error_report("Could not find LPAR firmware '%s'", bios_name); 31024c56440dSStefan Weil exit(1); 31034c56440dSStefan Weil } 310453018216SPaolo Bonzini fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); 310568fea5a0SThomas Huth if (fw_size <= 0) { 310668fea5a0SThomas Huth error_report("Could not load LPAR firmware '%s'", filename); 310753018216SPaolo Bonzini exit(1); 310853018216SPaolo Bonzini } 310953018216SPaolo Bonzini g_free(filename); 311053018216SPaolo Bonzini 311128e02042SDavid Gibson /* FIXME: Should register things through the MachineState's qdev 311228e02042SDavid Gibson * interface, this is a legacy from the sPAPREnvironment structure 311328e02042SDavid Gibson * which predated MachineState but had a similar function */ 31144be21d56SDavid Gibson vmstate_register(NULL, 0, &vmstate_spapr, spapr); 3115ce62df53SDr. David Alan Gilbert register_savevm_live("spapr/htab", -1, 1, 31164be21d56SDavid Gibson &savevm_htab_handlers, spapr); 31174be21d56SDavid Gibson 3118bb2bdd81SGreg Kurz qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine), 3119bb2bdd81SGreg Kurz &error_fatal); 3120bb2bdd81SGreg Kurz 31215b2128d2SAlexander Graf qemu_register_boot_set(spapr_boot_set, spapr); 312242043e4fSLaurent Vivier 312393eac7b8SNicholas Piggin /* 312493eac7b8SNicholas Piggin * Nothing needs to be done to resume a suspended guest because 312593eac7b8SNicholas Piggin * suspending does not change the machine state, so no need for 312693eac7b8SNicholas Piggin * a ->wakeup method. 312793eac7b8SNicholas Piggin */ 312893eac7b8SNicholas Piggin qemu_register_wakeup_support(); 312993eac7b8SNicholas Piggin 313042043e4fSLaurent Vivier if (kvm_enabled()) { 31313dc410aeSAlexey Kardashevskiy /* to stop and start vmclock */ 313242043e4fSLaurent Vivier qemu_add_vm_change_state_handler(cpu_ppc_clock_vm_state_change, 313342043e4fSLaurent Vivier &spapr->tb); 31343dc410aeSAlexey Kardashevskiy 31353dc410aeSAlexey Kardashevskiy kvmppc_spapr_enable_inkernel_multitce(); 313642043e4fSLaurent Vivier } 313753018216SPaolo Bonzini } 313853018216SPaolo Bonzini 3139dc0ca80eSEric Auger static int spapr_kvm_type(MachineState *machine, const char *vm_type) 3140135a129aSAneesh Kumar K.V { 3141135a129aSAneesh Kumar K.V if (!vm_type) { 3142135a129aSAneesh Kumar K.V return 0; 3143135a129aSAneesh Kumar K.V } 3144135a129aSAneesh Kumar K.V 3145135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "HV")) { 3146135a129aSAneesh Kumar K.V return 1; 3147135a129aSAneesh Kumar K.V } 3148135a129aSAneesh Kumar K.V 3149135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "PR")) { 3150135a129aSAneesh Kumar K.V return 2; 3151135a129aSAneesh Kumar K.V } 3152135a129aSAneesh Kumar K.V 3153135a129aSAneesh Kumar K.V error_report("Unknown kvm-type specified '%s'", vm_type); 3154135a129aSAneesh Kumar K.V exit(1); 3155135a129aSAneesh Kumar K.V } 3156135a129aSAneesh Kumar K.V 315771461b0fSAlexey Kardashevskiy /* 3158627b84f4SGonglei * Implementation of an interface to adjust firmware path 315971461b0fSAlexey Kardashevskiy * for the bootindex property handling. 316071461b0fSAlexey Kardashevskiy */ 316171461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, 316271461b0fSAlexey Kardashevskiy DeviceState *dev) 316371461b0fSAlexey Kardashevskiy { 316471461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \ 316571461b0fSAlexey Kardashevskiy ((type *)object_dynamic_cast(OBJECT(obj), (name))) 316671461b0fSAlexey Kardashevskiy SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); 3167ce2918cbSDavid Gibson SpaprPhbState *phb = CAST(SpaprPhbState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); 3168c4e13492SFelipe Franciosi VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON); 316971461b0fSAlexey Kardashevskiy 317071461b0fSAlexey Kardashevskiy if (d) { 317171461b0fSAlexey Kardashevskiy void *spapr = CAST(void, bus->parent, "spapr-vscsi"); 317271461b0fSAlexey Kardashevskiy VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); 317371461b0fSAlexey Kardashevskiy USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); 317471461b0fSAlexey Kardashevskiy 317571461b0fSAlexey Kardashevskiy if (spapr) { 317671461b0fSAlexey Kardashevskiy /* 317771461b0fSAlexey Kardashevskiy * Replace "channel@0/disk@0,0" with "disk@8000000000000000": 31781ac24c91SThomas Huth * In the top 16 bits of the 64-bit LUN, we use SRP luns of the form 31791ac24c91SThomas Huth * 0x8000 | (target << 8) | (bus << 5) | lun 31801ac24c91SThomas Huth * (see the "Logical unit addressing format" table in SAM5) 318171461b0fSAlexey Kardashevskiy */ 31821ac24c91SThomas Huth unsigned id = 0x8000 | (d->id << 8) | (d->channel << 5) | d->lun; 318371461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 318471461b0fSAlexey Kardashevskiy (uint64_t)id << 48); 318571461b0fSAlexey Kardashevskiy } else if (virtio) { 318671461b0fSAlexey Kardashevskiy /* 318771461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (target << 8) | lun 318871461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 318971461b0fSAlexey Kardashevskiy * Note: the quote above is from SLOF and it is wrong, 319071461b0fSAlexey Kardashevskiy * the actual binding is: 319171461b0fSAlexey Kardashevskiy * swap 0100 or 10 << or 20 << ( target lun-id -- srplun ) 319271461b0fSAlexey Kardashevskiy */ 319371461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (d->id << 16) | d->lun; 3194bac658d1SThomas Huth if (d->lun >= 256) { 3195bac658d1SThomas Huth /* Use the LUN "flat space addressing method" */ 3196bac658d1SThomas Huth id |= 0x4000; 3197bac658d1SThomas Huth } 319871461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 319971461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 320071461b0fSAlexey Kardashevskiy } else if (usb) { 320171461b0fSAlexey Kardashevskiy /* 320271461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (usb-port << 16) | lun 320371461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 320471461b0fSAlexey Kardashevskiy */ 320571461b0fSAlexey Kardashevskiy unsigned usb_port = atoi(usb->port->path); 320671461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (usb_port << 16) | d->lun; 320771461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 320871461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 320971461b0fSAlexey Kardashevskiy } 321071461b0fSAlexey Kardashevskiy } 321171461b0fSAlexey Kardashevskiy 3212b99260ebSThomas Huth /* 3213b99260ebSThomas Huth * SLOF probes the USB devices, and if it recognizes that the device is a 3214b99260ebSThomas Huth * storage device, it changes its name to "storage" instead of "usb-host", 3215b99260ebSThomas Huth * and additionally adds a child node for the SCSI LUN, so the correct 3216b99260ebSThomas Huth * boot path in SLOF is something like .../storage@1/disk@xxx" instead. 3217b99260ebSThomas Huth */ 3218b99260ebSThomas Huth if (strcmp("usb-host", qdev_fw_name(dev)) == 0) { 3219b99260ebSThomas Huth USBDevice *usbdev = CAST(USBDevice, dev, TYPE_USB_DEVICE); 3220b99260ebSThomas Huth if (usb_host_dev_is_scsi_storage(usbdev)) { 3221b99260ebSThomas Huth return g_strdup_printf("storage@%s/disk", usbdev->port->path); 3222b99260ebSThomas Huth } 3223b99260ebSThomas Huth } 3224b99260ebSThomas Huth 322571461b0fSAlexey Kardashevskiy if (phb) { 322671461b0fSAlexey Kardashevskiy /* Replace "pci" with "pci@800000020000000" */ 322771461b0fSAlexey Kardashevskiy return g_strdup_printf("pci@%"PRIX64, phb->buid); 322871461b0fSAlexey Kardashevskiy } 322971461b0fSAlexey Kardashevskiy 3230c4e13492SFelipe Franciosi if (vsc) { 3231c4e13492SFelipe Franciosi /* Same logic as virtio above */ 3232c4e13492SFelipe Franciosi unsigned id = 0x1000000 | (vsc->target << 16) | vsc->lun; 3233c4e13492SFelipe Franciosi return g_strdup_printf("disk@%"PRIX64, (uint64_t)id << 32); 3234c4e13492SFelipe Franciosi } 3235c4e13492SFelipe Franciosi 32364871dd4cSThomas Huth if (g_str_equal("pci-bridge", qdev_fw_name(dev))) { 32374871dd4cSThomas Huth /* SLOF uses "pci" instead of "pci-bridge" for PCI bridges */ 32384871dd4cSThomas Huth PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); 32394871dd4cSThomas Huth return g_strdup_printf("pci@%x", PCI_SLOT(pcidev->devfn)); 32404871dd4cSThomas Huth } 32414871dd4cSThomas Huth 324271461b0fSAlexey Kardashevskiy return NULL; 324371461b0fSAlexey Kardashevskiy } 324471461b0fSAlexey Kardashevskiy 324523825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp) 324623825581SEduardo Habkost { 3247ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 324823825581SEduardo Habkost 324928e02042SDavid Gibson return g_strdup(spapr->kvm_type); 325023825581SEduardo Habkost } 325123825581SEduardo Habkost 325223825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp) 325323825581SEduardo Habkost { 3254ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 325523825581SEduardo Habkost 325628e02042SDavid Gibson g_free(spapr->kvm_type); 325728e02042SDavid Gibson spapr->kvm_type = g_strdup(value); 325823825581SEduardo Habkost } 325923825581SEduardo Habkost 3260f6229214SMichael Roth static bool spapr_get_modern_hotplug_events(Object *obj, Error **errp) 3261f6229214SMichael Roth { 3262ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3263f6229214SMichael Roth 3264f6229214SMichael Roth return spapr->use_hotplug_event_source; 3265f6229214SMichael Roth } 3266f6229214SMichael Roth 3267f6229214SMichael Roth static void spapr_set_modern_hotplug_events(Object *obj, bool value, 3268f6229214SMichael Roth Error **errp) 3269f6229214SMichael Roth { 3270ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3271f6229214SMichael Roth 3272f6229214SMichael Roth spapr->use_hotplug_event_source = value; 3273f6229214SMichael Roth } 3274f6229214SMichael Roth 3275fcad0d21SAlexey Kardashevskiy static bool spapr_get_msix_emulation(Object *obj, Error **errp) 3276fcad0d21SAlexey Kardashevskiy { 3277fcad0d21SAlexey Kardashevskiy return true; 3278fcad0d21SAlexey Kardashevskiy } 3279fcad0d21SAlexey Kardashevskiy 328030f4b05bSDavid Gibson static char *spapr_get_resize_hpt(Object *obj, Error **errp) 328130f4b05bSDavid Gibson { 3282ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 328330f4b05bSDavid Gibson 328430f4b05bSDavid Gibson switch (spapr->resize_hpt) { 328530f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DEFAULT: 328630f4b05bSDavid Gibson return g_strdup("default"); 328730f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DISABLED: 328830f4b05bSDavid Gibson return g_strdup("disabled"); 328930f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_ENABLED: 329030f4b05bSDavid Gibson return g_strdup("enabled"); 329130f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_REQUIRED: 329230f4b05bSDavid Gibson return g_strdup("required"); 329330f4b05bSDavid Gibson } 329430f4b05bSDavid Gibson g_assert_not_reached(); 329530f4b05bSDavid Gibson } 329630f4b05bSDavid Gibson 329730f4b05bSDavid Gibson static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp) 329830f4b05bSDavid Gibson { 3299ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 330030f4b05bSDavid Gibson 330130f4b05bSDavid Gibson if (strcmp(value, "default") == 0) { 330230f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DEFAULT; 330330f4b05bSDavid Gibson } else if (strcmp(value, "disabled") == 0) { 330430f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 330530f4b05bSDavid Gibson } else if (strcmp(value, "enabled") == 0) { 330630f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_ENABLED; 330730f4b05bSDavid Gibson } else if (strcmp(value, "required") == 0) { 330830f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_REQUIRED; 330930f4b05bSDavid Gibson } else { 331030f4b05bSDavid Gibson error_setg(errp, "Bad value for \"resize-hpt\" property"); 331130f4b05bSDavid Gibson } 331230f4b05bSDavid Gibson } 331330f4b05bSDavid Gibson 3314fa98fbfcSSam Bobroff static void spapr_get_vsmt(Object *obj, Visitor *v, const char *name, 3315fa98fbfcSSam Bobroff void *opaque, Error **errp) 3316fa98fbfcSSam Bobroff { 3317fa98fbfcSSam Bobroff visit_type_uint32(v, name, (uint32_t *)opaque, errp); 3318fa98fbfcSSam Bobroff } 3319fa98fbfcSSam Bobroff 3320fa98fbfcSSam Bobroff static void spapr_set_vsmt(Object *obj, Visitor *v, const char *name, 3321fa98fbfcSSam Bobroff void *opaque, Error **errp) 3322fa98fbfcSSam Bobroff { 3323fa98fbfcSSam Bobroff visit_type_uint32(v, name, (uint32_t *)opaque, errp); 3324fa98fbfcSSam Bobroff } 3325fa98fbfcSSam Bobroff 33263ba3d0bcSCédric Le Goater static char *spapr_get_ic_mode(Object *obj, Error **errp) 33273ba3d0bcSCédric Le Goater { 3328ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 33293ba3d0bcSCédric Le Goater 33303ba3d0bcSCédric Le Goater if (spapr->irq == &spapr_irq_xics_legacy) { 33313ba3d0bcSCédric Le Goater return g_strdup("legacy"); 33323ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xics) { 33333ba3d0bcSCédric Le Goater return g_strdup("xics"); 33343ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xive) { 33353ba3d0bcSCédric Le Goater return g_strdup("xive"); 333613db0cd9SCédric Le Goater } else if (spapr->irq == &spapr_irq_dual) { 333713db0cd9SCédric Le Goater return g_strdup("dual"); 33383ba3d0bcSCédric Le Goater } 33393ba3d0bcSCédric Le Goater g_assert_not_reached(); 33403ba3d0bcSCédric Le Goater } 33413ba3d0bcSCédric Le Goater 33423ba3d0bcSCédric Le Goater static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp) 33433ba3d0bcSCédric Le Goater { 3344ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 33453ba3d0bcSCédric Le Goater 334621df5e4fSGreg Kurz if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { 334721df5e4fSGreg Kurz error_setg(errp, "This machine only uses the legacy XICS backend, don't pass ic-mode"); 334821df5e4fSGreg Kurz return; 334921df5e4fSGreg Kurz } 335021df5e4fSGreg Kurz 33513ba3d0bcSCédric Le Goater /* The legacy IRQ backend can not be set */ 33523ba3d0bcSCédric Le Goater if (strcmp(value, "xics") == 0) { 33533ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xics; 33543ba3d0bcSCédric Le Goater } else if (strcmp(value, "xive") == 0) { 33553ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xive; 335613db0cd9SCédric Le Goater } else if (strcmp(value, "dual") == 0) { 335713db0cd9SCédric Le Goater spapr->irq = &spapr_irq_dual; 33583ba3d0bcSCédric Le Goater } else { 33593ba3d0bcSCédric Le Goater error_setg(errp, "Bad value for \"ic-mode\" property"); 33603ba3d0bcSCédric Le Goater } 33613ba3d0bcSCédric Le Goater } 33623ba3d0bcSCédric Le Goater 336327461d69SPrasad J Pandit static char *spapr_get_host_model(Object *obj, Error **errp) 336427461d69SPrasad J Pandit { 3365ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 336627461d69SPrasad J Pandit 336727461d69SPrasad J Pandit return g_strdup(spapr->host_model); 336827461d69SPrasad J Pandit } 336927461d69SPrasad J Pandit 337027461d69SPrasad J Pandit static void spapr_set_host_model(Object *obj, const char *value, Error **errp) 337127461d69SPrasad J Pandit { 3372ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 337327461d69SPrasad J Pandit 337427461d69SPrasad J Pandit g_free(spapr->host_model); 337527461d69SPrasad J Pandit spapr->host_model = g_strdup(value); 337627461d69SPrasad J Pandit } 337727461d69SPrasad J Pandit 337827461d69SPrasad J Pandit static char *spapr_get_host_serial(Object *obj, Error **errp) 337927461d69SPrasad J Pandit { 3380ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 338127461d69SPrasad J Pandit 338227461d69SPrasad J Pandit return g_strdup(spapr->host_serial); 338327461d69SPrasad J Pandit } 338427461d69SPrasad J Pandit 338527461d69SPrasad J Pandit static void spapr_set_host_serial(Object *obj, const char *value, Error **errp) 338627461d69SPrasad J Pandit { 3387ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 338827461d69SPrasad J Pandit 338927461d69SPrasad J Pandit g_free(spapr->host_serial); 339027461d69SPrasad J Pandit spapr->host_serial = g_strdup(value); 339127461d69SPrasad J Pandit } 339227461d69SPrasad J Pandit 3393bcb5ce08SDavid Gibson static void spapr_instance_init(Object *obj) 339423825581SEduardo Habkost { 3395ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3396ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 3397715c5407SDavid Gibson 3398715c5407SDavid Gibson spapr->htab_fd = -1; 3399f6229214SMichael Roth spapr->use_hotplug_event_source = true; 340023825581SEduardo Habkost object_property_add_str(obj, "kvm-type", 340123825581SEduardo Habkost spapr_get_kvm_type, spapr_set_kvm_type, NULL); 340249d2e648SMarcel Apfelbaum object_property_set_description(obj, "kvm-type", 340349d2e648SMarcel Apfelbaum "Specifies the KVM virtualization mode (HV, PR)", 340449d2e648SMarcel Apfelbaum NULL); 3405f6229214SMichael Roth object_property_add_bool(obj, "modern-hotplug-events", 3406f6229214SMichael Roth spapr_get_modern_hotplug_events, 3407f6229214SMichael Roth spapr_set_modern_hotplug_events, 3408f6229214SMichael Roth NULL); 3409f6229214SMichael Roth object_property_set_description(obj, "modern-hotplug-events", 3410f6229214SMichael Roth "Use dedicated hotplug event mechanism in" 3411f6229214SMichael Roth " place of standard EPOW events when possible" 3412f6229214SMichael Roth " (required for memory hot-unplug support)", 3413f6229214SMichael Roth NULL); 34147843c0d6SDavid Gibson ppc_compat_add_property(obj, "max-cpu-compat", &spapr->max_compat_pvr, 34157843c0d6SDavid Gibson "Maximum permitted CPU compatibility mode", 34167843c0d6SDavid Gibson &error_fatal); 341730f4b05bSDavid Gibson 341830f4b05bSDavid Gibson object_property_add_str(obj, "resize-hpt", 341930f4b05bSDavid Gibson spapr_get_resize_hpt, spapr_set_resize_hpt, NULL); 342030f4b05bSDavid Gibson object_property_set_description(obj, "resize-hpt", 342130f4b05bSDavid Gibson "Resizing of the Hash Page Table (enabled, disabled, required)", 342230f4b05bSDavid Gibson NULL); 3423fa98fbfcSSam Bobroff object_property_add(obj, "vsmt", "uint32", spapr_get_vsmt, 3424fa98fbfcSSam Bobroff spapr_set_vsmt, NULL, &spapr->vsmt, &error_abort); 3425fa98fbfcSSam Bobroff object_property_set_description(obj, "vsmt", 3426fa98fbfcSSam Bobroff "Virtual SMT: KVM behaves as if this were" 3427fa98fbfcSSam Bobroff " the host's SMT mode", &error_abort); 3428fcad0d21SAlexey Kardashevskiy object_property_add_bool(obj, "vfio-no-msix-emulation", 3429fcad0d21SAlexey Kardashevskiy spapr_get_msix_emulation, NULL, NULL); 34303ba3d0bcSCédric Le Goater 34313ba3d0bcSCédric Le Goater /* The machine class defines the default interrupt controller mode */ 34323ba3d0bcSCédric Le Goater spapr->irq = smc->irq; 34333ba3d0bcSCédric Le Goater object_property_add_str(obj, "ic-mode", spapr_get_ic_mode, 34343ba3d0bcSCédric Le Goater spapr_set_ic_mode, NULL); 34353ba3d0bcSCédric Le Goater object_property_set_description(obj, "ic-mode", 343613db0cd9SCédric Le Goater "Specifies the interrupt controller mode (xics, xive, dual)", 34373ba3d0bcSCédric Le Goater NULL); 343827461d69SPrasad J Pandit 343927461d69SPrasad J Pandit object_property_add_str(obj, "host-model", 344027461d69SPrasad J Pandit spapr_get_host_model, spapr_set_host_model, 344127461d69SPrasad J Pandit &error_abort); 344227461d69SPrasad J Pandit object_property_set_description(obj, "host-model", 34430a794529SDavid Gibson "Host model to advertise in guest device tree", &error_abort); 344427461d69SPrasad J Pandit object_property_add_str(obj, "host-serial", 344527461d69SPrasad J Pandit spapr_get_host_serial, spapr_set_host_serial, 344627461d69SPrasad J Pandit &error_abort); 344727461d69SPrasad J Pandit object_property_set_description(obj, "host-serial", 34480a794529SDavid Gibson "Host serial number to advertise in guest device tree", &error_abort); 344923825581SEduardo Habkost } 345023825581SEduardo Habkost 345187bbdd9cSDavid Gibson static void spapr_machine_finalizefn(Object *obj) 345287bbdd9cSDavid Gibson { 3453ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 345487bbdd9cSDavid Gibson 345587bbdd9cSDavid Gibson g_free(spapr->kvm_type); 345687bbdd9cSDavid Gibson } 345787bbdd9cSDavid Gibson 34581c7ad77eSNicholas Piggin void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg) 345934316482SAlexey Kardashevskiy { 346034316482SAlexey Kardashevskiy cpu_synchronize_state(cs); 346134316482SAlexey Kardashevskiy ppc_cpu_do_system_reset(cs); 346234316482SAlexey Kardashevskiy } 346334316482SAlexey Kardashevskiy 346434316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) 346534316482SAlexey Kardashevskiy { 346634316482SAlexey Kardashevskiy CPUState *cs; 346734316482SAlexey Kardashevskiy 346834316482SAlexey Kardashevskiy CPU_FOREACH(cs) { 34691c7ad77eSNicholas Piggin async_run_on_cpu(cs, spapr_do_system_reset_on_cpu, RUN_ON_CPU_NULL); 347034316482SAlexey Kardashevskiy } 347134316482SAlexey Kardashevskiy } 347234316482SAlexey Kardashevskiy 3473ce2918cbSDavid Gibson int spapr_lmb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 347462d38c9bSGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 347562d38c9bSGreg Kurz { 347662d38c9bSGreg Kurz uint64_t addr; 347762d38c9bSGreg Kurz uint32_t node; 347862d38c9bSGreg Kurz 347962d38c9bSGreg Kurz addr = spapr_drc_index(drc) * SPAPR_MEMORY_BLOCK_SIZE; 348062d38c9bSGreg Kurz node = object_property_get_uint(OBJECT(drc->dev), PC_DIMM_NODE_PROP, 348162d38c9bSGreg Kurz &error_abort); 348262d38c9bSGreg Kurz *fdt_start_offset = spapr_populate_memory_node(fdt, node, addr, 348362d38c9bSGreg Kurz SPAPR_MEMORY_BLOCK_SIZE); 348462d38c9bSGreg Kurz return 0; 348562d38c9bSGreg Kurz } 348662d38c9bSGreg Kurz 348779b78a6bSMichael Roth static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, 348862d38c9bSGreg Kurz bool dedicated_hp_event_source, Error **errp) 3489c20d332aSBharata B Rao { 3490ce2918cbSDavid Gibson SpaprDrc *drc; 3491c20d332aSBharata B Rao uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; 349262d38c9bSGreg Kurz int i; 349379b78a6bSMichael Roth uint64_t addr = addr_start; 349494fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 3495160bb678SGreg Kurz Error *local_err = NULL; 3496c20d332aSBharata B Rao 3497c20d332aSBharata B Rao for (i = 0; i < nr_lmbs; i++) { 3498fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 3499c20d332aSBharata B Rao addr / SPAPR_MEMORY_BLOCK_SIZE); 3500c20d332aSBharata B Rao g_assert(drc); 3501c20d332aSBharata B Rao 350209d876ceSGreg Kurz spapr_drc_attach(drc, dev, &local_err); 3503160bb678SGreg Kurz if (local_err) { 3504160bb678SGreg Kurz while (addr > addr_start) { 3505160bb678SGreg Kurz addr -= SPAPR_MEMORY_BLOCK_SIZE; 3506160bb678SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 3507160bb678SGreg Kurz addr / SPAPR_MEMORY_BLOCK_SIZE); 3508a8dc47fdSDavid Gibson spapr_drc_detach(drc); 3509160bb678SGreg Kurz } 3510160bb678SGreg Kurz error_propagate(errp, local_err); 3511160bb678SGreg Kurz return; 3512160bb678SGreg Kurz } 351394fd9cbaSLaurent Vivier if (!hotplugged) { 351494fd9cbaSLaurent Vivier spapr_drc_reset(drc); 351594fd9cbaSLaurent Vivier } 3516c20d332aSBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE; 3517c20d332aSBharata B Rao } 35185dd5238cSJianjun Duan /* send hotplug notification to the 35195dd5238cSJianjun Duan * guest only in case of hotplugged memory 35205dd5238cSJianjun Duan */ 352194fd9cbaSLaurent Vivier if (hotplugged) { 352279b78a6bSMichael Roth if (dedicated_hp_event_source) { 3523fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 352479b78a6bSMichael Roth addr_start / SPAPR_MEMORY_BLOCK_SIZE); 352579b78a6bSMichael Roth spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 352679b78a6bSMichael Roth nr_lmbs, 35270b55aa91SDavid Gibson spapr_drc_index(drc)); 352879b78a6bSMichael Roth } else { 352979b78a6bSMichael Roth spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, 353079b78a6bSMichael Roth nr_lmbs); 353179b78a6bSMichael Roth } 3532c20d332aSBharata B Rao } 35335dd5238cSJianjun Duan } 3534c20d332aSBharata B Rao 3535c20d332aSBharata B Rao static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 353681985f3bSDavid Hildenbrand Error **errp) 3537c20d332aSBharata B Rao { 3538c20d332aSBharata B Rao Error *local_err = NULL; 3539ce2918cbSDavid Gibson SpaprMachineState *ms = SPAPR_MACHINE(hotplug_dev); 3540c20d332aSBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 3541b0e62443SDavid Hildenbrand uint64_t size, addr; 354204790978SThomas Huth 3543946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dev), &error_abort); 3544df587133SThomas Huth 3545fd3416f5SDavid Hildenbrand pc_dimm_plug(dimm, MACHINE(ms), &local_err); 3546c20d332aSBharata B Rao if (local_err) { 3547c20d332aSBharata B Rao goto out; 3548c20d332aSBharata B Rao } 3549c20d332aSBharata B Rao 35509ed442b8SMarc-André Lureau addr = object_property_get_uint(OBJECT(dimm), 35519ed442b8SMarc-André Lureau PC_DIMM_ADDR_PROP, &local_err); 3552c20d332aSBharata B Rao if (local_err) { 3553160bb678SGreg Kurz goto out_unplug; 3554c20d332aSBharata B Rao } 3555c20d332aSBharata B Rao 355662d38c9bSGreg Kurz spapr_add_lmbs(dev, addr, size, spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), 3557160bb678SGreg Kurz &local_err); 3558160bb678SGreg Kurz if (local_err) { 3559160bb678SGreg Kurz goto out_unplug; 3560160bb678SGreg Kurz } 3561c20d332aSBharata B Rao 3562160bb678SGreg Kurz return; 3563160bb678SGreg Kurz 3564160bb678SGreg Kurz out_unplug: 3565fd3416f5SDavid Hildenbrand pc_dimm_unplug(dimm, MACHINE(ms)); 3566c20d332aSBharata B Rao out: 3567c20d332aSBharata B Rao error_propagate(errp, local_err); 3568c20d332aSBharata B Rao } 3569c20d332aSBharata B Rao 3570c871bc70SLaurent Vivier static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3571c871bc70SLaurent Vivier Error **errp) 3572c871bc70SLaurent Vivier { 3573ce2918cbSDavid Gibson const SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev); 3574ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3575c871bc70SLaurent Vivier PCDIMMDevice *dimm = PC_DIMM(dev); 35768f1ffe5bSDavid Hildenbrand Error *local_err = NULL; 357704790978SThomas Huth uint64_t size; 3578123eec65SDavid Gibson Object *memdev; 3579123eec65SDavid Gibson hwaddr pagesize; 3580c871bc70SLaurent Vivier 35814e8a01bdSDavid Hildenbrand if (!smc->dr_lmb_enabled) { 35824e8a01bdSDavid Hildenbrand error_setg(errp, "Memory hotplug not supported for this machine"); 35834e8a01bdSDavid Hildenbrand return; 35844e8a01bdSDavid Hildenbrand } 35854e8a01bdSDavid Hildenbrand 3586946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &local_err); 3587946d6154SDavid Hildenbrand if (local_err) { 3588946d6154SDavid Hildenbrand error_propagate(errp, local_err); 358904790978SThomas Huth return; 359004790978SThomas Huth } 359104790978SThomas Huth 3592c871bc70SLaurent Vivier if (size % SPAPR_MEMORY_BLOCK_SIZE) { 3593c871bc70SLaurent Vivier error_setg(errp, "Hotplugged memory size must be a multiple of " 3594ab3dd749SPhilippe Mathieu-Daudé "%" PRIu64 " MB", SPAPR_MEMORY_BLOCK_SIZE / MiB); 3595c871bc70SLaurent Vivier return; 3596c871bc70SLaurent Vivier } 3597c871bc70SLaurent Vivier 3598123eec65SDavid Gibson memdev = object_property_get_link(OBJECT(dimm), PC_DIMM_MEMDEV_PROP, 3599123eec65SDavid Gibson &error_abort); 3600123eec65SDavid Gibson pagesize = host_memory_backend_pagesize(MEMORY_BACKEND(memdev)); 36018f1ffe5bSDavid Hildenbrand spapr_check_pagesize(spapr, pagesize, &local_err); 36028f1ffe5bSDavid Hildenbrand if (local_err) { 36038f1ffe5bSDavid Hildenbrand error_propagate(errp, local_err); 36048f1ffe5bSDavid Hildenbrand return; 36058f1ffe5bSDavid Hildenbrand } 36068f1ffe5bSDavid Hildenbrand 3607fd3416f5SDavid Hildenbrand pc_dimm_pre_plug(dimm, MACHINE(hotplug_dev), NULL, errp); 3608c871bc70SLaurent Vivier } 3609c871bc70SLaurent Vivier 3610ce2918cbSDavid Gibson struct SpaprDimmState { 36110cffce56SDavid Gibson PCDIMMDevice *dimm; 3612cf632463SBharata B Rao uint32_t nr_lmbs; 3613ce2918cbSDavid Gibson QTAILQ_ENTRY(SpaprDimmState) next; 36140cffce56SDavid Gibson }; 36150cffce56SDavid Gibson 3616ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_find(SpaprMachineState *s, 36170cffce56SDavid Gibson PCDIMMDevice *dimm) 36180cffce56SDavid Gibson { 3619ce2918cbSDavid Gibson SpaprDimmState *dimm_state = NULL; 36200cffce56SDavid Gibson 36210cffce56SDavid Gibson QTAILQ_FOREACH(dimm_state, &s->pending_dimm_unplugs, next) { 36220cffce56SDavid Gibson if (dimm_state->dimm == dimm) { 36230cffce56SDavid Gibson break; 36240cffce56SDavid Gibson } 36250cffce56SDavid Gibson } 36260cffce56SDavid Gibson return dimm_state; 36270cffce56SDavid Gibson } 36280cffce56SDavid Gibson 3629ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_add(SpaprMachineState *spapr, 36308d5981c4SBharata B Rao uint32_t nr_lmbs, 36318d5981c4SBharata B Rao PCDIMMDevice *dimm) 36320cffce56SDavid Gibson { 3633ce2918cbSDavid Gibson SpaprDimmState *ds = NULL; 36348d5981c4SBharata B Rao 36358d5981c4SBharata B Rao /* 36368d5981c4SBharata B Rao * If this request is for a DIMM whose removal had failed earlier 36378d5981c4SBharata B Rao * (due to guest's refusal to remove the LMBs), we would have this 36388d5981c4SBharata B Rao * dimm already in the pending_dimm_unplugs list. In that 36398d5981c4SBharata B Rao * case don't add again. 36408d5981c4SBharata B Rao */ 36418d5981c4SBharata B Rao ds = spapr_pending_dimm_unplugs_find(spapr, dimm); 36428d5981c4SBharata B Rao if (!ds) { 3643ce2918cbSDavid Gibson ds = g_malloc0(sizeof(SpaprDimmState)); 36448d5981c4SBharata B Rao ds->nr_lmbs = nr_lmbs; 36458d5981c4SBharata B Rao ds->dimm = dimm; 36468d5981c4SBharata B Rao QTAILQ_INSERT_HEAD(&spapr->pending_dimm_unplugs, ds, next); 36478d5981c4SBharata B Rao } 36488d5981c4SBharata B Rao return ds; 36490cffce56SDavid Gibson } 36500cffce56SDavid Gibson 3651ce2918cbSDavid Gibson static void spapr_pending_dimm_unplugs_remove(SpaprMachineState *spapr, 3652ce2918cbSDavid Gibson SpaprDimmState *dimm_state) 36530cffce56SDavid Gibson { 36540cffce56SDavid Gibson QTAILQ_REMOVE(&spapr->pending_dimm_unplugs, dimm_state, next); 36550cffce56SDavid Gibson g_free(dimm_state); 36560cffce56SDavid Gibson } 3657cf632463SBharata B Rao 3658ce2918cbSDavid Gibson static SpaprDimmState *spapr_recover_pending_dimm_state(SpaprMachineState *ms, 365916ee9980SDaniel Henrique Barboza PCDIMMDevice *dimm) 366016ee9980SDaniel Henrique Barboza { 3661ce2918cbSDavid Gibson SpaprDrc *drc; 3662946d6154SDavid Hildenbrand uint64_t size = memory_device_get_region_size(MEMORY_DEVICE(dimm), 3663946d6154SDavid Hildenbrand &error_abort); 366416ee9980SDaniel Henrique Barboza uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 366516ee9980SDaniel Henrique Barboza uint32_t avail_lmbs = 0; 366616ee9980SDaniel Henrique Barboza uint64_t addr_start, addr; 366716ee9980SDaniel Henrique Barboza int i; 366816ee9980SDaniel Henrique Barboza 366916ee9980SDaniel Henrique Barboza addr_start = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, 367016ee9980SDaniel Henrique Barboza &error_abort); 367116ee9980SDaniel Henrique Barboza 367216ee9980SDaniel Henrique Barboza addr = addr_start; 367316ee9980SDaniel Henrique Barboza for (i = 0; i < nr_lmbs; i++) { 3674fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 367516ee9980SDaniel Henrique Barboza addr / SPAPR_MEMORY_BLOCK_SIZE); 367616ee9980SDaniel Henrique Barboza g_assert(drc); 3677454b580aSDavid Gibson if (drc->dev) { 367816ee9980SDaniel Henrique Barboza avail_lmbs++; 367916ee9980SDaniel Henrique Barboza } 368016ee9980SDaniel Henrique Barboza addr += SPAPR_MEMORY_BLOCK_SIZE; 368116ee9980SDaniel Henrique Barboza } 368216ee9980SDaniel Henrique Barboza 36838d5981c4SBharata B Rao return spapr_pending_dimm_unplugs_add(ms, avail_lmbs, dimm); 368416ee9980SDaniel Henrique Barboza } 368516ee9980SDaniel Henrique Barboza 368631834723SDaniel Henrique Barboza /* Callback to be called during DRC release. */ 368731834723SDaniel Henrique Barboza void spapr_lmb_release(DeviceState *dev) 3688cf632463SBharata B Rao { 36893ec71474SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3690ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl); 3691ce2918cbSDavid Gibson SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); 3692cf632463SBharata B Rao 369316ee9980SDaniel Henrique Barboza /* This information will get lost if a migration occurs 369416ee9980SDaniel Henrique Barboza * during the unplug process. In this case recover it. */ 369516ee9980SDaniel Henrique Barboza if (ds == NULL) { 369616ee9980SDaniel Henrique Barboza ds = spapr_recover_pending_dimm_state(spapr, PC_DIMM(dev)); 36978d5981c4SBharata B Rao g_assert(ds); 3698454b580aSDavid Gibson /* The DRC being examined by the caller at least must be counted */ 3699454b580aSDavid Gibson g_assert(ds->nr_lmbs); 370016ee9980SDaniel Henrique Barboza } 3701454b580aSDavid Gibson 3702454b580aSDavid Gibson if (--ds->nr_lmbs) { 3703cf632463SBharata B Rao return; 3704cf632463SBharata B Rao } 3705cf632463SBharata B Rao 3706cf632463SBharata B Rao /* 3707cf632463SBharata B Rao * Now that all the LMBs have been removed by the guest, call the 37083ec71474SDavid Hildenbrand * unplug handler chain. This can never fail. 3709cf632463SBharata B Rao */ 37103ec71474SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 371107578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 37123ec71474SDavid Hildenbrand } 37133ec71474SDavid Hildenbrand 37143ec71474SDavid Hildenbrand static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 37153ec71474SDavid Hildenbrand { 3716ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3717ce2918cbSDavid Gibson SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); 37183ec71474SDavid Hildenbrand 3719fd3416f5SDavid Hildenbrand pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev)); 372007578b0aSDavid Hildenbrand object_property_set_bool(OBJECT(dev), false, "realized", NULL); 37212a129767SDaniel Henrique Barboza spapr_pending_dimm_unplugs_remove(spapr, ds); 3722cf632463SBharata B Rao } 3723cf632463SBharata B Rao 3724cf632463SBharata B Rao static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, 3725cf632463SBharata B Rao DeviceState *dev, Error **errp) 3726cf632463SBharata B Rao { 3727ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3728cf632463SBharata B Rao Error *local_err = NULL; 3729cf632463SBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 373004790978SThomas Huth uint32_t nr_lmbs; 373104790978SThomas Huth uint64_t size, addr_start, addr; 37320cffce56SDavid Gibson int i; 3733ce2918cbSDavid Gibson SpaprDrc *drc; 373404790978SThomas Huth 3735946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &error_abort); 373604790978SThomas Huth nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 373704790978SThomas Huth 37389ed442b8SMarc-André Lureau addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, 37390cffce56SDavid Gibson &local_err); 3740cf632463SBharata B Rao if (local_err) { 3741cf632463SBharata B Rao goto out; 3742cf632463SBharata B Rao } 3743cf632463SBharata B Rao 37442a129767SDaniel Henrique Barboza /* 37452a129767SDaniel Henrique Barboza * An existing pending dimm state for this DIMM means that there is an 37462a129767SDaniel Henrique Barboza * unplug operation in progress, waiting for the spapr_lmb_release 37472a129767SDaniel Henrique Barboza * callback to complete the job (BQL can't cover that far). In this case, 37482a129767SDaniel Henrique Barboza * bail out to avoid detaching DRCs that were already released. 37492a129767SDaniel Henrique Barboza */ 37502a129767SDaniel Henrique Barboza if (spapr_pending_dimm_unplugs_find(spapr, dimm)) { 37512a129767SDaniel Henrique Barboza error_setg(&local_err, 37522a129767SDaniel Henrique Barboza "Memory unplug already in progress for device %s", 37532a129767SDaniel Henrique Barboza dev->id); 37542a129767SDaniel Henrique Barboza goto out; 37552a129767SDaniel Henrique Barboza } 37562a129767SDaniel Henrique Barboza 37578d5981c4SBharata B Rao spapr_pending_dimm_unplugs_add(spapr, nr_lmbs, dimm); 37580cffce56SDavid Gibson 37590cffce56SDavid Gibson addr = addr_start; 37600cffce56SDavid Gibson for (i = 0; i < nr_lmbs; i++) { 3761fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 37620cffce56SDavid Gibson addr / SPAPR_MEMORY_BLOCK_SIZE); 37630cffce56SDavid Gibson g_assert(drc); 37640cffce56SDavid Gibson 3765a8dc47fdSDavid Gibson spapr_drc_detach(drc); 37660cffce56SDavid Gibson addr += SPAPR_MEMORY_BLOCK_SIZE; 37670cffce56SDavid Gibson } 37680cffce56SDavid Gibson 3769fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 37700cffce56SDavid Gibson addr_start / SPAPR_MEMORY_BLOCK_SIZE); 37710cffce56SDavid Gibson spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 37720b55aa91SDavid Gibson nr_lmbs, spapr_drc_index(drc)); 3773cf632463SBharata B Rao out: 3774cf632463SBharata B Rao error_propagate(errp, local_err); 3775cf632463SBharata B Rao } 3776cf632463SBharata B Rao 3777765d1bddSDavid Gibson /* Callback to be called during DRC release. */ 3778765d1bddSDavid Gibson void spapr_core_release(DeviceState *dev) 3779ff9006ddSIgor Mammedov { 3780a4261be1SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3781a4261be1SDavid Hildenbrand 3782a4261be1SDavid Hildenbrand /* Call the unplug handler chain. This can never fail. */ 3783a4261be1SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 378407578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 3785a4261be1SDavid Hildenbrand } 3786a4261be1SDavid Hildenbrand 3787a4261be1SDavid Hildenbrand static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 3788a4261be1SDavid Hildenbrand { 3789a4261be1SDavid Hildenbrand MachineState *ms = MACHINE(hotplug_dev); 3790ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms); 3791ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3792535455fdSIgor Mammedov CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL); 3793ff9006ddSIgor Mammedov 379446f7afa3SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 3795ce2918cbSDavid Gibson SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); 379646f7afa3SGreg Kurz int i; 379746f7afa3SGreg Kurz 379846f7afa3SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 379994ad93bdSGreg Kurz CPUState *cs = CPU(sc->threads[i]); 380046f7afa3SGreg Kurz 380146f7afa3SGreg Kurz pre_2_10_vmstate_register_dummy_icp(cs->cpu_index); 380246f7afa3SGreg Kurz } 380346f7afa3SGreg Kurz } 380446f7afa3SGreg Kurz 380507572c06SGreg Kurz assert(core_slot); 3806535455fdSIgor Mammedov core_slot->cpu = NULL; 380707578b0aSDavid Hildenbrand object_property_set_bool(OBJECT(dev), false, "realized", NULL); 3808ff9006ddSIgor Mammedov } 3809ff9006ddSIgor Mammedov 3810115debf2SIgor Mammedov static 3811115debf2SIgor Mammedov void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, 3812ff9006ddSIgor Mammedov Error **errp) 3813ff9006ddSIgor Mammedov { 3814ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3815535455fdSIgor Mammedov int index; 3816ce2918cbSDavid Gibson SpaprDrc *drc; 3817535455fdSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3818ff9006ddSIgor Mammedov 3819535455fdSIgor Mammedov if (!spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index)) { 3820535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 3821535455fdSIgor Mammedov cc->core_id); 3822535455fdSIgor Mammedov return; 3823535455fdSIgor Mammedov } 3824ff9006ddSIgor Mammedov if (index == 0) { 3825ff9006ddSIgor Mammedov error_setg(errp, "Boot CPU core may not be unplugged"); 3826ff9006ddSIgor Mammedov return; 3827ff9006ddSIgor Mammedov } 3828ff9006ddSIgor Mammedov 38295d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 38305d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 3831ff9006ddSIgor Mammedov g_assert(drc); 3832ff9006ddSIgor Mammedov 3833a8dc47fdSDavid Gibson spapr_drc_detach(drc); 3834ff9006ddSIgor Mammedov 3835ff9006ddSIgor Mammedov spapr_hotplug_req_remove_by_index(drc); 3836ff9006ddSIgor Mammedov } 3837ff9006ddSIgor Mammedov 3838ce2918cbSDavid Gibson int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 3839345b12b9SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 3840345b12b9SGreg Kurz { 3841ce2918cbSDavid Gibson SpaprCpuCore *core = SPAPR_CPU_CORE(drc->dev); 3842345b12b9SGreg Kurz CPUState *cs = CPU(core->threads[0]); 3843345b12b9SGreg Kurz PowerPCCPU *cpu = POWERPC_CPU(cs); 3844345b12b9SGreg Kurz DeviceClass *dc = DEVICE_GET_CLASS(cs); 3845345b12b9SGreg Kurz int id = spapr_get_vcpu_id(cpu); 3846345b12b9SGreg Kurz char *nodename; 3847345b12b9SGreg Kurz int offset; 3848345b12b9SGreg Kurz 3849345b12b9SGreg Kurz nodename = g_strdup_printf("%s@%x", dc->fw_name, id); 3850345b12b9SGreg Kurz offset = fdt_add_subnode(fdt, 0, nodename); 3851345b12b9SGreg Kurz g_free(nodename); 3852345b12b9SGreg Kurz 3853345b12b9SGreg Kurz spapr_populate_cpu_dt(cs, fdt, offset, spapr); 3854345b12b9SGreg Kurz 3855345b12b9SGreg Kurz *fdt_start_offset = offset; 3856345b12b9SGreg Kurz return 0; 3857345b12b9SGreg Kurz } 3858345b12b9SGreg Kurz 3859ff9006ddSIgor Mammedov static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3860ff9006ddSIgor Mammedov Error **errp) 3861ff9006ddSIgor Mammedov { 3862ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3863ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(spapr); 3864ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 3865ce2918cbSDavid Gibson SpaprCpuCore *core = SPAPR_CPU_CORE(OBJECT(dev)); 3866ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3867345b12b9SGreg Kurz CPUState *cs; 3868ce2918cbSDavid Gibson SpaprDrc *drc; 3869ff9006ddSIgor Mammedov Error *local_err = NULL; 3870535455fdSIgor Mammedov CPUArchId *core_slot; 3871535455fdSIgor Mammedov int index; 387294fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 3873b1e81567SGreg Kurz int i; 3874ff9006ddSIgor Mammedov 3875535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 3876535455fdSIgor Mammedov if (!core_slot) { 3877535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 3878535455fdSIgor Mammedov cc->core_id); 3879535455fdSIgor Mammedov return; 3880535455fdSIgor Mammedov } 38815d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 38825d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 3883ff9006ddSIgor Mammedov 3884c5514d0eSIgor Mammedov g_assert(drc || !mc->has_hotpluggable_cpus); 3885ff9006ddSIgor Mammedov 3886e49c63d5SGreg Kurz if (drc) { 388709d876ceSGreg Kurz spapr_drc_attach(drc, dev, &local_err); 3888ff9006ddSIgor Mammedov if (local_err) { 3889ff9006ddSIgor Mammedov error_propagate(errp, local_err); 3890ff9006ddSIgor Mammedov return; 3891ff9006ddSIgor Mammedov } 3892ff9006ddSIgor Mammedov 389394fd9cbaSLaurent Vivier if (hotplugged) { 3894ff9006ddSIgor Mammedov /* 389594fd9cbaSLaurent Vivier * Send hotplug notification interrupt to the guest only 389694fd9cbaSLaurent Vivier * in case of hotplugged CPUs. 3897ff9006ddSIgor Mammedov */ 3898ff9006ddSIgor Mammedov spapr_hotplug_req_add_by_index(drc); 389994fd9cbaSLaurent Vivier } else { 390094fd9cbaSLaurent Vivier spapr_drc_reset(drc); 3901ff9006ddSIgor Mammedov } 390294fd9cbaSLaurent Vivier } 390394fd9cbaSLaurent Vivier 3904535455fdSIgor Mammedov core_slot->cpu = OBJECT(dev); 390546f7afa3SGreg Kurz 390646f7afa3SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 390746f7afa3SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 3908bc877283SGreg Kurz cs = CPU(core->threads[i]); 390946f7afa3SGreg Kurz pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index); 391046f7afa3SGreg Kurz } 391146f7afa3SGreg Kurz } 3912b1e81567SGreg Kurz 3913b1e81567SGreg Kurz /* 3914b1e81567SGreg Kurz * Set compatibility mode to match the boot CPU, which was either set 3915b1e81567SGreg Kurz * by the machine reset code or by CAS. 3916b1e81567SGreg Kurz */ 3917b1e81567SGreg Kurz if (hotplugged) { 3918b1e81567SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 3919b1e81567SGreg Kurz ppc_set_compat(core->threads[i], POWERPC_CPU(first_cpu)->compat_pvr, 3920b1e81567SGreg Kurz &local_err); 3921b1e81567SGreg Kurz if (local_err) { 3922b1e81567SGreg Kurz error_propagate(errp, local_err); 3923b1e81567SGreg Kurz return; 3924b1e81567SGreg Kurz } 3925b1e81567SGreg Kurz } 3926b1e81567SGreg Kurz } 3927ff9006ddSIgor Mammedov } 3928ff9006ddSIgor Mammedov 3929ff9006ddSIgor Mammedov static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3930ff9006ddSIgor Mammedov Error **errp) 3931ff9006ddSIgor Mammedov { 3932ff9006ddSIgor Mammedov MachineState *machine = MACHINE(OBJECT(hotplug_dev)); 3933ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); 3934ff9006ddSIgor Mammedov Error *local_err = NULL; 3935ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 39362e9c10ebSIgor Mammedov const char *base_core_type = spapr_get_cpu_core_type(machine->cpu_type); 3937ff9006ddSIgor Mammedov const char *type = object_get_typename(OBJECT(dev)); 3938535455fdSIgor Mammedov CPUArchId *core_slot; 3939535455fdSIgor Mammedov int index; 3940fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 3941ff9006ddSIgor Mammedov 3942c5514d0eSIgor Mammedov if (dev->hotplugged && !mc->has_hotpluggable_cpus) { 3943ff9006ddSIgor Mammedov error_setg(&local_err, "CPU hotplug not supported for this machine"); 3944ff9006ddSIgor Mammedov goto out; 3945ff9006ddSIgor Mammedov } 3946ff9006ddSIgor Mammedov 3947ff9006ddSIgor Mammedov if (strcmp(base_core_type, type)) { 3948ff9006ddSIgor Mammedov error_setg(&local_err, "CPU core type should be %s", base_core_type); 3949ff9006ddSIgor Mammedov goto out; 3950ff9006ddSIgor Mammedov } 3951ff9006ddSIgor Mammedov 3952ff9006ddSIgor Mammedov if (cc->core_id % smp_threads) { 3953ff9006ddSIgor Mammedov error_setg(&local_err, "invalid core id %d", cc->core_id); 3954ff9006ddSIgor Mammedov goto out; 3955ff9006ddSIgor Mammedov } 3956ff9006ddSIgor Mammedov 3957459264efSDavid Gibson /* 3958459264efSDavid Gibson * In general we should have homogeneous threads-per-core, but old 3959459264efSDavid Gibson * (pre hotplug support) machine types allow the last core to have 3960459264efSDavid Gibson * reduced threads as a compatibility hack for when we allowed 3961459264efSDavid Gibson * total vcpus not a multiple of threads-per-core. 3962459264efSDavid Gibson */ 3963459264efSDavid Gibson if (mc->has_hotpluggable_cpus && (cc->nr_threads != smp_threads)) { 3964df8658deSGreg Kurz error_setg(&local_err, "invalid nr-threads %d, must be %d", 39658149e299SDavid Gibson cc->nr_threads, smp_threads); 3966df8658deSGreg Kurz goto out; 39678149e299SDavid Gibson } 39688149e299SDavid Gibson 3969535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 3970535455fdSIgor Mammedov if (!core_slot) { 3971ff9006ddSIgor Mammedov error_setg(&local_err, "core id %d out of range", cc->core_id); 3972ff9006ddSIgor Mammedov goto out; 3973ff9006ddSIgor Mammedov } 3974ff9006ddSIgor Mammedov 3975535455fdSIgor Mammedov if (core_slot->cpu) { 3976ff9006ddSIgor Mammedov error_setg(&local_err, "core %d already populated", cc->core_id); 3977ff9006ddSIgor Mammedov goto out; 3978ff9006ddSIgor Mammedov } 3979ff9006ddSIgor Mammedov 3980a0ceb640SIgor Mammedov numa_cpu_pre_plug(core_slot, dev, &local_err); 39810b8497f0SIgor Mammedov 3982ff9006ddSIgor Mammedov out: 3983ff9006ddSIgor Mammedov error_propagate(errp, local_err); 3984ff9006ddSIgor Mammedov } 3985ff9006ddSIgor Mammedov 3986ce2918cbSDavid Gibson int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 3987bb2bdd81SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 3988bb2bdd81SGreg Kurz { 3989ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(drc->dev); 3990bb2bdd81SGreg Kurz int intc_phandle; 3991bb2bdd81SGreg Kurz 3992bb2bdd81SGreg Kurz intc_phandle = spapr_irq_get_phandle(spapr, spapr->fdt_blob, errp); 3993bb2bdd81SGreg Kurz if (intc_phandle <= 0) { 3994bb2bdd81SGreg Kurz return -1; 3995bb2bdd81SGreg Kurz } 3996bb2bdd81SGreg Kurz 3997466e8831SDavid Gibson if (spapr_dt_phb(sphb, intc_phandle, fdt, spapr->irq->nr_msis, 3998bb2bdd81SGreg Kurz fdt_start_offset)) { 3999bb2bdd81SGreg Kurz error_setg(errp, "unable to create FDT node for PHB %d", sphb->index); 4000bb2bdd81SGreg Kurz return -1; 4001bb2bdd81SGreg Kurz } 4002bb2bdd81SGreg Kurz 4003bb2bdd81SGreg Kurz /* generally SLOF creates these, for hotplug it's up to QEMU */ 4004bb2bdd81SGreg Kurz _FDT(fdt_setprop_string(fdt, *fdt_start_offset, "name", "pci")); 4005bb2bdd81SGreg Kurz 4006bb2bdd81SGreg Kurz return 0; 4007bb2bdd81SGreg Kurz } 4008bb2bdd81SGreg Kurz 4009bb2bdd81SGreg Kurz static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 4010bb2bdd81SGreg Kurz Error **errp) 4011bb2bdd81SGreg Kurz { 4012ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 4013ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 4014ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 4015bb2bdd81SGreg Kurz const unsigned windows_supported = spapr_phb_windows_supported(sphb); 4016bb2bdd81SGreg Kurz 4017bb2bdd81SGreg Kurz if (dev->hotplugged && !smc->dr_phb_enabled) { 4018bb2bdd81SGreg Kurz error_setg(errp, "PHB hotplug not supported for this machine"); 4019bb2bdd81SGreg Kurz return; 4020bb2bdd81SGreg Kurz } 4021bb2bdd81SGreg Kurz 4022bb2bdd81SGreg Kurz if (sphb->index == (uint32_t)-1) { 4023bb2bdd81SGreg Kurz error_setg(errp, "\"index\" for PAPR PHB is mandatory"); 4024bb2bdd81SGreg Kurz return; 4025bb2bdd81SGreg Kurz } 4026bb2bdd81SGreg Kurz 4027bb2bdd81SGreg Kurz /* 4028bb2bdd81SGreg Kurz * This will check that sphb->index doesn't exceed the maximum number of 4029bb2bdd81SGreg Kurz * PHBs for the current machine type. 4030bb2bdd81SGreg Kurz */ 4031bb2bdd81SGreg Kurz smc->phb_placement(spapr, sphb->index, 4032bb2bdd81SGreg Kurz &sphb->buid, &sphb->io_win_addr, 4033bb2bdd81SGreg Kurz &sphb->mem_win_addr, &sphb->mem64_win_addr, 4034ec132efaSAlexey Kardashevskiy windows_supported, sphb->dma_liobn, 4035ec132efaSAlexey Kardashevskiy &sphb->nv2_gpa_win_addr, &sphb->nv2_atsd_win_addr, 4036ec132efaSAlexey Kardashevskiy errp); 4037bb2bdd81SGreg Kurz } 4038bb2bdd81SGreg Kurz 4039bb2bdd81SGreg Kurz static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 4040bb2bdd81SGreg Kurz Error **errp) 4041bb2bdd81SGreg Kurz { 4042ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 4043ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 4044ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 4045ce2918cbSDavid Gibson SpaprDrc *drc; 4046bb2bdd81SGreg Kurz bool hotplugged = spapr_drc_hotplugged(dev); 4047bb2bdd81SGreg Kurz Error *local_err = NULL; 4048bb2bdd81SGreg Kurz 4049bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) { 4050bb2bdd81SGreg Kurz return; 4051bb2bdd81SGreg Kurz } 4052bb2bdd81SGreg Kurz 4053bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); 4054bb2bdd81SGreg Kurz /* hotplug hooks should check it's enabled before getting this far */ 4055bb2bdd81SGreg Kurz assert(drc); 4056bb2bdd81SGreg Kurz 4057bb2bdd81SGreg Kurz spapr_drc_attach(drc, DEVICE(dev), &local_err); 4058bb2bdd81SGreg Kurz if (local_err) { 4059bb2bdd81SGreg Kurz error_propagate(errp, local_err); 4060bb2bdd81SGreg Kurz return; 4061bb2bdd81SGreg Kurz } 4062bb2bdd81SGreg Kurz 4063bb2bdd81SGreg Kurz if (hotplugged) { 4064bb2bdd81SGreg Kurz spapr_hotplug_req_add_by_index(drc); 4065bb2bdd81SGreg Kurz } else { 4066bb2bdd81SGreg Kurz spapr_drc_reset(drc); 4067bb2bdd81SGreg Kurz } 4068bb2bdd81SGreg Kurz } 4069bb2bdd81SGreg Kurz 4070bb2bdd81SGreg Kurz void spapr_phb_release(DeviceState *dev) 4071bb2bdd81SGreg Kurz { 4072bb2bdd81SGreg Kurz HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 4073bb2bdd81SGreg Kurz 4074bb2bdd81SGreg Kurz hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 407507578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 4076bb2bdd81SGreg Kurz } 4077bb2bdd81SGreg Kurz 4078bb2bdd81SGreg Kurz static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 4079bb2bdd81SGreg Kurz { 408007578b0aSDavid Hildenbrand object_property_set_bool(OBJECT(dev), false, "realized", NULL); 4081bb2bdd81SGreg Kurz } 4082bb2bdd81SGreg Kurz 4083bb2bdd81SGreg Kurz static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev, 4084bb2bdd81SGreg Kurz DeviceState *dev, Error **errp) 4085bb2bdd81SGreg Kurz { 4086ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 4087ce2918cbSDavid Gibson SpaprDrc *drc; 4088bb2bdd81SGreg Kurz 4089bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); 4090bb2bdd81SGreg Kurz assert(drc); 4091bb2bdd81SGreg Kurz 4092bb2bdd81SGreg Kurz if (!spapr_drc_unplug_requested(drc)) { 4093bb2bdd81SGreg Kurz spapr_drc_detach(drc); 4094bb2bdd81SGreg Kurz spapr_hotplug_req_remove_by_index(drc); 4095bb2bdd81SGreg Kurz } 4096bb2bdd81SGreg Kurz } 4097bb2bdd81SGreg Kurz 40980fb6bd07SMichael Roth static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 40990fb6bd07SMichael Roth Error **errp) 41000fb6bd07SMichael Roth { 41010fb6bd07SMichael Roth SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 41020fb6bd07SMichael Roth SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(dev); 41030fb6bd07SMichael Roth 41040fb6bd07SMichael Roth if (spapr->tpm_proxy != NULL) { 41050fb6bd07SMichael Roth error_setg(errp, "Only one TPM proxy can be specified for this machine"); 41060fb6bd07SMichael Roth return; 41070fb6bd07SMichael Roth } 41080fb6bd07SMichael Roth 41090fb6bd07SMichael Roth spapr->tpm_proxy = tpm_proxy; 41100fb6bd07SMichael Roth } 41110fb6bd07SMichael Roth 41120fb6bd07SMichael Roth static void spapr_tpm_proxy_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 41130fb6bd07SMichael Roth { 41140fb6bd07SMichael Roth SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 41150fb6bd07SMichael Roth 41160fb6bd07SMichael Roth object_property_set_bool(OBJECT(dev), false, "realized", NULL); 41170fb6bd07SMichael Roth object_unparent(OBJECT(dev)); 41180fb6bd07SMichael Roth spapr->tpm_proxy = NULL; 41190fb6bd07SMichael Roth } 41200fb6bd07SMichael Roth 4121c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, 4122c20d332aSBharata B Rao DeviceState *dev, Error **errp) 4123c20d332aSBharata B Rao { 4124c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 412581985f3bSDavid Hildenbrand spapr_memory_plug(hotplug_dev, dev, errp); 4126af81cf32SBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4127af81cf32SBharata B Rao spapr_core_plug(hotplug_dev, dev, errp); 4128bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4129bb2bdd81SGreg Kurz spapr_phb_plug(hotplug_dev, dev, errp); 41300fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 41310fb6bd07SMichael Roth spapr_tpm_proxy_plug(hotplug_dev, dev, errp); 4132c20d332aSBharata B Rao } 4133c20d332aSBharata B Rao } 4134c20d332aSBharata B Rao 413588432f44SDavid Hildenbrand static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, 413688432f44SDavid Hildenbrand DeviceState *dev, Error **errp) 413788432f44SDavid Hildenbrand { 41383ec71474SDavid Hildenbrand if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 41393ec71474SDavid Hildenbrand spapr_memory_unplug(hotplug_dev, dev); 4140a4261be1SDavid Hildenbrand } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4141a4261be1SDavid Hildenbrand spapr_core_unplug(hotplug_dev, dev); 4142bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4143bb2bdd81SGreg Kurz spapr_phb_unplug(hotplug_dev, dev); 41440fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 41450fb6bd07SMichael Roth spapr_tpm_proxy_unplug(hotplug_dev, dev); 41463ec71474SDavid Hildenbrand } 414788432f44SDavid Hildenbrand } 414888432f44SDavid Hildenbrand 4149cf632463SBharata B Rao static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev, 4150cf632463SBharata B Rao DeviceState *dev, Error **errp) 4151cf632463SBharata B Rao { 4152ce2918cbSDavid Gibson SpaprMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev)); 4153c86c1affSDaniel Henrique Barboza MachineClass *mc = MACHINE_GET_CLASS(sms); 4154ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4155cf632463SBharata B Rao 4156cf632463SBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 4157cf632463SBharata B Rao if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) { 4158cf632463SBharata B Rao spapr_memory_unplug_request(hotplug_dev, dev, errp); 4159cf632463SBharata B Rao } else { 4160cf632463SBharata B Rao /* NOTE: this means there is a window after guest reset, prior to 4161cf632463SBharata B Rao * CAS negotiation, where unplug requests will fail due to the 4162cf632463SBharata B Rao * capability not being detected yet. This is a bit different than 4163cf632463SBharata B Rao * the case with PCI unplug, where the events will be queued and 4164cf632463SBharata B Rao * eventually handled by the guest after boot 4165cf632463SBharata B Rao */ 4166cf632463SBharata B Rao error_setg(errp, "Memory hot unplug not supported for this guest"); 4167cf632463SBharata B Rao } 41686f4b5c3eSBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4169c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 41706f4b5c3eSBharata B Rao error_setg(errp, "CPU hot unplug not supported on this machine"); 41716f4b5c3eSBharata B Rao return; 41726f4b5c3eSBharata B Rao } 4173115debf2SIgor Mammedov spapr_core_unplug_request(hotplug_dev, dev, errp); 4174bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4175bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) { 4176bb2bdd81SGreg Kurz error_setg(errp, "PHB hot unplug not supported on this machine"); 4177bb2bdd81SGreg Kurz return; 4178bb2bdd81SGreg Kurz } 4179bb2bdd81SGreg Kurz spapr_phb_unplug_request(hotplug_dev, dev, errp); 41800fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 41810fb6bd07SMichael Roth spapr_tpm_proxy_unplug(hotplug_dev, dev); 4182c20d332aSBharata B Rao } 4183c20d332aSBharata B Rao } 4184c20d332aSBharata B Rao 418594a94e4cSBharata B Rao static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, 418694a94e4cSBharata B Rao DeviceState *dev, Error **errp) 418794a94e4cSBharata B Rao { 4188c871bc70SLaurent Vivier if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 4189c871bc70SLaurent Vivier spapr_memory_pre_plug(hotplug_dev, dev, errp); 4190c871bc70SLaurent Vivier } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 419194a94e4cSBharata B Rao spapr_core_pre_plug(hotplug_dev, dev, errp); 4192bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4193bb2bdd81SGreg Kurz spapr_phb_pre_plug(hotplug_dev, dev, errp); 419494a94e4cSBharata B Rao } 419594a94e4cSBharata B Rao } 419694a94e4cSBharata B Rao 41977ebaf795SBharata B Rao static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine, 4198c20d332aSBharata B Rao DeviceState *dev) 4199c20d332aSBharata B Rao { 420094a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || 4201bb2bdd81SGreg Kurz object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE) || 42020fb6bd07SMichael Roth object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE) || 42030fb6bd07SMichael Roth object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 4204c20d332aSBharata B Rao return HOTPLUG_HANDLER(machine); 4205c20d332aSBharata B Rao } 4206cb600087SDavid Gibson if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { 4207cb600087SDavid Gibson PCIDevice *pcidev = PCI_DEVICE(dev); 4208cb600087SDavid Gibson PCIBus *root = pci_device_root_bus(pcidev); 4209cb600087SDavid Gibson SpaprPhbState *phb = 4210cb600087SDavid Gibson (SpaprPhbState *)object_dynamic_cast(OBJECT(BUS(root)->parent), 4211cb600087SDavid Gibson TYPE_SPAPR_PCI_HOST_BRIDGE); 4212cb600087SDavid Gibson 4213cb600087SDavid Gibson if (phb) { 4214cb600087SDavid Gibson return HOTPLUG_HANDLER(phb); 4215cb600087SDavid Gibson } 4216cb600087SDavid Gibson } 4217c20d332aSBharata B Rao return NULL; 4218c20d332aSBharata B Rao } 4219c20d332aSBharata B Rao 4220ea089eebSIgor Mammedov static CpuInstanceProperties 4221ea089eebSIgor Mammedov spapr_cpu_index_to_props(MachineState *machine, unsigned cpu_index) 422220bb648dSDavid Gibson { 4223ea089eebSIgor Mammedov CPUArchId *core_slot; 4224ea089eebSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 4225ea089eebSIgor Mammedov 4226ea089eebSIgor Mammedov /* make sure possible_cpu are intialized */ 4227ea089eebSIgor Mammedov mc->possible_cpu_arch_ids(machine); 4228ea089eebSIgor Mammedov /* get CPU core slot containing thread that matches cpu_index */ 4229ea089eebSIgor Mammedov core_slot = spapr_find_cpu_slot(machine, cpu_index, NULL); 4230ea089eebSIgor Mammedov assert(core_slot); 4231ea089eebSIgor Mammedov return core_slot->props; 423220bb648dSDavid Gibson } 423320bb648dSDavid Gibson 423479e07936SIgor Mammedov static int64_t spapr_get_default_cpu_node_id(const MachineState *ms, int idx) 423579e07936SIgor Mammedov { 4236aa570207STao Xu return idx / ms->smp.cores % ms->numa_state->num_nodes; 423779e07936SIgor Mammedov } 423879e07936SIgor Mammedov 4239535455fdSIgor Mammedov static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine) 4240535455fdSIgor Mammedov { 4241535455fdSIgor Mammedov int i; 4242fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 4243fe6b6346SLike Xu unsigned int smp_cpus = machine->smp.cpus; 4244d342eb76SIgor Mammedov const char *core_type; 4245fe6b6346SLike Xu int spapr_max_cores = machine->smp.max_cpus / smp_threads; 4246535455fdSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 4247535455fdSIgor Mammedov 4248c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 4249535455fdSIgor Mammedov spapr_max_cores = QEMU_ALIGN_UP(smp_cpus, smp_threads) / smp_threads; 4250535455fdSIgor Mammedov } 4251535455fdSIgor Mammedov if (machine->possible_cpus) { 4252535455fdSIgor Mammedov assert(machine->possible_cpus->len == spapr_max_cores); 4253535455fdSIgor Mammedov return machine->possible_cpus; 4254535455fdSIgor Mammedov } 4255535455fdSIgor Mammedov 4256d342eb76SIgor Mammedov core_type = spapr_get_cpu_core_type(machine->cpu_type); 4257d342eb76SIgor Mammedov if (!core_type) { 4258d342eb76SIgor Mammedov error_report("Unable to find sPAPR CPU Core definition"); 4259d342eb76SIgor Mammedov exit(1); 4260d342eb76SIgor Mammedov } 4261d342eb76SIgor Mammedov 4262535455fdSIgor Mammedov machine->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + 4263535455fdSIgor Mammedov sizeof(CPUArchId) * spapr_max_cores); 4264535455fdSIgor Mammedov machine->possible_cpus->len = spapr_max_cores; 4265535455fdSIgor Mammedov for (i = 0; i < machine->possible_cpus->len; i++) { 4266535455fdSIgor Mammedov int core_id = i * smp_threads; 4267535455fdSIgor Mammedov 4268d342eb76SIgor Mammedov machine->possible_cpus->cpus[i].type = core_type; 4269f2d672c2SIgor Mammedov machine->possible_cpus->cpus[i].vcpus_count = smp_threads; 4270535455fdSIgor Mammedov machine->possible_cpus->cpus[i].arch_id = core_id; 4271535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.has_core_id = true; 4272535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.core_id = core_id; 4273535455fdSIgor Mammedov } 4274535455fdSIgor Mammedov return machine->possible_cpus; 4275535455fdSIgor Mammedov } 4276535455fdSIgor Mammedov 4277ce2918cbSDavid Gibson static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index, 4278daa23699SDavid Gibson uint64_t *buid, hwaddr *pio, 4279daa23699SDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 4280ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4281ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 42826737d9adSDavid Gibson { 4283357d1e3bSDavid Gibson /* 4284357d1e3bSDavid Gibson * New-style PHB window placement. 4285357d1e3bSDavid Gibson * 4286357d1e3bSDavid Gibson * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window 4287357d1e3bSDavid Gibson * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO 4288357d1e3bSDavid Gibson * windows. 4289357d1e3bSDavid Gibson * 4290357d1e3bSDavid Gibson * Some guest kernels can't work with MMIO windows above 1<<46 4291357d1e3bSDavid Gibson * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB 4292357d1e3bSDavid Gibson * 4293357d1e3bSDavid Gibson * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each 4294357d1e3bSDavid Gibson * PHB stacked together. (32TiB+2GiB)..(32TiB+64GiB) contains the 4295357d1e3bSDavid Gibson * 2GiB 32-bit MMIO windows for each PHB. Then 33..64TiB has the 4296357d1e3bSDavid Gibson * 1TiB 64-bit MMIO windows for each PHB. 4297357d1e3bSDavid Gibson */ 42986737d9adSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 42996737d9adSDavid Gibson int i; 43006737d9adSDavid Gibson 4301357d1e3bSDavid Gibson /* Sanity check natural alignments */ 4302357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 4303357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 4304357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0); 4305357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0); 4306357d1e3bSDavid Gibson /* Sanity check bounds */ 430725e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_IO_WIN_SIZE) > 430825e6a118SMichael S. Tsirkin SPAPR_PCI_MEM32_WIN_SIZE); 430925e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_MEM32_WIN_SIZE) > 431025e6a118SMichael S. Tsirkin SPAPR_PCI_MEM64_WIN_SIZE); 43112efff1c0SDavid Gibson 431225e6a118SMichael S. Tsirkin if (index >= SPAPR_MAX_PHBS) { 431325e6a118SMichael S. Tsirkin error_setg(errp, "\"index\" for PAPR PHB is too large (max %llu)", 431425e6a118SMichael S. Tsirkin SPAPR_MAX_PHBS - 1); 43156737d9adSDavid Gibson return; 43166737d9adSDavid Gibson } 43176737d9adSDavid Gibson 43186737d9adSDavid Gibson *buid = base_buid + index; 43196737d9adSDavid Gibson for (i = 0; i < n_dma; ++i) { 43206737d9adSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 43216737d9adSDavid Gibson } 43226737d9adSDavid Gibson 4323357d1e3bSDavid Gibson *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE; 4324357d1e3bSDavid Gibson *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE; 4325357d1e3bSDavid Gibson *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE; 4326ec132efaSAlexey Kardashevskiy 4327ec132efaSAlexey Kardashevskiy *nv2gpa = SPAPR_PCI_NV2RAM64_WIN_BASE + index * SPAPR_PCI_NV2RAM64_WIN_SIZE; 4328ec132efaSAlexey Kardashevskiy *nv2atsd = SPAPR_PCI_NV2ATSD_WIN_BASE + index * SPAPR_PCI_NV2ATSD_WIN_SIZE; 43296737d9adSDavid Gibson } 43306737d9adSDavid Gibson 43317844e12bSCédric Le Goater static ICSState *spapr_ics_get(XICSFabric *dev, int irq) 43327844e12bSCédric Le Goater { 4333ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(dev); 43347844e12bSCédric Le Goater 43357844e12bSCédric Le Goater return ics_valid_irq(spapr->ics, irq) ? spapr->ics : NULL; 43367844e12bSCédric Le Goater } 43377844e12bSCédric Le Goater 43387844e12bSCédric Le Goater static void spapr_ics_resend(XICSFabric *dev) 43397844e12bSCédric Le Goater { 4340ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(dev); 43417844e12bSCédric Le Goater 43427844e12bSCédric Le Goater ics_resend(spapr->ics); 43437844e12bSCédric Le Goater } 43447844e12bSCédric Le Goater 434581210c20SSam Bobroff static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id) 4346b2fc59aaSCédric Le Goater { 43472e886fb3SSam Bobroff PowerPCCPU *cpu = spapr_find_cpu(vcpu_id); 4348b2fc59aaSCédric Le Goater 4349a28b9a5aSCédric Le Goater return cpu ? spapr_cpu_state(cpu)->icp : NULL; 4350b2fc59aaSCédric Le Goater } 4351b2fc59aaSCédric Le Goater 43526449da45SCédric Le Goater static void spapr_pic_print_info(InterruptStatsProvider *obj, 43536449da45SCédric Le Goater Monitor *mon) 43546449da45SCédric Le Goater { 4355ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 43566449da45SCédric Le Goater 43573ba3d0bcSCédric Le Goater spapr->irq->print_info(spapr, mon); 4358f041d6afSGreg Kurz monitor_printf(mon, "irqchip: %s\n", 4359f041d6afSGreg Kurz kvm_irqchip_in_kernel() ? "in-kernel" : "emulated"); 43606449da45SCédric Le Goater } 43616449da45SCédric Le Goater 436214bb4486SGreg Kurz int spapr_get_vcpu_id(PowerPCCPU *cpu) 43632e886fb3SSam Bobroff { 4364b1a568c1SGreg Kurz return cpu->vcpu_id; 43652e886fb3SSam Bobroff } 43662e886fb3SSam Bobroff 4367648edb64SGreg Kurz void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp) 4368648edb64SGreg Kurz { 4369ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 4370fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 4371648edb64SGreg Kurz int vcpu_id; 4372648edb64SGreg Kurz 43735d0fb150SGreg Kurz vcpu_id = spapr_vcpu_id(spapr, cpu_index); 4374648edb64SGreg Kurz 4375648edb64SGreg Kurz if (kvm_enabled() && !kvm_vcpu_id_is_valid(vcpu_id)) { 4376648edb64SGreg Kurz error_setg(errp, "Can't create CPU with id %d in KVM", vcpu_id); 4377648edb64SGreg Kurz error_append_hint(errp, "Adjust the number of cpus to %d " 4378648edb64SGreg Kurz "or try to raise the number of threads per core\n", 4379fe6b6346SLike Xu vcpu_id * ms->smp.threads / spapr->vsmt); 4380648edb64SGreg Kurz return; 4381648edb64SGreg Kurz } 4382648edb64SGreg Kurz 4383648edb64SGreg Kurz cpu->vcpu_id = vcpu_id; 4384648edb64SGreg Kurz } 4385648edb64SGreg Kurz 43862e886fb3SSam Bobroff PowerPCCPU *spapr_find_cpu(int vcpu_id) 43872e886fb3SSam Bobroff { 43882e886fb3SSam Bobroff CPUState *cs; 43892e886fb3SSam Bobroff 43902e886fb3SSam Bobroff CPU_FOREACH(cs) { 43912e886fb3SSam Bobroff PowerPCCPU *cpu = POWERPC_CPU(cs); 43922e886fb3SSam Bobroff 439314bb4486SGreg Kurz if (spapr_get_vcpu_id(cpu) == vcpu_id) { 43942e886fb3SSam Bobroff return cpu; 43952e886fb3SSam Bobroff } 43962e886fb3SSam Bobroff } 43972e886fb3SSam Bobroff 43982e886fb3SSam Bobroff return NULL; 43992e886fb3SSam Bobroff } 44002e886fb3SSam Bobroff 440103ef074cSNicholas Piggin static void spapr_cpu_exec_enter(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) 440203ef074cSNicholas Piggin { 440303ef074cSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 440403ef074cSNicholas Piggin 440503ef074cSNicholas Piggin /* These are only called by TCG, KVM maintains dispatch state */ 440603ef074cSNicholas Piggin 44073a6e6224SNicholas Piggin spapr_cpu->prod = false; 440803ef074cSNicholas Piggin if (spapr_cpu->vpa_addr) { 440903ef074cSNicholas Piggin CPUState *cs = CPU(cpu); 441003ef074cSNicholas Piggin uint32_t dispatch; 441103ef074cSNicholas Piggin 441203ef074cSNicholas Piggin dispatch = ldl_be_phys(cs->as, 441303ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER); 441403ef074cSNicholas Piggin dispatch++; 441503ef074cSNicholas Piggin if ((dispatch & 1) != 0) { 441603ef074cSNicholas Piggin qemu_log_mask(LOG_GUEST_ERROR, 441703ef074cSNicholas Piggin "VPA: incorrect dispatch counter value for " 441803ef074cSNicholas Piggin "dispatched partition %u, correcting.\n", dispatch); 441903ef074cSNicholas Piggin dispatch++; 442003ef074cSNicholas Piggin } 442103ef074cSNicholas Piggin stl_be_phys(cs->as, 442203ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch); 442303ef074cSNicholas Piggin } 442403ef074cSNicholas Piggin } 442503ef074cSNicholas Piggin 442603ef074cSNicholas Piggin static void spapr_cpu_exec_exit(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) 442703ef074cSNicholas Piggin { 442803ef074cSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 442903ef074cSNicholas Piggin 443003ef074cSNicholas Piggin if (spapr_cpu->vpa_addr) { 443103ef074cSNicholas Piggin CPUState *cs = CPU(cpu); 443203ef074cSNicholas Piggin uint32_t dispatch; 443303ef074cSNicholas Piggin 443403ef074cSNicholas Piggin dispatch = ldl_be_phys(cs->as, 443503ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER); 443603ef074cSNicholas Piggin dispatch++; 443703ef074cSNicholas Piggin if ((dispatch & 1) != 1) { 443803ef074cSNicholas Piggin qemu_log_mask(LOG_GUEST_ERROR, 443903ef074cSNicholas Piggin "VPA: incorrect dispatch counter value for " 444003ef074cSNicholas Piggin "preempted partition %u, correcting.\n", dispatch); 444103ef074cSNicholas Piggin dispatch++; 444203ef074cSNicholas Piggin } 444303ef074cSNicholas Piggin stl_be_phys(cs->as, 444403ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch); 444503ef074cSNicholas Piggin } 444603ef074cSNicholas Piggin } 444703ef074cSNicholas Piggin 444829ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data) 444953018216SPaolo Bonzini { 445029ee3247SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 4451ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(oc); 445271461b0fSAlexey Kardashevskiy FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); 445334316482SAlexey Kardashevskiy NMIClass *nc = NMI_CLASS(oc); 4454c20d332aSBharata B Rao HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); 44551d1be34dSDavid Gibson PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc); 44567844e12bSCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 44576449da45SCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 445829ee3247SAlexey Kardashevskiy 44590eb9054cSDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant)"; 4460907aac2fSMark Cave-Ayland mc->ignore_boot_device_suffixes = true; 4461fc9f38c3SDavid Gibson 4462fc9f38c3SDavid Gibson /* 4463fc9f38c3SDavid Gibson * We set up the default / latest behaviour here. The class_init 4464fc9f38c3SDavid Gibson * functions for the specific versioned machine types can override 4465fc9f38c3SDavid Gibson * these details for backwards compatibility 4466fc9f38c3SDavid Gibson */ 4467bcb5ce08SDavid Gibson mc->init = spapr_machine_init; 4468bcb5ce08SDavid Gibson mc->reset = spapr_machine_reset; 4469958db90cSMarcel Apfelbaum mc->block_default_type = IF_SCSI; 44706244bb7eSGreg Kurz mc->max_cpus = 1024; 4471958db90cSMarcel Apfelbaum mc->no_parallel = 1; 44725b2128d2SAlexander Graf mc->default_boot_order = ""; 4473d23b6caaSPhilippe Mathieu-Daudé mc->default_ram_size = 512 * MiB; 447429f9cef3SSebastian Bauer mc->default_display = "std"; 4475958db90cSMarcel Apfelbaum mc->kvm_type = spapr_kvm_type; 44767da79a16SEduardo Habkost machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SPAPR_PCI_HOST_BRIDGE); 4477e4024630SLaurent Vivier mc->pci_allow_0_address = true; 4478debbdc00SIgor Mammedov assert(!mc->get_hotplug_handler); 44797ebaf795SBharata B Rao mc->get_hotplug_handler = spapr_get_hotplug_handler; 448094a94e4cSBharata B Rao hc->pre_plug = spapr_machine_device_pre_plug; 4481c20d332aSBharata B Rao hc->plug = spapr_machine_device_plug; 4482ea089eebSIgor Mammedov mc->cpu_index_to_instance_props = spapr_cpu_index_to_props; 448379e07936SIgor Mammedov mc->get_default_cpu_node_id = spapr_get_default_cpu_node_id; 4484535455fdSIgor Mammedov mc->possible_cpu_arch_ids = spapr_possible_cpu_arch_ids; 4485cf632463SBharata B Rao hc->unplug_request = spapr_machine_device_unplug_request; 448688432f44SDavid Hildenbrand hc->unplug = spapr_machine_device_unplug; 448700b4fbe2SMarcel Apfelbaum 4488fc9f38c3SDavid Gibson smc->dr_lmb_enabled = true; 4489fea35ca4SAlexey Kardashevskiy smc->update_dt_enabled = true; 449034a6b015SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 4491c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = true; 449252b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED; 449371461b0fSAlexey Kardashevskiy fwc->get_dev_path = spapr_get_fw_dev_path; 449434316482SAlexey Kardashevskiy nc->nmi_monitor_handler = spapr_nmi; 44956737d9adSDavid Gibson smc->phb_placement = spapr_phb_placement; 44961d1be34dSDavid Gibson vhc->hypercall = emulate_spapr_hypercall; 4497e57ca75cSDavid Gibson vhc->hpt_mask = spapr_hpt_mask; 4498e57ca75cSDavid Gibson vhc->map_hptes = spapr_map_hptes; 4499e57ca75cSDavid Gibson vhc->unmap_hptes = spapr_unmap_hptes; 4500a2dd4e83SBenjamin Herrenschmidt vhc->hpte_set_c = spapr_hpte_set_c; 4501a2dd4e83SBenjamin Herrenschmidt vhc->hpte_set_r = spapr_hpte_set_r; 450279825f4dSBenjamin Herrenschmidt vhc->get_pate = spapr_get_pate; 45031ec26c75SGreg Kurz vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr; 450403ef074cSNicholas Piggin vhc->cpu_exec_enter = spapr_cpu_exec_enter; 450503ef074cSNicholas Piggin vhc->cpu_exec_exit = spapr_cpu_exec_exit; 45067844e12bSCédric Le Goater xic->ics_get = spapr_ics_get; 45077844e12bSCédric Le Goater xic->ics_resend = spapr_ics_resend; 4508b2fc59aaSCédric Le Goater xic->icp_get = spapr_icp_get; 45096449da45SCédric Le Goater ispc->print_info = spapr_pic_print_info; 451055641213SLaurent Vivier /* Force NUMA node memory size to be a multiple of 451155641213SLaurent Vivier * SPAPR_MEMORY_BLOCK_SIZE (256M) since that's the granularity 451255641213SLaurent Vivier * in which LMBs are represented and hot-added 451355641213SLaurent Vivier */ 451455641213SLaurent Vivier mc->numa_mem_align_shift = 28; 4515cd5ff833SIgor Mammedov mc->numa_mem_supported = true; 451633face6bSDavid Gibson 45174e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF; 45184e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON; 45194e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON; 45202782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND; 45212782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND; 45222782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_WORKAROUND; 45232309832aSDavid Gibson smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */ 4524b9a477b7SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF; 4525edaa7995SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON; 45268ff43ee4SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF; 452733face6bSDavid Gibson spapr_caps_add_properties(smc, &error_abort); 4528bd94bc06SCédric Le Goater smc->irq = &spapr_irq_dual; 4529dae5e39aSMichael Roth smc->dr_phb_enabled = true; 45306c3829a2SAlexey Kardashevskiy smc->linux_pci_probe = true; 453153018216SPaolo Bonzini } 453253018216SPaolo Bonzini 453329ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = { 453429ee3247SAlexey Kardashevskiy .name = TYPE_SPAPR_MACHINE, 453529ee3247SAlexey Kardashevskiy .parent = TYPE_MACHINE, 45364aee7362SDavid Gibson .abstract = true, 4537ce2918cbSDavid Gibson .instance_size = sizeof(SpaprMachineState), 4538bcb5ce08SDavid Gibson .instance_init = spapr_instance_init, 453987bbdd9cSDavid Gibson .instance_finalize = spapr_machine_finalizefn, 4540ce2918cbSDavid Gibson .class_size = sizeof(SpaprMachineClass), 454129ee3247SAlexey Kardashevskiy .class_init = spapr_machine_class_init, 454271461b0fSAlexey Kardashevskiy .interfaces = (InterfaceInfo[]) { 454371461b0fSAlexey Kardashevskiy { TYPE_FW_PATH_PROVIDER }, 454434316482SAlexey Kardashevskiy { TYPE_NMI }, 4545c20d332aSBharata B Rao { TYPE_HOTPLUG_HANDLER }, 45461d1be34dSDavid Gibson { TYPE_PPC_VIRTUAL_HYPERVISOR }, 45477844e12bSCédric Le Goater { TYPE_XICS_FABRIC }, 45486449da45SCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 454971461b0fSAlexey Kardashevskiy { } 455071461b0fSAlexey Kardashevskiy }, 455129ee3247SAlexey Kardashevskiy }; 455229ee3247SAlexey Kardashevskiy 4553fccbc785SDavid Gibson #define DEFINE_SPAPR_MACHINE(suffix, verstr, latest) \ 45545013c547SDavid Gibson static void spapr_machine_##suffix##_class_init(ObjectClass *oc, \ 45555013c547SDavid Gibson void *data) \ 45565013c547SDavid Gibson { \ 45575013c547SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); \ 45585013c547SDavid Gibson spapr_machine_##suffix##_class_options(mc); \ 4559fccbc785SDavid Gibson if (latest) { \ 4560fccbc785SDavid Gibson mc->alias = "pseries"; \ 4561fccbc785SDavid Gibson mc->is_default = 1; \ 4562fccbc785SDavid Gibson } \ 45635013c547SDavid Gibson } \ 45645013c547SDavid Gibson static const TypeInfo spapr_machine_##suffix##_info = { \ 45655013c547SDavid Gibson .name = MACHINE_TYPE_NAME("pseries-" verstr), \ 45665013c547SDavid Gibson .parent = TYPE_SPAPR_MACHINE, \ 45675013c547SDavid Gibson .class_init = spapr_machine_##suffix##_class_init, \ 45685013c547SDavid Gibson }; \ 45695013c547SDavid Gibson static void spapr_machine_register_##suffix(void) \ 45705013c547SDavid Gibson { \ 45715013c547SDavid Gibson type_register(&spapr_machine_##suffix##_info); \ 45725013c547SDavid Gibson } \ 45730e6aac87SEduardo Habkost type_init(spapr_machine_register_##suffix) 45745013c547SDavid Gibson 45751c5f29bbSDavid Gibson /* 45769aec2e52SCornelia Huck * pseries-4.2 4577e2676b16SGreg Kurz */ 45789aec2e52SCornelia Huck static void spapr_machine_4_2_class_options(MachineClass *mc) 4579e2676b16SGreg Kurz { 4580e2676b16SGreg Kurz /* Defaults for the latest behaviour inherited from the base class */ 4581e2676b16SGreg Kurz } 4582e2676b16SGreg Kurz 45839aec2e52SCornelia Huck DEFINE_SPAPR_MACHINE(4_2, "4.2", true); 45849aec2e52SCornelia Huck 45859aec2e52SCornelia Huck /* 45869aec2e52SCornelia Huck * pseries-4.1 45879aec2e52SCornelia Huck */ 45889aec2e52SCornelia Huck static void spapr_machine_4_1_class_options(MachineClass *mc) 45899aec2e52SCornelia Huck { 45906c3829a2SAlexey Kardashevskiy SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4591d15d4ad6SDavid Gibson static GlobalProperty compat[] = { 4592d15d4ad6SDavid Gibson /* Only allow 4kiB and 64kiB IOMMU pagesizes */ 4593d15d4ad6SDavid Gibson { TYPE_SPAPR_PCI_HOST_BRIDGE, "pgsz", "0x11000" }, 4594d15d4ad6SDavid Gibson }; 4595d15d4ad6SDavid Gibson 45969aec2e52SCornelia Huck spapr_machine_4_2_class_options(mc); 45976c3829a2SAlexey Kardashevskiy smc->linux_pci_probe = false; 45989aec2e52SCornelia Huck compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len); 4599d15d4ad6SDavid Gibson compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 46009aec2e52SCornelia Huck } 46019aec2e52SCornelia Huck 46029aec2e52SCornelia Huck DEFINE_SPAPR_MACHINE(4_1, "4.1", false); 46039bf2650bSCornelia Huck 46049bf2650bSCornelia Huck /* 46059bf2650bSCornelia Huck * pseries-4.0 46069bf2650bSCornelia Huck */ 4607eb3cba82SDavid Gibson static void phb_placement_4_0(SpaprMachineState *spapr, uint32_t index, 4608ec132efaSAlexey Kardashevskiy uint64_t *buid, hwaddr *pio, 4609ec132efaSAlexey Kardashevskiy hwaddr *mmio32, hwaddr *mmio64, 4610ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4611ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 4612ec132efaSAlexey Kardashevskiy { 4613ec132efaSAlexey Kardashevskiy spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma, liobns, 4614ec132efaSAlexey Kardashevskiy nv2gpa, nv2atsd, errp); 4615ec132efaSAlexey Kardashevskiy *nv2gpa = 0; 4616ec132efaSAlexey Kardashevskiy *nv2atsd = 0; 4617ec132efaSAlexey Kardashevskiy } 4618ec132efaSAlexey Kardashevskiy 4619eb3cba82SDavid Gibson static void spapr_machine_4_0_class_options(MachineClass *mc) 4620eb3cba82SDavid Gibson { 4621eb3cba82SDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4622eb3cba82SDavid Gibson 4623eb3cba82SDavid Gibson spapr_machine_4_1_class_options(mc); 4624eb3cba82SDavid Gibson compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); 4625eb3cba82SDavid Gibson smc->phb_placement = phb_placement_4_0; 4626bd94bc06SCédric Le Goater smc->irq = &spapr_irq_xics; 46273725ef1aSGreg Kurz smc->pre_4_1_migration = true; 4628eb3cba82SDavid Gibson } 4629eb3cba82SDavid Gibson 4630eb3cba82SDavid Gibson DEFINE_SPAPR_MACHINE(4_0, "4.0", false); 4631eb3cba82SDavid Gibson 4632eb3cba82SDavid Gibson /* 4633eb3cba82SDavid Gibson * pseries-3.1 4634eb3cba82SDavid Gibson */ 463588cbe073SMarc-André Lureau static void spapr_machine_3_1_class_options(MachineClass *mc) 463688cbe073SMarc-André Lureau { 4637ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4638fea35ca4SAlexey Kardashevskiy 463984e060bfSAlex Williamson spapr_machine_4_0_class_options(mc); 4640abd93cc7SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len); 464127461d69SPrasad J Pandit 464234a6b015SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 4643fea35ca4SAlexey Kardashevskiy smc->update_dt_enabled = false; 4644dae5e39aSMichael Roth smc->dr_phb_enabled = false; 46450a794529SDavid Gibson smc->broken_host_serial_model = true; 46462782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN; 46472782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN; 46482782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN; 4649edaa7995SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF; 465084e060bfSAlex Williamson } 465184e060bfSAlex Williamson 465284e060bfSAlex Williamson DEFINE_SPAPR_MACHINE(3_1, "3.1", false); 4653d45360d9SCédric Le Goater 4654d45360d9SCédric Le Goater /* 4655d45360d9SCédric Le Goater * pseries-3.0 4656d45360d9SCédric Le Goater */ 4657d45360d9SCédric Le Goater 4658d45360d9SCédric Le Goater static void spapr_machine_3_0_class_options(MachineClass *mc) 4659d45360d9SCédric Le Goater { 4660ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 466182cffa2eSCédric Le Goater 4662d45360d9SCédric Le Goater spapr_machine_3_1_class_options(mc); 4663ddb3235dSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len); 466482cffa2eSCédric Le Goater 466582cffa2eSCédric Le Goater smc->legacy_irq_allocation = true; 4666ae837402SCédric Le Goater smc->irq = &spapr_irq_xics_legacy; 4667d45360d9SCédric Le Goater } 4668d45360d9SCédric Le Goater 4669d45360d9SCédric Le Goater DEFINE_SPAPR_MACHINE(3_0, "3.0", false); 46708a4fd427SDavid Gibson 46718a4fd427SDavid Gibson /* 46728a4fd427SDavid Gibson * pseries-2.12 46738a4fd427SDavid Gibson */ 467488cbe073SMarc-André Lureau static void spapr_machine_2_12_class_options(MachineClass *mc) 467588cbe073SMarc-André Lureau { 4676ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 467788cbe073SMarc-André Lureau static GlobalProperty compat[] = { 46786c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-3.0-migration", "on" }, 46796c36bddfSEduardo Habkost { TYPE_SPAPR_CPU_CORE, "pre-3.0-migration", "on" }, 4680fa386d98SMarc-André Lureau }; 46818a4fd427SDavid Gibson 4682d8c0c7afSPeter Maydell spapr_machine_3_0_class_options(mc); 46830d47310bSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_12, hw_compat_2_12_len); 468488cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 46852309832aSDavid Gibson 4686e8937295SGreg Kurz /* We depend on kvm_enabled() to choose a default value for the 4687e8937295SGreg Kurz * hpt-max-page-size capability. Of course we can't do it here 4688e8937295SGreg Kurz * because this is too early and the HW accelerator isn't initialzed 4689e8937295SGreg Kurz * yet. Postpone this to machine init (see default_caps_with_cpu()). 4690e8937295SGreg Kurz */ 4691e8937295SGreg Kurz smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 0; 46928a4fd427SDavid Gibson } 46938a4fd427SDavid Gibson 46948a4fd427SDavid Gibson DEFINE_SPAPR_MACHINE(2_12, "2.12", false); 46952b615412SDavid Gibson 4696813f3cf6SSuraj Jitindar Singh static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc) 4697813f3cf6SSuraj Jitindar Singh { 4698ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4699813f3cf6SSuraj Jitindar Singh 4700813f3cf6SSuraj Jitindar Singh spapr_machine_2_12_class_options(mc); 4701813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND; 4702813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND; 4703813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_FIXED_CCD; 4704813f3cf6SSuraj Jitindar Singh } 4705813f3cf6SSuraj Jitindar Singh 4706813f3cf6SSuraj Jitindar Singh DEFINE_SPAPR_MACHINE(2_12_sxxm, "2.12-sxxm", false); 4707813f3cf6SSuraj Jitindar Singh 47082b615412SDavid Gibson /* 47092b615412SDavid Gibson * pseries-2.11 47102b615412SDavid Gibson */ 47112b615412SDavid Gibson 47122b615412SDavid Gibson static void spapr_machine_2_11_class_options(MachineClass *mc) 47132b615412SDavid Gibson { 4714ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4715ee76a09fSDavid Gibson 47162b615412SDavid Gibson spapr_machine_2_12_class_options(mc); 47174e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON; 471843df70a9SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len); 47192b615412SDavid Gibson } 47202b615412SDavid Gibson 47212b615412SDavid Gibson DEFINE_SPAPR_MACHINE(2_11, "2.11", false); 4722e2676b16SGreg Kurz 4723e2676b16SGreg Kurz /* 47243fa14fbeSDavid Gibson * pseries-2.10 4725db800b21SDavid Gibson */ 4726e2676b16SGreg Kurz 47273fa14fbeSDavid Gibson static void spapr_machine_2_10_class_options(MachineClass *mc) 4728db800b21SDavid Gibson { 4729e2676b16SGreg Kurz spapr_machine_2_11_class_options(mc); 4730503224f4SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_10, hw_compat_2_10_len); 4731db800b21SDavid Gibson } 4732db800b21SDavid Gibson 4733e2676b16SGreg Kurz DEFINE_SPAPR_MACHINE(2_10, "2.10", false); 47343fa14fbeSDavid Gibson 47353fa14fbeSDavid Gibson /* 47363fa14fbeSDavid Gibson * pseries-2.9 47373fa14fbeSDavid Gibson */ 473888cbe073SMarc-André Lureau 473988cbe073SMarc-André Lureau static void spapr_machine_2_9_class_options(MachineClass *mc) 474088cbe073SMarc-André Lureau { 4741ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 474288cbe073SMarc-André Lureau static GlobalProperty compat[] = { 47436c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-2.10-migration", "on" }, 4744fa386d98SMarc-André Lureau }; 47453fa14fbeSDavid Gibson 47463fa14fbeSDavid Gibson spapr_machine_2_10_class_options(mc); 47473e803152SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len); 474888cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 47493bfe5716SLaurent Vivier mc->numa_auto_assign_ram = numa_legacy_auto_assign_ram; 475046f7afa3SGreg Kurz smc->pre_2_10_has_unused_icps = true; 475152b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED; 47523fa14fbeSDavid Gibson } 47533fa14fbeSDavid Gibson 47543fa14fbeSDavid Gibson DEFINE_SPAPR_MACHINE(2_9, "2.9", false); 4755fa325e6cSDavid Gibson 4756fa325e6cSDavid Gibson /* 4757fa325e6cSDavid Gibson * pseries-2.8 4758fa325e6cSDavid Gibson */ 475988cbe073SMarc-André Lureau 476088cbe073SMarc-André Lureau static void spapr_machine_2_8_class_options(MachineClass *mc) 476188cbe073SMarc-André Lureau { 476288cbe073SMarc-André Lureau static GlobalProperty compat[] = { 47636c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "pcie-extended-configuration-space", "off" }, 4764fa386d98SMarc-André Lureau }; 4765fa325e6cSDavid Gibson 4766fa325e6cSDavid Gibson spapr_machine_2_9_class_options(mc); 4767edc24ccdSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len); 476888cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 476955641213SLaurent Vivier mc->numa_mem_align_shift = 23; 4770fa325e6cSDavid Gibson } 4771fa325e6cSDavid Gibson 4772fa325e6cSDavid Gibson DEFINE_SPAPR_MACHINE(2_8, "2.8", false); 4773db800b21SDavid Gibson 4774db800b21SDavid Gibson /* 47751ea1eefcSBharata B Rao * pseries-2.7 47761ea1eefcSBharata B Rao */ 4777357d1e3bSDavid Gibson 4778ce2918cbSDavid Gibson static void phb_placement_2_7(SpaprMachineState *spapr, uint32_t index, 4779357d1e3bSDavid Gibson uint64_t *buid, hwaddr *pio, 4780357d1e3bSDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 4781ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4782ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 4783357d1e3bSDavid Gibson { 4784357d1e3bSDavid Gibson /* Legacy PHB placement for pseries-2.7 and earlier machine types */ 4785357d1e3bSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 4786357d1e3bSDavid Gibson const hwaddr phb_spacing = 0x1000000000ULL; /* 64 GiB */ 4787357d1e3bSDavid Gibson const hwaddr mmio_offset = 0xa0000000; /* 2 GiB + 512 MiB */ 4788357d1e3bSDavid Gibson const hwaddr pio_offset = 0x80000000; /* 2 GiB */ 4789357d1e3bSDavid Gibson const uint32_t max_index = 255; 4790357d1e3bSDavid Gibson const hwaddr phb0_alignment = 0x10000000000ULL; /* 1 TiB */ 4791357d1e3bSDavid Gibson 4792357d1e3bSDavid Gibson uint64_t ram_top = MACHINE(spapr)->ram_size; 4793357d1e3bSDavid Gibson hwaddr phb0_base, phb_base; 4794357d1e3bSDavid Gibson int i; 4795357d1e3bSDavid Gibson 47960c9269a5SDavid Hildenbrand /* Do we have device memory? */ 4797357d1e3bSDavid Gibson if (MACHINE(spapr)->maxram_size > ram_top) { 4798357d1e3bSDavid Gibson /* Can't just use maxram_size, because there may be an 47990c9269a5SDavid Hildenbrand * alignment gap between normal and device memory regions 48000c9269a5SDavid Hildenbrand */ 4801b0c14ec4SDavid Hildenbrand ram_top = MACHINE(spapr)->device_memory->base + 4802b0c14ec4SDavid Hildenbrand memory_region_size(&MACHINE(spapr)->device_memory->mr); 4803357d1e3bSDavid Gibson } 4804357d1e3bSDavid Gibson 4805357d1e3bSDavid Gibson phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment); 4806357d1e3bSDavid Gibson 4807357d1e3bSDavid Gibson if (index > max_index) { 4808357d1e3bSDavid Gibson error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", 4809357d1e3bSDavid Gibson max_index); 4810357d1e3bSDavid Gibson return; 4811357d1e3bSDavid Gibson } 4812357d1e3bSDavid Gibson 4813357d1e3bSDavid Gibson *buid = base_buid + index; 4814357d1e3bSDavid Gibson for (i = 0; i < n_dma; ++i) { 4815357d1e3bSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 4816357d1e3bSDavid Gibson } 4817357d1e3bSDavid Gibson 4818357d1e3bSDavid Gibson phb_base = phb0_base + index * phb_spacing; 4819357d1e3bSDavid Gibson *pio = phb_base + pio_offset; 4820357d1e3bSDavid Gibson *mmio32 = phb_base + mmio_offset; 4821357d1e3bSDavid Gibson /* 4822357d1e3bSDavid Gibson * We don't set the 64-bit MMIO window, relying on the PHB's 4823357d1e3bSDavid Gibson * fallback behaviour of automatically splitting a large "32-bit" 4824357d1e3bSDavid Gibson * window into contiguous 32-bit and 64-bit windows 4825357d1e3bSDavid Gibson */ 4826ec132efaSAlexey Kardashevskiy 4827ec132efaSAlexey Kardashevskiy *nv2gpa = 0; 4828ec132efaSAlexey Kardashevskiy *nv2atsd = 0; 4829357d1e3bSDavid Gibson } 4830db800b21SDavid Gibson 48311ea1eefcSBharata B Rao static void spapr_machine_2_7_class_options(MachineClass *mc) 48321ea1eefcSBharata B Rao { 4833ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 483488cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48356c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0xf80000000", }, 48366c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem64_win_size", "0", }, 48376c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-2.8-migration", "on", }, 48386c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-2.8-migration", "on", }, 483988cbe073SMarc-André Lureau }; 48403daa4a9fSThomas Huth 4841db800b21SDavid Gibson spapr_machine_2_8_class_options(mc); 48422e9c10ebSIgor Mammedov mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power7_v2.3"); 4843a140c199SEduardo Habkost mc->default_machine_opts = "modern-hotplug-events=off"; 48445a995064SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_7, hw_compat_2_7_len); 484588cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 4846357d1e3bSDavid Gibson smc->phb_placement = phb_placement_2_7; 48471ea1eefcSBharata B Rao } 48481ea1eefcSBharata B Rao 4849db800b21SDavid Gibson DEFINE_SPAPR_MACHINE(2_7, "2.7", false); 48501ea1eefcSBharata B Rao 48511ea1eefcSBharata B Rao /* 48524b23699cSDavid Gibson * pseries-2.6 48534b23699cSDavid Gibson */ 485488cbe073SMarc-André Lureau 485588cbe073SMarc-André Lureau static void spapr_machine_2_6_class_options(MachineClass *mc) 485688cbe073SMarc-André Lureau { 485788cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48586c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "ddw", "off" }, 4859fa386d98SMarc-André Lureau }; 48601ea1eefcSBharata B Rao 48611ea1eefcSBharata B Rao spapr_machine_2_7_class_options(mc); 4862c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = false; 4863ff8f261fSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_6, hw_compat_2_6_len); 486488cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 48654b23699cSDavid Gibson } 48664b23699cSDavid Gibson 48671ea1eefcSBharata B Rao DEFINE_SPAPR_MACHINE(2_6, "2.6", false); 48684b23699cSDavid Gibson 48694b23699cSDavid Gibson /* 48701c5f29bbSDavid Gibson * pseries-2.5 48711c5f29bbSDavid Gibson */ 487288cbe073SMarc-André Lureau 487388cbe073SMarc-André Lureau static void spapr_machine_2_5_class_options(MachineClass *mc) 487488cbe073SMarc-André Lureau { 4875ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 487688cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48776c36bddfSEduardo Habkost { "spapr-vlan", "use-rx-buffer-pools", "off" }, 4878fa386d98SMarc-André Lureau }; 48794b23699cSDavid Gibson 48804b23699cSDavid Gibson spapr_machine_2_6_class_options(mc); 488157040d45SThomas Huth smc->use_ohci_by_default = true; 4882fe759610SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_5, hw_compat_2_5_len); 488388cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 48841c5f29bbSDavid Gibson } 48851c5f29bbSDavid Gibson 48864b23699cSDavid Gibson DEFINE_SPAPR_MACHINE(2_5, "2.5", false); 48871c5f29bbSDavid Gibson 48881c5f29bbSDavid Gibson /* 48891c5f29bbSDavid Gibson * pseries-2.4 48901c5f29bbSDavid Gibson */ 489180fd50f9SCornelia Huck 48925013c547SDavid Gibson static void spapr_machine_2_4_class_options(MachineClass *mc) 48935013c547SDavid Gibson { 4894ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4895fc9f38c3SDavid Gibson 4896fc9f38c3SDavid Gibson spapr_machine_2_5_class_options(mc); 4897fc9f38c3SDavid Gibson smc->dr_lmb_enabled = false; 48982f99b9c2SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_4, hw_compat_2_4_len); 48991c5f29bbSDavid Gibson } 49001c5f29bbSDavid Gibson 4901fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_4, "2.4", false); 49021c5f29bbSDavid Gibson 49031c5f29bbSDavid Gibson /* 49041c5f29bbSDavid Gibson * pseries-2.3 49051c5f29bbSDavid Gibson */ 490688cbe073SMarc-André Lureau 490788cbe073SMarc-André Lureau static void spapr_machine_2_3_class_options(MachineClass *mc) 490888cbe073SMarc-André Lureau { 490988cbe073SMarc-André Lureau static GlobalProperty compat[] = { 49106c36bddfSEduardo Habkost { "spapr-pci-host-bridge", "dynamic-reconfiguration", "off" }, 4911fa386d98SMarc-André Lureau }; 4912fc9f38c3SDavid Gibson spapr_machine_2_4_class_options(mc); 49138995dd90SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_3, hw_compat_2_3_len); 491488cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 49151c5f29bbSDavid Gibson } 4916fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_3, "2.3", false); 49171c5f29bbSDavid Gibson 49181c5f29bbSDavid Gibson /* 49191c5f29bbSDavid Gibson * pseries-2.2 49201c5f29bbSDavid Gibson */ 492188cbe073SMarc-André Lureau 492288cbe073SMarc-André Lureau static void spapr_machine_2_2_class_options(MachineClass *mc) 492388cbe073SMarc-André Lureau { 492488cbe073SMarc-André Lureau static GlobalProperty compat[] = { 49256c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0x20000000" }, 4926fa386d98SMarc-André Lureau }; 4927b194df47SAlexey Kardashevskiy 4928fc9f38c3SDavid Gibson spapr_machine_2_3_class_options(mc); 49291c30044eSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_2, hw_compat_2_2_len); 493088cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 4931f6d0656bSEduardo Habkost mc->default_machine_opts = "modern-hotplug-events=off,suppress-vmdesc=on"; 49321c5f29bbSDavid Gibson } 4933fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_2, "2.2", false); 49341c5f29bbSDavid Gibson 49351c5f29bbSDavid Gibson /* 49361c5f29bbSDavid Gibson * pseries-2.1 49371c5f29bbSDavid Gibson */ 49381c5f29bbSDavid Gibson 49395013c547SDavid Gibson static void spapr_machine_2_1_class_options(MachineClass *mc) 4940b0e966d0SJason Wang { 4941fc9f38c3SDavid Gibson spapr_machine_2_2_class_options(mc); 4942c4fc5695SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_1, hw_compat_2_1_len); 49436026db45SAlexey Kardashevskiy } 4944fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_1, "2.1", false); 49456026db45SAlexey Kardashevskiy 494629ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void) 494729ee3247SAlexey Kardashevskiy { 494829ee3247SAlexey Kardashevskiy type_register_static(&spapr_machine_info); 494929ee3247SAlexey Kardashevskiy } 495029ee3247SAlexey Kardashevskiy 495129ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types) 4952