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" 492500fb42SAravinda Prasad #include "migration/blocker.h" 504be21d56SDavid Gibson #include "mmu-hash64.h" 51b4db5413SSuraj Jitindar Singh #include "mmu-book3s-v3.h" 527abd43baSSuraj Jitindar Singh #include "cpu-models.h" 532e5b09fdSMarkus Armbruster #include "hw/core/cpu.h" 5453018216SPaolo Bonzini 5553018216SPaolo Bonzini #include "hw/boards.h" 560d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h" 5753018216SPaolo Bonzini #include "hw/loader.h" 5853018216SPaolo Bonzini 597804c353SCédric Le Goater #include "hw/ppc/fdt.h" 600d09e41aSPaolo Bonzini #include "hw/ppc/spapr.h" 610d09e41aSPaolo Bonzini #include "hw/ppc/spapr_vio.h" 62a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 630d09e41aSPaolo Bonzini #include "hw/pci-host/spapr.h" 6453018216SPaolo Bonzini #include "hw/pci/msi.h" 6553018216SPaolo Bonzini 6653018216SPaolo Bonzini #include "hw/pci/pci.h" 6771461b0fSAlexey Kardashevskiy #include "hw/scsi/scsi.h" 6871461b0fSAlexey Kardashevskiy #include "hw/virtio/virtio-scsi.h" 69c4e13492SFelipe Franciosi #include "hw/virtio/vhost-scsi-common.h" 7053018216SPaolo Bonzini 7153018216SPaolo Bonzini #include "exec/address-spaces.h" 722309832aSDavid Gibson #include "exec/ram_addr.h" 7353018216SPaolo Bonzini #include "hw/usb.h" 7453018216SPaolo Bonzini #include "qemu/config-file.h" 75135a129aSAneesh Kumar K.V #include "qemu/error-report.h" 762a6593cbSAlexey Kardashevskiy #include "trace.h" 7734316482SAlexey Kardashevskiy #include "hw/nmi.h" 786449da45SCédric Le Goater #include "hw/intc/intc.h" 7953018216SPaolo Bonzini 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" 83ee3a71e3SShivaprasad G Bhat #include "hw/ppc/spapr_nvdimm.h" 8468a27b20SMichael S. Tsirkin 85f041d6afSGreg Kurz #include "monitor/monitor.h" 86f041d6afSGreg Kurz 8753018216SPaolo Bonzini #include <libfdt.h> 8853018216SPaolo Bonzini 8953018216SPaolo Bonzini /* SLOF memory layout: 9053018216SPaolo Bonzini * 9153018216SPaolo Bonzini * SLOF raw image loaded at 0, copies its romfs right below the flat 9253018216SPaolo Bonzini * device-tree, then position SLOF itself 31M below that 9353018216SPaolo Bonzini * 9453018216SPaolo Bonzini * So we set FW_OVERHEAD to 40MB which should account for all of that 9553018216SPaolo Bonzini * and more 9653018216SPaolo Bonzini * 9753018216SPaolo Bonzini * We load our kernel at 4M, leaving space for SLOF initial image 9853018216SPaolo Bonzini */ 99b7d1f77aSBenjamin Herrenschmidt #define RTAS_MAX_ADDR 0x80000000 /* RTAS must stay below that */ 10053018216SPaolo Bonzini #define FW_MAX_SIZE 0x400000 10153018216SPaolo Bonzini #define FW_FILE_NAME "slof.bin" 10253018216SPaolo Bonzini #define FW_OVERHEAD 0x2800000 10353018216SPaolo Bonzini #define KERNEL_LOAD_ADDR FW_MAX_SIZE 10453018216SPaolo Bonzini 1059943266eSDavid Gibson #define MIN_RMA_SLOF (128 * MiB) 10653018216SPaolo Bonzini 1075c7adcf4SGreg Kurz #define PHANDLE_INTC 0x00001111 10853018216SPaolo Bonzini 1095d0fb150SGreg Kurz /* These two functions implement the VCPU id numbering: one to compute them 1105d0fb150SGreg Kurz * all and one to identify thread 0 of a VCORE. Any change to the first one 1115d0fb150SGreg Kurz * is likely to have an impact on the second one, so let's keep them close. 1125d0fb150SGreg Kurz */ 113ce2918cbSDavid Gibson static int spapr_vcpu_id(SpaprMachineState *spapr, int cpu_index) 1145d0fb150SGreg Kurz { 115fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 116fe6b6346SLike Xu unsigned int smp_threads = ms->smp.threads; 117fe6b6346SLike Xu 1181a5008fcSGreg Kurz assert(spapr->vsmt); 1195d0fb150SGreg Kurz return 1205d0fb150SGreg Kurz (cpu_index / smp_threads) * spapr->vsmt + cpu_index % smp_threads; 1215d0fb150SGreg Kurz } 122ce2918cbSDavid Gibson static bool spapr_is_thread0_in_vcore(SpaprMachineState *spapr, 1235d0fb150SGreg Kurz PowerPCCPU *cpu) 1245d0fb150SGreg Kurz { 1251a5008fcSGreg Kurz assert(spapr->vsmt); 1265d0fb150SGreg Kurz return spapr_get_vcpu_id(cpu) % spapr->vsmt == 0; 1275d0fb150SGreg Kurz } 1285d0fb150SGreg Kurz 12946f7afa3SGreg Kurz static bool pre_2_10_vmstate_dummy_icp_needed(void *opaque) 13046f7afa3SGreg Kurz { 13146f7afa3SGreg Kurz /* Dummy entries correspond to unused ICPState objects in older QEMUs, 13246f7afa3SGreg Kurz * and newer QEMUs don't even have them. In both cases, we don't want 13346f7afa3SGreg Kurz * to send anything on the wire. 13446f7afa3SGreg Kurz */ 13546f7afa3SGreg Kurz return false; 13646f7afa3SGreg Kurz } 13746f7afa3SGreg Kurz 13846f7afa3SGreg Kurz static const VMStateDescription pre_2_10_vmstate_dummy_icp = { 13946f7afa3SGreg Kurz .name = "icp/server", 14046f7afa3SGreg Kurz .version_id = 1, 14146f7afa3SGreg Kurz .minimum_version_id = 1, 14246f7afa3SGreg Kurz .needed = pre_2_10_vmstate_dummy_icp_needed, 14346f7afa3SGreg Kurz .fields = (VMStateField[]) { 14446f7afa3SGreg Kurz VMSTATE_UNUSED(4), /* uint32_t xirr */ 14546f7afa3SGreg Kurz VMSTATE_UNUSED(1), /* uint8_t pending_priority */ 14646f7afa3SGreg Kurz VMSTATE_UNUSED(1), /* uint8_t mfrr */ 14746f7afa3SGreg Kurz VMSTATE_END_OF_LIST() 14846f7afa3SGreg Kurz }, 14946f7afa3SGreg Kurz }; 15046f7afa3SGreg Kurz 15146f7afa3SGreg Kurz static void pre_2_10_vmstate_register_dummy_icp(int i) 15246f7afa3SGreg Kurz { 15346f7afa3SGreg Kurz vmstate_register(NULL, i, &pre_2_10_vmstate_dummy_icp, 15446f7afa3SGreg Kurz (void *)(uintptr_t) i); 15546f7afa3SGreg Kurz } 15646f7afa3SGreg Kurz 15746f7afa3SGreg Kurz static void pre_2_10_vmstate_unregister_dummy_icp(int i) 15846f7afa3SGreg Kurz { 15946f7afa3SGreg Kurz vmstate_unregister(NULL, &pre_2_10_vmstate_dummy_icp, 16046f7afa3SGreg Kurz (void *)(uintptr_t) i); 16146f7afa3SGreg Kurz } 16246f7afa3SGreg Kurz 163ce2918cbSDavid Gibson int spapr_max_server_number(SpaprMachineState *spapr) 16446f7afa3SGreg Kurz { 165fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 166fe6b6346SLike Xu 1671a5008fcSGreg Kurz assert(spapr->vsmt); 168fe6b6346SLike Xu return DIV_ROUND_UP(ms->smp.max_cpus * spapr->vsmt, ms->smp.threads); 16946f7afa3SGreg Kurz } 17046f7afa3SGreg Kurz 171833d4668SAlexey Kardashevskiy static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, 172833d4668SAlexey Kardashevskiy int smt_threads) 173833d4668SAlexey Kardashevskiy { 174833d4668SAlexey Kardashevskiy int i, ret = 0; 175833d4668SAlexey Kardashevskiy uint32_t servers_prop[smt_threads]; 176833d4668SAlexey Kardashevskiy uint32_t gservers_prop[smt_threads * 2]; 17714bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 178833d4668SAlexey Kardashevskiy 179d6e166c0SDavid Gibson if (cpu->compat_pvr) { 180d6e166c0SDavid Gibson ret = fdt_setprop_cell(fdt, offset, "cpu-version", cpu->compat_pvr); 1816d9412eaSAlexey Kardashevskiy if (ret < 0) { 1826d9412eaSAlexey Kardashevskiy return ret; 1836d9412eaSAlexey Kardashevskiy } 1846d9412eaSAlexey Kardashevskiy } 1856d9412eaSAlexey Kardashevskiy 186833d4668SAlexey Kardashevskiy /* Build interrupt servers and gservers properties */ 187833d4668SAlexey Kardashevskiy for (i = 0; i < smt_threads; i++) { 188833d4668SAlexey Kardashevskiy servers_prop[i] = cpu_to_be32(index + i); 189833d4668SAlexey Kardashevskiy /* Hack, direct the group queues back to cpu 0 */ 190833d4668SAlexey Kardashevskiy gservers_prop[i*2] = cpu_to_be32(index + i); 191833d4668SAlexey Kardashevskiy gservers_prop[i*2 + 1] = 0; 192833d4668SAlexey Kardashevskiy } 193833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 194833d4668SAlexey Kardashevskiy servers_prop, sizeof(servers_prop)); 195833d4668SAlexey Kardashevskiy if (ret < 0) { 196833d4668SAlexey Kardashevskiy return ret; 197833d4668SAlexey Kardashevskiy } 198833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-gserver#s", 199833d4668SAlexey Kardashevskiy gservers_prop, sizeof(gservers_prop)); 200833d4668SAlexey Kardashevskiy 201833d4668SAlexey Kardashevskiy return ret; 202833d4668SAlexey Kardashevskiy } 203833d4668SAlexey Kardashevskiy 20499861ecbSIgor Mammedov static int spapr_fixup_cpu_numa_dt(void *fdt, int offset, PowerPCCPU *cpu) 2050da6f3feSBharata B Rao { 20614bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 2070da6f3feSBharata B Rao uint32_t associativity[] = {cpu_to_be32(0x5), 2080da6f3feSBharata B Rao cpu_to_be32(0x0), 2090da6f3feSBharata B Rao cpu_to_be32(0x0), 2100da6f3feSBharata B Rao cpu_to_be32(0x0), 21115f8b142SIgor Mammedov cpu_to_be32(cpu->node_id), 2120da6f3feSBharata B Rao cpu_to_be32(index)}; 2130da6f3feSBharata B Rao 2140da6f3feSBharata B Rao /* Advertise NUMA via ibm,associativity */ 21599861ecbSIgor Mammedov return fdt_setprop(fdt, offset, "ibm,associativity", associativity, 2160da6f3feSBharata B Rao sizeof(associativity)); 2170da6f3feSBharata B Rao } 2180da6f3feSBharata B Rao 21991335a5eSDavid Gibson static void spapr_dt_pa_features(SpaprMachineState *spapr, 220ee76a09fSDavid Gibson PowerPCCPU *cpu, 221daa36379SDavid Gibson void *fdt, int offset) 22286d5771aSSam Bobroff { 22386d5771aSSam Bobroff uint8_t pa_features_206[] = { 6, 0, 22486d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 }; 22586d5771aSSam Bobroff uint8_t pa_features_207[] = { 24, 0, 22686d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, 22786d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 22886d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 22986d5771aSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 }; 2309fb4541fSSam Bobroff uint8_t pa_features_300[] = { 66, 0, 2319fb4541fSSam Bobroff /* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */ 2329fb4541fSSam Bobroff /* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, SSO, 5: LE|CFAR|EB|LSQ */ 23386d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, /* 0 - 5 */ 2349fb4541fSSam Bobroff /* 6: DS207 */ 23586d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */ 2369fb4541fSSam Bobroff /* 16: Vector */ 23786d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */ 2389fb4541fSSam Bobroff /* 18: Vec. Scalar, 20: Vec. XOR, 22: HTM */ 2399bf502feSDavid Gibson 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */ 2409fb4541fSSam Bobroff /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */ 2419fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */ 2429fb4541fSSam Bobroff /* 30: MMR, 32: LE atomic, 34: EBB + ext EBB */ 2439fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */ 2449fb4541fSSam Bobroff /* 36: SPR SO, 38: Copy/Paste, 40: Radix MMU */ 2459fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 36 - 41 */ 2469fb4541fSSam Bobroff /* 42: PM, 44: PC RA, 46: SC vec'd */ 2479fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */ 2489fb4541fSSam Bobroff /* 48: SIMD, 50: QP BFP, 52: String */ 2499fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */ 2509fb4541fSSam Bobroff /* 54: DecFP, 56: DecI, 58: SHA */ 2519fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */ 2529fb4541fSSam Bobroff /* 60: NM atomic, 62: RNG */ 2539fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */ 2549fb4541fSSam Bobroff }; 2557abd43baSSuraj Jitindar Singh uint8_t *pa_features = NULL; 25686d5771aSSam Bobroff size_t pa_size; 25786d5771aSSam Bobroff 2587abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06, 0, cpu->compat_pvr)) { 25986d5771aSSam Bobroff pa_features = pa_features_206; 26086d5771aSSam Bobroff pa_size = sizeof(pa_features_206); 2617abd43baSSuraj Jitindar Singh } 2627abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07, 0, cpu->compat_pvr)) { 26386d5771aSSam Bobroff pa_features = pa_features_207; 26486d5771aSSam Bobroff pa_size = sizeof(pa_features_207); 2657abd43baSSuraj Jitindar Singh } 2667abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0, cpu->compat_pvr)) { 26786d5771aSSam Bobroff pa_features = pa_features_300; 26886d5771aSSam Bobroff pa_size = sizeof(pa_features_300); 2697abd43baSSuraj Jitindar Singh } 2707abd43baSSuraj Jitindar Singh if (!pa_features) { 27186d5771aSSam Bobroff return; 27286d5771aSSam Bobroff } 27386d5771aSSam Bobroff 27426cd35b8SDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_CI_LARGEPAGE)) { 27586d5771aSSam Bobroff /* 27686d5771aSSam Bobroff * Note: we keep CI large pages off by default because a 64K capable 27786d5771aSSam Bobroff * guest provisioned with large pages might otherwise try to map a qemu 27886d5771aSSam Bobroff * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages 27986d5771aSSam Bobroff * even if that qemu runs on a 4k host. 28086d5771aSSam Bobroff * We dd this bit back here if we are confident this is not an issue 28186d5771aSSam Bobroff */ 28286d5771aSSam Bobroff pa_features[3] |= 0x20; 28386d5771aSSam Bobroff } 2844e5fe368SSuraj Jitindar Singh if ((spapr_get_cap(spapr, SPAPR_CAP_HTM) != 0) && pa_size > 24) { 28586d5771aSSam Bobroff pa_features[24] |= 0x80; /* Transactional memory support */ 28686d5771aSSam Bobroff } 287daa36379SDavid Gibson if (spapr->cas_pre_isa3_guest && pa_size > 40) { 288e957f6a9SSam Bobroff /* Workaround for broken kernels that attempt (guest) radix 289e957f6a9SSam Bobroff * mode when they can't handle it, if they see the radix bit set 290e957f6a9SSam Bobroff * in pa-features. So hide it from them. */ 291e957f6a9SSam Bobroff pa_features[40 + 2] &= ~0x80; /* Radix MMU */ 292e957f6a9SSam Bobroff } 29386d5771aSSam Bobroff 29486d5771aSSam Bobroff _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size))); 29586d5771aSSam Bobroff } 29686d5771aSSam Bobroff 297c86c1affSDaniel Henrique Barboza static hwaddr spapr_node0_size(MachineState *machine) 298b082d65aSAlexey Kardashevskiy { 299aa570207STao Xu if (machine->numa_state->num_nodes) { 300b082d65aSAlexey Kardashevskiy int i; 301aa570207STao Xu for (i = 0; i < machine->numa_state->num_nodes; ++i) { 3027e721e7bSTao Xu if (machine->numa_state->nodes[i].node_mem) { 3037e721e7bSTao Xu return MIN(pow2floor(machine->numa_state->nodes[i].node_mem), 304fb164994SDavid Gibson machine->ram_size); 305b082d65aSAlexey Kardashevskiy } 306b082d65aSAlexey Kardashevskiy } 307b082d65aSAlexey Kardashevskiy } 308fb164994SDavid Gibson return machine->ram_size; 309b082d65aSAlexey Kardashevskiy } 310b082d65aSAlexey Kardashevskiy 311a1d59c0fSAlexey Kardashevskiy static void add_str(GString *s, const gchar *s1) 312a1d59c0fSAlexey Kardashevskiy { 313a1d59c0fSAlexey Kardashevskiy g_string_append_len(s, s1, strlen(s1) + 1); 314a1d59c0fSAlexey Kardashevskiy } 31553018216SPaolo Bonzini 31691335a5eSDavid Gibson static int spapr_dt_memory_node(void *fdt, int nodeid, hwaddr start, 31726a8c353SAlexey Kardashevskiy hwaddr size) 31826a8c353SAlexey Kardashevskiy { 31926a8c353SAlexey Kardashevskiy uint32_t associativity[] = { 32026a8c353SAlexey Kardashevskiy cpu_to_be32(0x4), /* length */ 32126a8c353SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(0x0), 322c3b4f589SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(nodeid) 32326a8c353SAlexey Kardashevskiy }; 32426a8c353SAlexey Kardashevskiy char mem_name[32]; 32526a8c353SAlexey Kardashevskiy uint64_t mem_reg_property[2]; 32626a8c353SAlexey Kardashevskiy int off; 32726a8c353SAlexey Kardashevskiy 32826a8c353SAlexey Kardashevskiy mem_reg_property[0] = cpu_to_be64(start); 32926a8c353SAlexey Kardashevskiy mem_reg_property[1] = cpu_to_be64(size); 33026a8c353SAlexey Kardashevskiy 3313a17e38fSAlexey Kardashevskiy sprintf(mem_name, "memory@%" HWADDR_PRIx, start); 33226a8c353SAlexey Kardashevskiy off = fdt_add_subnode(fdt, 0, mem_name); 33326a8c353SAlexey Kardashevskiy _FDT(off); 33426a8c353SAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 33526a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 33626a8c353SAlexey Kardashevskiy sizeof(mem_reg_property)))); 33726a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity, 33826a8c353SAlexey Kardashevskiy sizeof(associativity)))); 33903d196b7SBharata B Rao return off; 34026a8c353SAlexey Kardashevskiy } 34126a8c353SAlexey Kardashevskiy 342f47bd1c8SIgor Mammedov static uint32_t spapr_pc_dimm_node(MemoryDeviceInfoList *list, ram_addr_t addr) 343f47bd1c8SIgor Mammedov { 344f47bd1c8SIgor Mammedov MemoryDeviceInfoList *info; 345f47bd1c8SIgor Mammedov 346f47bd1c8SIgor Mammedov for (info = list; info; info = info->next) { 347f47bd1c8SIgor Mammedov MemoryDeviceInfo *value = info->value; 348f47bd1c8SIgor Mammedov 349f47bd1c8SIgor Mammedov if (value && value->type == MEMORY_DEVICE_INFO_KIND_DIMM) { 350f47bd1c8SIgor Mammedov PCDIMMDeviceInfo *pcdimm_info = value->u.dimm.data; 351f47bd1c8SIgor Mammedov 352ccc2cef8SDavid Gibson if (addr >= pcdimm_info->addr && 353f47bd1c8SIgor Mammedov addr < (pcdimm_info->addr + pcdimm_info->size)) { 354f47bd1c8SIgor Mammedov return pcdimm_info->node; 355f47bd1c8SIgor Mammedov } 356f47bd1c8SIgor Mammedov } 357f47bd1c8SIgor Mammedov } 358f47bd1c8SIgor Mammedov 359f47bd1c8SIgor Mammedov return -1; 360f47bd1c8SIgor Mammedov } 361f47bd1c8SIgor Mammedov 362a324d6f1SBharata B Rao struct sPAPRDrconfCellV2 { 363a324d6f1SBharata B Rao uint32_t seq_lmbs; 364a324d6f1SBharata B Rao uint64_t base_addr; 365a324d6f1SBharata B Rao uint32_t drc_index; 366a324d6f1SBharata B Rao uint32_t aa_index; 367a324d6f1SBharata B Rao uint32_t flags; 368a324d6f1SBharata B Rao } QEMU_PACKED; 369a324d6f1SBharata B Rao 370a324d6f1SBharata B Rao typedef struct DrconfCellQueue { 371a324d6f1SBharata B Rao struct sPAPRDrconfCellV2 cell; 372a324d6f1SBharata B Rao QSIMPLEQ_ENTRY(DrconfCellQueue) entry; 373a324d6f1SBharata B Rao } DrconfCellQueue; 374a324d6f1SBharata B Rao 375a324d6f1SBharata B Rao static DrconfCellQueue * 376a324d6f1SBharata B Rao spapr_get_drconf_cell(uint32_t seq_lmbs, uint64_t base_addr, 377a324d6f1SBharata B Rao uint32_t drc_index, uint32_t aa_index, 378a324d6f1SBharata B Rao uint32_t flags) 37903d196b7SBharata B Rao { 380a324d6f1SBharata B Rao DrconfCellQueue *elem; 381a324d6f1SBharata B Rao 382a324d6f1SBharata B Rao elem = g_malloc0(sizeof(*elem)); 383a324d6f1SBharata B Rao elem->cell.seq_lmbs = cpu_to_be32(seq_lmbs); 384a324d6f1SBharata B Rao elem->cell.base_addr = cpu_to_be64(base_addr); 385a324d6f1SBharata B Rao elem->cell.drc_index = cpu_to_be32(drc_index); 386a324d6f1SBharata B Rao elem->cell.aa_index = cpu_to_be32(aa_index); 387a324d6f1SBharata B Rao elem->cell.flags = cpu_to_be32(flags); 388a324d6f1SBharata B Rao 389a324d6f1SBharata B Rao return elem; 390a324d6f1SBharata B Rao } 391a324d6f1SBharata B Rao 39291335a5eSDavid Gibson static int spapr_dt_dynamic_memory_v2(SpaprMachineState *spapr, void *fdt, 393a324d6f1SBharata B Rao int offset, MemoryDeviceInfoList *dimms) 3942a6593cbSAlexey Kardashevskiy { 3952a6593cbSAlexey Kardashevskiy MachineState *machine = MACHINE(spapr); 396cc941111SFabiano Rosas uint8_t *int_buf, *cur_index; 397a324d6f1SBharata B Rao int ret; 39803d196b7SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 399a324d6f1SBharata B Rao uint64_t addr, cur_addr, size; 400b0c14ec4SDavid Hildenbrand uint32_t nr_boot_lmbs = (machine->device_memory->base / lmb_size); 401b0c14ec4SDavid Hildenbrand uint64_t mem_end = machine->device_memory->base + 402b0c14ec4SDavid Hildenbrand memory_region_size(&machine->device_memory->mr); 403cc941111SFabiano Rosas uint32_t node, buf_len, nr_entries = 0; 404ce2918cbSDavid Gibson SpaprDrc *drc; 405a324d6f1SBharata B Rao DrconfCellQueue *elem, *next; 406a324d6f1SBharata B Rao MemoryDeviceInfoList *info; 407a324d6f1SBharata B Rao QSIMPLEQ_HEAD(, DrconfCellQueue) drconf_queue 408a324d6f1SBharata B Rao = QSIMPLEQ_HEAD_INITIALIZER(drconf_queue); 409a324d6f1SBharata B Rao 410a324d6f1SBharata B Rao /* Entry to cover RAM and the gap area */ 411a324d6f1SBharata B Rao elem = spapr_get_drconf_cell(nr_boot_lmbs, 0, 0, -1, 412a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_RESERVED | 413a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 414a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 415a324d6f1SBharata B Rao nr_entries++; 416a324d6f1SBharata B Rao 417b0c14ec4SDavid Hildenbrand cur_addr = machine->device_memory->base; 418a324d6f1SBharata B Rao for (info = dimms; info; info = info->next) { 419a324d6f1SBharata B Rao PCDIMMDeviceInfo *di = info->value->u.dimm.data; 420a324d6f1SBharata B Rao 421a324d6f1SBharata B Rao addr = di->addr; 422a324d6f1SBharata B Rao size = di->size; 423a324d6f1SBharata B Rao node = di->node; 424a324d6f1SBharata B Rao 425ee3a71e3SShivaprasad G Bhat /* 426ee3a71e3SShivaprasad G Bhat * The NVDIMM area is hotpluggable after the NVDIMM is unplugged. The 427ee3a71e3SShivaprasad G Bhat * area is marked hotpluggable in the next iteration for the bigger 428ee3a71e3SShivaprasad G Bhat * chunk including the NVDIMM occupied area. 429ee3a71e3SShivaprasad G Bhat */ 430ee3a71e3SShivaprasad G Bhat if (info->value->type == MEMORY_DEVICE_INFO_KIND_NVDIMM) 431ee3a71e3SShivaprasad G Bhat continue; 432ee3a71e3SShivaprasad G Bhat 433a324d6f1SBharata B Rao /* Entry for hot-pluggable area */ 434a324d6f1SBharata B Rao if (cur_addr < addr) { 435a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size); 436a324d6f1SBharata B Rao g_assert(drc); 437a324d6f1SBharata B Rao elem = spapr_get_drconf_cell((addr - cur_addr) / lmb_size, 438a324d6f1SBharata B Rao cur_addr, spapr_drc_index(drc), -1, 0); 439a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 440a324d6f1SBharata B Rao nr_entries++; 441a324d6f1SBharata B Rao } 442a324d6f1SBharata B Rao 443a324d6f1SBharata B Rao /* Entry for DIMM */ 444a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr / lmb_size); 445a324d6f1SBharata B Rao g_assert(drc); 446a324d6f1SBharata B Rao elem = spapr_get_drconf_cell(size / lmb_size, addr, 447a324d6f1SBharata B Rao spapr_drc_index(drc), node, 4480911a60cSLeonardo Bras (SPAPR_LMB_FLAGS_ASSIGNED | 4490911a60cSLeonardo Bras SPAPR_LMB_FLAGS_HOTREMOVABLE)); 450a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 451a324d6f1SBharata B Rao nr_entries++; 452a324d6f1SBharata B Rao cur_addr = addr + size; 453a324d6f1SBharata B Rao } 454a324d6f1SBharata B Rao 455a324d6f1SBharata B Rao /* Entry for remaining hotpluggable area */ 456a324d6f1SBharata B Rao if (cur_addr < mem_end) { 457a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size); 458a324d6f1SBharata B Rao g_assert(drc); 459a324d6f1SBharata B Rao elem = spapr_get_drconf_cell((mem_end - cur_addr) / lmb_size, 460a324d6f1SBharata B Rao cur_addr, spapr_drc_index(drc), -1, 0); 461a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 462a324d6f1SBharata B Rao nr_entries++; 463a324d6f1SBharata B Rao } 464a324d6f1SBharata B Rao 465a324d6f1SBharata B Rao buf_len = nr_entries * sizeof(struct sPAPRDrconfCellV2) + sizeof(uint32_t); 466a324d6f1SBharata B Rao int_buf = cur_index = g_malloc0(buf_len); 467a324d6f1SBharata B Rao *(uint32_t *)int_buf = cpu_to_be32(nr_entries); 468a324d6f1SBharata B Rao cur_index += sizeof(nr_entries); 469a324d6f1SBharata B Rao 470a324d6f1SBharata B Rao QSIMPLEQ_FOREACH_SAFE(elem, &drconf_queue, entry, next) { 471a324d6f1SBharata B Rao memcpy(cur_index, &elem->cell, sizeof(elem->cell)); 472a324d6f1SBharata B Rao cur_index += sizeof(elem->cell); 473a324d6f1SBharata B Rao QSIMPLEQ_REMOVE(&drconf_queue, elem, DrconfCellQueue, entry); 474a324d6f1SBharata B Rao g_free(elem); 475a324d6f1SBharata B Rao } 476a324d6f1SBharata B Rao 477a324d6f1SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory-v2", int_buf, buf_len); 478a324d6f1SBharata B Rao g_free(int_buf); 479a324d6f1SBharata B Rao if (ret < 0) { 480a324d6f1SBharata B Rao return -1; 481a324d6f1SBharata B Rao } 482a324d6f1SBharata B Rao return 0; 483a324d6f1SBharata B Rao } 484a324d6f1SBharata B Rao 48591335a5eSDavid Gibson static int spapr_dt_dynamic_memory(SpaprMachineState *spapr, void *fdt, 486a324d6f1SBharata B Rao int offset, MemoryDeviceInfoList *dimms) 487a324d6f1SBharata B Rao { 488b0c14ec4SDavid Hildenbrand MachineState *machine = MACHINE(spapr); 489a324d6f1SBharata B Rao int i, ret; 490a324d6f1SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 4910c9269a5SDavid Hildenbrand uint32_t device_lmb_start = machine->device_memory->base / lmb_size; 492b0c14ec4SDavid Hildenbrand uint32_t nr_lmbs = (machine->device_memory->base + 493b0c14ec4SDavid Hildenbrand memory_region_size(&machine->device_memory->mr)) / 494d0e5a8f2SBharata B Rao lmb_size; 49503d196b7SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 49616c25aefSBharata B Rao 49716c25aefSBharata B Rao /* 498ef001f06SThomas Huth * Allocate enough buffer size to fit in ibm,dynamic-memory 499ef001f06SThomas Huth */ 500a324d6f1SBharata B Rao buf_len = (nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1) * sizeof(uint32_t); 50103d196b7SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 50203d196b7SBharata B Rao int_buf[0] = cpu_to_be32(nr_lmbs); 50303d196b7SBharata B Rao cur_index++; 50403d196b7SBharata B Rao for (i = 0; i < nr_lmbs; i++) { 505d0e5a8f2SBharata B Rao uint64_t addr = i * lmb_size; 50603d196b7SBharata B Rao uint32_t *dynamic_memory = cur_index; 50703d196b7SBharata B Rao 5080c9269a5SDavid Hildenbrand if (i >= device_lmb_start) { 509ce2918cbSDavid Gibson SpaprDrc *drc; 510d0e5a8f2SBharata B Rao 511fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, i); 51203d196b7SBharata B Rao g_assert(drc); 51303d196b7SBharata B Rao 51403d196b7SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 51503d196b7SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 5160b55aa91SDavid Gibson dynamic_memory[2] = cpu_to_be32(spapr_drc_index(drc)); 51703d196b7SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 518f47bd1c8SIgor Mammedov dynamic_memory[4] = cpu_to_be32(spapr_pc_dimm_node(dimms, addr)); 519d0e5a8f2SBharata B Rao if (memory_region_present(get_system_memory(), addr)) { 52003d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); 52103d196b7SBharata B Rao } else { 52203d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(0); 52303d196b7SBharata B Rao } 524d0e5a8f2SBharata B Rao } else { 525d0e5a8f2SBharata B Rao /* 526d0e5a8f2SBharata B Rao * LMB information for RMA, boot time RAM and gap b/n RAM and 5270c9269a5SDavid Hildenbrand * device memory region -- all these are marked as reserved 528d0e5a8f2SBharata B Rao * and as having no valid DRC. 529d0e5a8f2SBharata B Rao */ 530d0e5a8f2SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 531d0e5a8f2SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 532d0e5a8f2SBharata B Rao dynamic_memory[2] = cpu_to_be32(0); 533d0e5a8f2SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 534d0e5a8f2SBharata B Rao dynamic_memory[4] = cpu_to_be32(-1); 535d0e5a8f2SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED | 536d0e5a8f2SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 537d0e5a8f2SBharata B Rao } 53803d196b7SBharata B Rao 53903d196b7SBharata B Rao cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; 54003d196b7SBharata B Rao } 54103d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len); 542a324d6f1SBharata B Rao g_free(int_buf); 54303d196b7SBharata B Rao if (ret < 0) { 544a324d6f1SBharata B Rao return -1; 545a324d6f1SBharata B Rao } 546a324d6f1SBharata B Rao return 0; 547a324d6f1SBharata B Rao } 548a324d6f1SBharata B Rao 549a324d6f1SBharata B Rao /* 550a324d6f1SBharata B Rao * Adds ibm,dynamic-reconfiguration-memory node. 551a324d6f1SBharata B Rao * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation 552a324d6f1SBharata B Rao * of this device tree node. 553a324d6f1SBharata B Rao */ 55491335a5eSDavid Gibson static int spapr_dt_dynamic_reconfiguration_memory(SpaprMachineState *spapr, 55591335a5eSDavid Gibson void *fdt) 556a324d6f1SBharata B Rao { 557a324d6f1SBharata B Rao MachineState *machine = MACHINE(spapr); 558aa570207STao Xu int nb_numa_nodes = machine->numa_state->num_nodes; 559a324d6f1SBharata B Rao int ret, i, offset; 560a324d6f1SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 561a324d6f1SBharata B Rao uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; 562a324d6f1SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 563a324d6f1SBharata B Rao int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; 564a324d6f1SBharata B Rao MemoryDeviceInfoList *dimms = NULL; 565a324d6f1SBharata B Rao 566a324d6f1SBharata B Rao /* 5670c9269a5SDavid Hildenbrand * Don't create the node if there is no device memory 568a324d6f1SBharata B Rao */ 569a324d6f1SBharata B Rao if (machine->ram_size == machine->maxram_size) { 570a324d6f1SBharata B Rao return 0; 571a324d6f1SBharata B Rao } 572a324d6f1SBharata B Rao 573a324d6f1SBharata B Rao offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory"); 574a324d6f1SBharata B Rao 575a324d6f1SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size, 576a324d6f1SBharata B Rao sizeof(prop_lmb_size)); 577a324d6f1SBharata B Rao if (ret < 0) { 578a324d6f1SBharata B Rao return ret; 579a324d6f1SBharata B Rao } 580a324d6f1SBharata B Rao 581a324d6f1SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff); 582a324d6f1SBharata B Rao if (ret < 0) { 583a324d6f1SBharata B Rao return ret; 584a324d6f1SBharata B Rao } 585a324d6f1SBharata B Rao 586a324d6f1SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0); 587a324d6f1SBharata B Rao if (ret < 0) { 588a324d6f1SBharata B Rao return ret; 589a324d6f1SBharata B Rao } 590a324d6f1SBharata B Rao 591a324d6f1SBharata B Rao /* ibm,dynamic-memory or ibm,dynamic-memory-v2 */ 5922cc0e2e8SDavid Hildenbrand dimms = qmp_memory_device_list(); 593a324d6f1SBharata B Rao if (spapr_ovec_test(spapr->ov5_cas, OV5_DRMEM_V2)) { 59491335a5eSDavid Gibson ret = spapr_dt_dynamic_memory_v2(spapr, fdt, offset, dimms); 595a324d6f1SBharata B Rao } else { 59691335a5eSDavid Gibson ret = spapr_dt_dynamic_memory(spapr, fdt, offset, dimms); 597a324d6f1SBharata B Rao } 598a324d6f1SBharata B Rao qapi_free_MemoryDeviceInfoList(dimms); 599a324d6f1SBharata B Rao 600a324d6f1SBharata B Rao if (ret < 0) { 601a324d6f1SBharata B Rao return ret; 60203d196b7SBharata B Rao } 60303d196b7SBharata B Rao 60403d196b7SBharata B Rao /* ibm,associativity-lookup-arrays */ 605a324d6f1SBharata B Rao buf_len = (nr_nodes * 4 + 2) * sizeof(uint32_t); 606a324d6f1SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 6076663864eSBharata B Rao int_buf[0] = cpu_to_be32(nr_nodes); 60803d196b7SBharata B Rao int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */ 60903d196b7SBharata B Rao cur_index += 2; 6106663864eSBharata B Rao for (i = 0; i < nr_nodes; i++) { 61103d196b7SBharata B Rao uint32_t associativity[] = { 61203d196b7SBharata B Rao cpu_to_be32(0x0), 61303d196b7SBharata B Rao cpu_to_be32(0x0), 61403d196b7SBharata B Rao cpu_to_be32(0x0), 61503d196b7SBharata B Rao cpu_to_be32(i) 61603d196b7SBharata B Rao }; 61703d196b7SBharata B Rao memcpy(cur_index, associativity, sizeof(associativity)); 61803d196b7SBharata B Rao cur_index += 4; 61903d196b7SBharata B Rao } 62003d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf, 62103d196b7SBharata B Rao (cur_index - int_buf) * sizeof(uint32_t)); 62203d196b7SBharata B Rao g_free(int_buf); 623a324d6f1SBharata B Rao 62403d196b7SBharata B Rao return ret; 62503d196b7SBharata B Rao } 62603d196b7SBharata B Rao 62791335a5eSDavid Gibson static int spapr_dt_memory(SpaprMachineState *spapr, void *fdt) 6286787d27bSMichael Roth { 629fa523f0dSDavid Gibson MachineState *machine = MACHINE(spapr); 630ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 63153018216SPaolo Bonzini hwaddr mem_start, node_size; 63253018216SPaolo Bonzini int i, nb_nodes = machine->numa_state->num_nodes; 63353018216SPaolo Bonzini NodeInfo *nodes = machine->numa_state->nodes; 63453018216SPaolo Bonzini 63553018216SPaolo Bonzini for (i = 0, mem_start = 0; i < nb_nodes; ++i) { 63653018216SPaolo Bonzini if (!nodes[i].node_mem) { 63753018216SPaolo Bonzini continue; 63853018216SPaolo Bonzini } 63953018216SPaolo Bonzini if (mem_start >= machine->ram_size) { 64053018216SPaolo Bonzini node_size = 0; 64153018216SPaolo Bonzini } else { 64253018216SPaolo Bonzini node_size = nodes[i].node_mem; 64353018216SPaolo Bonzini if (node_size > machine->ram_size - mem_start) { 64453018216SPaolo Bonzini node_size = machine->ram_size - mem_start; 64553018216SPaolo Bonzini } 64653018216SPaolo Bonzini } 64753018216SPaolo Bonzini if (!mem_start) { 64853018216SPaolo Bonzini /* spapr_machine_init() checks for rma_size <= node0_size 64953018216SPaolo Bonzini * already */ 65091335a5eSDavid Gibson spapr_dt_memory_node(fdt, i, 0, spapr->rma_size); 65153018216SPaolo Bonzini mem_start += spapr->rma_size; 65253018216SPaolo Bonzini node_size -= spapr->rma_size; 65353018216SPaolo Bonzini } 65453018216SPaolo Bonzini for ( ; node_size; ) { 65553018216SPaolo Bonzini hwaddr sizetmp = pow2floor(node_size); 65653018216SPaolo Bonzini 65753018216SPaolo Bonzini /* mem_start != 0 here */ 65853018216SPaolo Bonzini if (ctzl(mem_start) < ctzl(sizetmp)) { 65953018216SPaolo Bonzini sizetmp = 1ULL << ctzl(mem_start); 66053018216SPaolo Bonzini } 66153018216SPaolo Bonzini 66291335a5eSDavid Gibson spapr_dt_memory_node(fdt, i, mem_start, sizetmp); 66353018216SPaolo Bonzini node_size -= sizetmp; 66453018216SPaolo Bonzini mem_start += sizetmp; 66553018216SPaolo Bonzini } 66653018216SPaolo Bonzini } 66753018216SPaolo Bonzini 6686787d27bSMichael Roth /* Generate ibm,dynamic-reconfiguration-memory node if required */ 669fa523f0dSDavid Gibson if (spapr_ovec_test(spapr->ov5_cas, OV5_DRCONF_MEMORY)) { 670fa523f0dSDavid Gibson int ret; 671fa523f0dSDavid Gibson 6726787d27bSMichael Roth g_assert(smc->dr_lmb_enabled); 67391335a5eSDavid Gibson ret = spapr_dt_dynamic_reconfiguration_memory(spapr, fdt); 674417ece33SMichael Roth if (ret) { 6759b6c1da5SDaniel Henrique Barboza return ret; 676417ece33SMichael Roth } 6776787d27bSMichael Roth } 6786787d27bSMichael Roth 67953018216SPaolo Bonzini return 0; 68053018216SPaolo Bonzini } 68153018216SPaolo Bonzini 68291335a5eSDavid Gibson static void spapr_dt_cpu(CPUState *cs, void *fdt, int offset, 68353018216SPaolo Bonzini SpaprMachineState *spapr) 68453018216SPaolo Bonzini { 68553018216SPaolo Bonzini MachineState *ms = MACHINE(spapr); 68653018216SPaolo Bonzini PowerPCCPU *cpu = POWERPC_CPU(cs); 68753018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 68853018216SPaolo Bonzini PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 68953018216SPaolo Bonzini int index = spapr_get_vcpu_id(cpu); 69053018216SPaolo Bonzini uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 69153018216SPaolo Bonzini 0xffffffff, 0xffffffff}; 69253018216SPaolo Bonzini uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() 69353018216SPaolo Bonzini : SPAPR_TIMEBASE_FREQ; 69453018216SPaolo Bonzini uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; 69553018216SPaolo Bonzini uint32_t page_sizes_prop[64]; 69653018216SPaolo Bonzini size_t page_sizes_prop_size; 69753018216SPaolo Bonzini unsigned int smp_threads = ms->smp.threads; 69853018216SPaolo Bonzini uint32_t vcpus_per_socket = smp_threads * ms->smp.cores; 69953018216SPaolo Bonzini uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 70053018216SPaolo Bonzini int compat_smt = MIN(smp_threads, ppc_compat_max_vthreads(cpu)); 70153018216SPaolo Bonzini SpaprDrc *drc; 70253018216SPaolo Bonzini int drc_index; 70353018216SPaolo Bonzini uint32_t radix_AP_encodings[PPC_PAGE_SIZES_MAX_SZ]; 70453018216SPaolo Bonzini int i; 70553018216SPaolo Bonzini 70653018216SPaolo Bonzini drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index); 70753018216SPaolo Bonzini if (drc) { 70853018216SPaolo Bonzini drc_index = spapr_drc_index(drc); 70953018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index))); 7102a6593cbSAlexey Kardashevskiy } 7112a6593cbSAlexey Kardashevskiy 7122a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); 7132a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 7142a6593cbSAlexey Kardashevskiy 7152a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 7162a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 7172a6593cbSAlexey Kardashevskiy env->dcache_line_size))); 7182a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 7192a6593cbSAlexey Kardashevskiy env->dcache_line_size))); 7202a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 7212a6593cbSAlexey Kardashevskiy env->icache_line_size))); 7222a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 7232a6593cbSAlexey Kardashevskiy env->icache_line_size))); 7242a6593cbSAlexey Kardashevskiy 7252a6593cbSAlexey Kardashevskiy if (pcc->l1_dcache_size) { 7262a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 7272a6593cbSAlexey Kardashevskiy pcc->l1_dcache_size))); 7282a6593cbSAlexey Kardashevskiy } else { 7292a6593cbSAlexey Kardashevskiy warn_report("Unknown L1 dcache size for cpu"); 7302a6593cbSAlexey Kardashevskiy } 7312a6593cbSAlexey Kardashevskiy if (pcc->l1_icache_size) { 7322a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 7332a6593cbSAlexey Kardashevskiy pcc->l1_icache_size))); 7342a6593cbSAlexey Kardashevskiy } else { 7352a6593cbSAlexey Kardashevskiy warn_report("Unknown L1 icache size for cpu"); 7362a6593cbSAlexey Kardashevskiy } 7372a6593cbSAlexey Kardashevskiy 7382a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 7392a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 7402a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "slb-size", cpu->hash64_opts->slb_size))); 7412a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", cpu->hash64_opts->slb_size))); 7422a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 7432a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 7442a6593cbSAlexey Kardashevskiy 74553018216SPaolo Bonzini if (env->spr_cb[SPR_PURR].oea_read) { 74653018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,purr", 1))); 74753018216SPaolo Bonzini } 74853018216SPaolo Bonzini if (env->spr_cb[SPR_SPURR].oea_read) { 74953018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,spurr", 1))); 75053018216SPaolo Bonzini } 7515fe269b1SPaul Mackerras 75253018216SPaolo Bonzini if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 75353018216SPaolo Bonzini _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 75453018216SPaolo Bonzini segs, sizeof(segs)))); 75553018216SPaolo Bonzini } 7565fe269b1SPaul Mackerras 7575fe269b1SPaul Mackerras /* Advertise VSX (vector extensions) if available 7585fe269b1SPaul Mackerras * 1 == VMX / Altivec available 7595fe269b1SPaul Mackerras * 2 == VSX available 7605fe269b1SPaul Mackerras * 76153018216SPaolo Bonzini * Only CPUs for which we create core types in spapr_cpu_core.c 76253018216SPaolo Bonzini * are possible, and all of those have VMX */ 76353018216SPaolo Bonzini if (spapr_get_cap(spapr, SPAPR_CAP_VSX) != 0) { 76453018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2))); 76553018216SPaolo Bonzini } else { 76653018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1))); 76728e02042SDavid Gibson } 76853018216SPaolo Bonzini 769fb164994SDavid Gibson /* Advertise DFP (Decimal Floating Point) if available 7707db8a127SAlexey Kardashevskiy * 0 / no property == no DFP 7717db8a127SAlexey Kardashevskiy * 1 == DFP available */ 7727db8a127SAlexey Kardashevskiy if (spapr_get_cap(spapr, SPAPR_CAP_DFP) != 0) { 7737db8a127SAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 77453018216SPaolo Bonzini } 7757db8a127SAlexey Kardashevskiy 7767db8a127SAlexey Kardashevskiy page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 7777db8a127SAlexey Kardashevskiy sizeof(page_sizes_prop)); 778fb164994SDavid Gibson if (page_sizes_prop_size) { 7797db8a127SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 78053018216SPaolo Bonzini page_sizes_prop, page_sizes_prop_size))); 78153018216SPaolo Bonzini } 7827db8a127SAlexey Kardashevskiy 78391335a5eSDavid Gibson spapr_dt_pa_features(spapr, cpu, fdt, offset); 78453018216SPaolo Bonzini 7857db8a127SAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", 7867db8a127SAlexey Kardashevskiy cs->cpu_index / vcpus_per_socket))); 7877db8a127SAlexey Kardashevskiy 78853018216SPaolo Bonzini _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", 789fb164994SDavid Gibson pft_size_prop, sizeof(pft_size_prop)))); 7905fe269b1SPaul Mackerras 7915fe269b1SPaul Mackerras if (ms->numa_state->num_nodes > 1) { 7927db8a127SAlexey Kardashevskiy _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cpu)); 793fb164994SDavid Gibson } 794fb164994SDavid Gibson 7955fe269b1SPaul Mackerras _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt)); 7965fe269b1SPaul Mackerras 7977db8a127SAlexey Kardashevskiy if (pcc->radix_page_info) { 7987db8a127SAlexey Kardashevskiy for (i = 0; i < pcc->radix_page_info->count; i++) { 7997db8a127SAlexey Kardashevskiy radix_AP_encodings[i] = 8007db8a127SAlexey Kardashevskiy cpu_to_be32(pcc->radix_page_info->entries[i]); 8017db8a127SAlexey Kardashevskiy } 8027db8a127SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, offset, "ibm,processor-radix-AP-encodings", 8036010818cSAlexey Kardashevskiy radix_AP_encodings, 8046010818cSAlexey Kardashevskiy pcc->radix_page_info->count * 8056010818cSAlexey Kardashevskiy sizeof(radix_AP_encodings[0])))); 8066010818cSAlexey Kardashevskiy } 8076010818cSAlexey Kardashevskiy 8086010818cSAlexey Kardashevskiy /* 8096010818cSAlexey Kardashevskiy * We set this property to let the guest know that it can use the large 8106010818cSAlexey Kardashevskiy * decrementer and its width in bits. 8116010818cSAlexey Kardashevskiy */ 8126010818cSAlexey Kardashevskiy if (spapr_get_cap(spapr, SPAPR_CAP_LARGE_DECREMENTER) != SPAPR_CAP_OFF) 8136010818cSAlexey Kardashevskiy _FDT((fdt_setprop_u32(fdt, offset, "ibm,dec-bits", 8146010818cSAlexey Kardashevskiy pcc->lrg_decr_bits))); 81553018216SPaolo Bonzini } 81653018216SPaolo Bonzini 81791335a5eSDavid Gibson static void spapr_dt_cpus(void *fdt, SpaprMachineState *spapr) 81853018216SPaolo Bonzini { 81953018216SPaolo Bonzini CPUState **rev; 82053018216SPaolo Bonzini CPUState *cs; 82153018216SPaolo Bonzini int n_cpus; 82253018216SPaolo Bonzini int cpus_offset; 82353018216SPaolo Bonzini char *nodename; 82453018216SPaolo Bonzini int i; 82553018216SPaolo Bonzini 82653018216SPaolo Bonzini cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 82753018216SPaolo Bonzini _FDT(cpus_offset); 82853018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 82953018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 83053018216SPaolo Bonzini 83153018216SPaolo Bonzini /* 83253018216SPaolo Bonzini * We walk the CPUs in reverse order to ensure that CPU DT nodes 83353018216SPaolo Bonzini * created by fdt_add_subnode() end up in the right order in FDT 83453018216SPaolo Bonzini * for the guest kernel the enumerate the CPUs correctly. 83553018216SPaolo Bonzini * 83653018216SPaolo Bonzini * The CPU list cannot be traversed in reverse order, so we need 83753018216SPaolo Bonzini * to do extra work. 83853018216SPaolo Bonzini */ 83953018216SPaolo Bonzini n_cpus = 0; 84053018216SPaolo Bonzini rev = NULL; 8410da6f3feSBharata B Rao CPU_FOREACH(cs) { 8420da6f3feSBharata B Rao rev = g_renew(CPUState *, rev, n_cpus + 1); 8430da6f3feSBharata B Rao rev[n_cpus++] = cs; 8440da6f3feSBharata B Rao } 8450da6f3feSBharata B Rao 8460da6f3feSBharata B Rao for (i = n_cpus - 1; i >= 0; i--) { 8470da6f3feSBharata B Rao CPUState *cs = rev[i]; 8480da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 8490da6f3feSBharata B Rao int index = spapr_get_vcpu_id(cpu); 8500da6f3feSBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 8510da6f3feSBharata B Rao int offset; 8520da6f3feSBharata B Rao 8530da6f3feSBharata B Rao if (!spapr_is_thread0_in_vcore(spapr, cpu)) { 85422419c2aSDavid Gibson continue; 8550da6f3feSBharata B Rao } 8560da6f3feSBharata B Rao 8570da6f3feSBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, index); 8580da6f3feSBharata B Rao offset = fdt_add_subnode(fdt, cpus_offset, nodename); 8590da6f3feSBharata B Rao g_free(nodename); 8600da6f3feSBharata B Rao _FDT(offset); 86191335a5eSDavid Gibson spapr_dt_cpu(cs, fdt, offset, spapr); 8620da6f3feSBharata B Rao } 8630da6f3feSBharata B Rao 8640da6f3feSBharata B Rao g_free(rev); 8650da6f3feSBharata B Rao } 8660da6f3feSBharata B Rao 86791335a5eSDavid Gibson static int spapr_dt_rng(void *fdt) 8680da6f3feSBharata B Rao { 8690da6f3feSBharata B Rao int node; 8700da6f3feSBharata B Rao int ret; 8710da6f3feSBharata B Rao 8720da6f3feSBharata B Rao node = qemu_fdt_add_subnode(fdt, "/ibm,platform-facilities"); 8730da6f3feSBharata B Rao if (node <= 0) { 8740da6f3feSBharata B Rao return -1; 8750da6f3feSBharata B Rao } 8760da6f3feSBharata B Rao ret = fdt_setprop_string(fdt, node, "device_type", 8770da6f3feSBharata B Rao "ibm,platform-facilities"); 8780da6f3feSBharata B Rao ret |= fdt_setprop_cell(fdt, node, "#address-cells", 0x1); 8790da6f3feSBharata B Rao ret |= fdt_setprop_cell(fdt, node, "#size-cells", 0x0); 8800da6f3feSBharata B Rao 8810da6f3feSBharata B Rao node = fdt_add_subnode(fdt, node, "ibm,random-v1"); 8820da6f3feSBharata B Rao if (node <= 0) { 8830da6f3feSBharata B Rao return -1; 8840da6f3feSBharata B Rao } 8850da6f3feSBharata B Rao ret |= fdt_setprop_string(fdt, node, "compatible", "ibm,random"); 8860da6f3feSBharata B Rao 8870da6f3feSBharata B Rao return ret ? -1 : 0; 8880da6f3feSBharata B Rao } 8890da6f3feSBharata B Rao 890ce2918cbSDavid Gibson static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt) 8913f5dabceSDavid Gibson { 892fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 8933f5dabceSDavid Gibson int rtas; 8943f5dabceSDavid Gibson GString *hypertas = g_string_sized_new(256); 8953f5dabceSDavid Gibson GString *qemu_hypertas = g_string_sized_new(256); 8963f5dabceSDavid Gibson uint32_t refpoints[] = { cpu_to_be32(0x4), cpu_to_be32(0x4) }; 8970c9269a5SDavid Hildenbrand uint64_t max_device_addr = MACHINE(spapr)->device_memory->base + 898b0c14ec4SDavid Hildenbrand memory_region_size(&MACHINE(spapr)->device_memory->mr); 8993f5dabceSDavid Gibson uint32_t lrdr_capacity[] = { 9000c9269a5SDavid Hildenbrand cpu_to_be32(max_device_addr >> 32), 9010c9269a5SDavid Hildenbrand cpu_to_be32(max_device_addr & 0xffffffff), 9023f5dabceSDavid Gibson 0, cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE), 903fe6b6346SLike Xu cpu_to_be32(ms->smp.max_cpus / ms->smp.threads), 9043f5dabceSDavid Gibson }; 905ec132efaSAlexey Kardashevskiy uint32_t maxdomain = cpu_to_be32(spapr->gpu_numa_id > 1 ? 1 : 0); 906da9f80fbSSerhii Popovych uint32_t maxdomains[] = { 907da9f80fbSSerhii Popovych cpu_to_be32(4), 908ec132efaSAlexey Kardashevskiy maxdomain, 909ec132efaSAlexey Kardashevskiy maxdomain, 910ec132efaSAlexey Kardashevskiy maxdomain, 911ec132efaSAlexey Kardashevskiy cpu_to_be32(spapr->gpu_numa_id), 912da9f80fbSSerhii Popovych }; 9133f5dabceSDavid Gibson 9143f5dabceSDavid Gibson _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas")); 9153f5dabceSDavid Gibson 9163f5dabceSDavid Gibson /* hypertas */ 9173f5dabceSDavid Gibson add_str(hypertas, "hcall-pft"); 9183f5dabceSDavid Gibson add_str(hypertas, "hcall-term"); 9193f5dabceSDavid Gibson add_str(hypertas, "hcall-dabr"); 9203f5dabceSDavid Gibson add_str(hypertas, "hcall-interrupt"); 9213f5dabceSDavid Gibson add_str(hypertas, "hcall-tce"); 9223f5dabceSDavid Gibson add_str(hypertas, "hcall-vio"); 9233f5dabceSDavid Gibson add_str(hypertas, "hcall-splpar"); 92410741314SNicholas Piggin add_str(hypertas, "hcall-join"); 9253f5dabceSDavid Gibson add_str(hypertas, "hcall-bulk"); 9263f5dabceSDavid Gibson add_str(hypertas, "hcall-set-mode"); 9273f5dabceSDavid Gibson add_str(hypertas, "hcall-sprg0"); 9283f5dabceSDavid Gibson add_str(hypertas, "hcall-copy"); 9293f5dabceSDavid Gibson add_str(hypertas, "hcall-debug"); 930c24ba3d0SLaurent Vivier add_str(hypertas, "hcall-vphn"); 9313f5dabceSDavid Gibson add_str(qemu_hypertas, "hcall-memop1"); 9323f5dabceSDavid Gibson 9333f5dabceSDavid Gibson if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { 9343f5dabceSDavid Gibson add_str(hypertas, "hcall-multi-tce"); 9353f5dabceSDavid Gibson } 93630f4b05bSDavid Gibson 93730f4b05bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { 93830f4b05bSDavid Gibson add_str(hypertas, "hcall-hpt-resize"); 93930f4b05bSDavid Gibson } 94030f4b05bSDavid Gibson 9413f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions", 9423f5dabceSDavid Gibson hypertas->str, hypertas->len)); 9433f5dabceSDavid Gibson g_string_free(hypertas, TRUE); 9443f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "qemu,hypertas-functions", 9453f5dabceSDavid Gibson qemu_hypertas->str, qemu_hypertas->len)); 9463f5dabceSDavid Gibson g_string_free(qemu_hypertas, TRUE); 9473f5dabceSDavid Gibson 9483f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,associativity-reference-points", 9493f5dabceSDavid Gibson refpoints, sizeof(refpoints))); 9503f5dabceSDavid Gibson 951da9f80fbSSerhii Popovych _FDT(fdt_setprop(fdt, rtas, "ibm,max-associativity-domains", 952da9f80fbSSerhii Popovych maxdomains, sizeof(maxdomains))); 953da9f80fbSSerhii Popovych 9540e236d34SNicholas Piggin /* 9550e236d34SNicholas Piggin * FWNMI reserves RTAS_ERROR_LOG_MAX for the machine check error log, 9560e236d34SNicholas Piggin * and 16 bytes per CPU for system reset error log plus an extra 8 bytes. 9570e236d34SNicholas Piggin * 9580e236d34SNicholas Piggin * The system reset requirements are driven by existing Linux and PowerVM 9590e236d34SNicholas Piggin * implementation which (contrary to PAPR) saves r3 in the error log 9600e236d34SNicholas Piggin * structure like machine check, so Linux expects to find the saved r3 9610e236d34SNicholas Piggin * value at the address in r3 upon FWNMI-enabled sreset interrupt (and 9620e236d34SNicholas Piggin * does not look at the error value). 9630e236d34SNicholas Piggin * 9640e236d34SNicholas Piggin * System reset interrupts are not subject to interlock like machine 9650e236d34SNicholas Piggin * check, so this memory area could be corrupted if the sreset is 9660e236d34SNicholas Piggin * interrupted by a machine check (or vice versa) if it was shared. To 9670e236d34SNicholas Piggin * prevent this, system reset uses per-CPU areas for the sreset save 9680e236d34SNicholas Piggin * area. A system reset that interrupts a system reset handler could 9690e236d34SNicholas Piggin * still overwrite this area, but Linux doesn't try to recover in that 9700e236d34SNicholas Piggin * case anyway. 9710e236d34SNicholas Piggin * 9720e236d34SNicholas Piggin * The extra 8 bytes is required because Linux's FWNMI error log check 9730e236d34SNicholas Piggin * is off-by-one. 9740e236d34SNicholas Piggin */ 9750e236d34SNicholas Piggin _FDT(fdt_setprop_cell(fdt, rtas, "rtas-size", RTAS_ERROR_LOG_MAX + 9760e236d34SNicholas Piggin ms->smp.max_cpus * sizeof(uint64_t)*2 + sizeof(uint64_t))); 9773f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-error-log-max", 9783f5dabceSDavid Gibson RTAS_ERROR_LOG_MAX)); 9793f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-event-scan-rate", 9803f5dabceSDavid Gibson RTAS_EVENT_SCAN_RATE)); 9813f5dabceSDavid Gibson 9824f441474SDavid Gibson g_assert(msi_nonbroken); 9833f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,change-msix-capable", NULL, 0)); 9843f5dabceSDavid Gibson 9853f5dabceSDavid Gibson /* 9863f5dabceSDavid Gibson * According to PAPR, rtas ibm,os-term does not guarantee a return 9873f5dabceSDavid Gibson * back to the guest cpu. 9883f5dabceSDavid Gibson * 9893f5dabceSDavid Gibson * While an additional ibm,extended-os-term property indicates 9903f5dabceSDavid Gibson * that rtas call return will always occur. Set this property. 9913f5dabceSDavid Gibson */ 9923f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,extended-os-term", NULL, 0)); 9933f5dabceSDavid Gibson 9943f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,lrdr-capacity", 9953f5dabceSDavid Gibson lrdr_capacity, sizeof(lrdr_capacity))); 9963f5dabceSDavid Gibson 9973f5dabceSDavid Gibson spapr_dt_rtas_tokens(fdt, rtas); 9983f5dabceSDavid Gibson } 9993f5dabceSDavid Gibson 1000db592b5bSCédric Le Goater /* 1001db592b5bSCédric Le Goater * Prepare ibm,arch-vec-5-platform-support, which indicates the MMU 1002db592b5bSCédric Le Goater * and the XIVE features that the guest may request and thus the valid 1003db592b5bSCédric Le Goater * values for bytes 23..26 of option vector 5: 1004db592b5bSCédric Le Goater */ 1005ce2918cbSDavid Gibson static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt, 1006db592b5bSCédric Le Goater int chosen) 10079fb4541fSSam Bobroff { 1008545d6e2bSSuraj Jitindar Singh PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); 1009545d6e2bSSuraj Jitindar Singh 1010f2b14e3aSCédric Le Goater char val[2 * 4] = { 1011ca62823bSDavid Gibson 23, 0x00, /* XICS / XIVE mode */ 10129fb4541fSSam Bobroff 24, 0x00, /* Hash/Radix, filled in below. */ 10139fb4541fSSam Bobroff 25, 0x00, /* Hash options: Segment Tables == no, GTSE == no. */ 10149fb4541fSSam Bobroff 26, 0x40, /* Radix options: GTSE == yes. */ 10159fb4541fSSam Bobroff }; 10169fb4541fSSam Bobroff 1017ca62823bSDavid Gibson if (spapr->irq->xics && spapr->irq->xive) { 1018ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_BOTH; 1019ca62823bSDavid Gibson } else if (spapr->irq->xive) { 1020ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_EXPLOIT; 1021ca62823bSDavid Gibson } else { 1022ca62823bSDavid Gibson assert(spapr->irq->xics); 1023ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_LEGACY; 1024ca62823bSDavid Gibson } 1025ca62823bSDavid Gibson 10267abd43baSSuraj Jitindar Singh if (!ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0, 10277abd43baSSuraj Jitindar Singh first_ppc_cpu->compat_pvr)) { 1028db592b5bSCédric Le Goater /* 1029db592b5bSCédric Le Goater * If we're in a pre POWER9 compat mode then the guest should 1030db592b5bSCédric Le Goater * do hash and use the legacy interrupt mode 1031db592b5bSCédric Le Goater */ 1032ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_LEGACY; /* XICS */ 10337abd43baSSuraj Jitindar Singh val[3] = 0x00; /* Hash */ 10347abd43baSSuraj Jitindar Singh } else if (kvm_enabled()) { 10359fb4541fSSam Bobroff if (kvmppc_has_cap_mmu_radix() && kvmppc_has_cap_mmu_hash_v3()) { 1036f2b14e3aSCédric Le Goater val[3] = 0x80; /* OV5_MMU_BOTH */ 10379fb4541fSSam Bobroff } else if (kvmppc_has_cap_mmu_radix()) { 1038f2b14e3aSCédric Le Goater val[3] = 0x40; /* OV5_MMU_RADIX_300 */ 10399fb4541fSSam Bobroff } else { 1040f2b14e3aSCédric Le Goater val[3] = 0x00; /* Hash */ 10419fb4541fSSam Bobroff } 10429fb4541fSSam Bobroff } else { 10437abd43baSSuraj Jitindar Singh /* V3 MMU supports both hash and radix in tcg (with dynamic switching) */ 1044f2b14e3aSCédric Le Goater val[3] = 0xC0; 1045545d6e2bSSuraj Jitindar Singh } 10469fb4541fSSam Bobroff _FDT(fdt_setprop(fdt, chosen, "ibm,arch-vec-5-platform-support", 10479fb4541fSSam Bobroff val, sizeof(val))); 10489fb4541fSSam Bobroff } 10499fb4541fSSam Bobroff 10501e0e1108SDavid Gibson static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt, bool reset) 10517c866c6aSDavid Gibson { 10527c866c6aSDavid Gibson MachineState *machine = MACHINE(spapr); 10536c3829a2SAlexey Kardashevskiy SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 10547c866c6aSDavid Gibson int chosen; 10551e0e1108SDavid Gibson 10561e0e1108SDavid Gibson _FDT(chosen = fdt_add_subnode(fdt, 0, "chosen")); 10571e0e1108SDavid Gibson 10581e0e1108SDavid Gibson if (reset) { 10597c866c6aSDavid Gibson const char *boot_device = machine->boot_order; 10607c866c6aSDavid Gibson char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus); 10617c866c6aSDavid Gibson size_t cb = 0; 1062907aac2fSMark Cave-Ayland char *bootlist = get_boot_devices_list(&cb); 10637c866c6aSDavid Gibson 10645ced7895SAlexey Kardashevskiy if (machine->kernel_cmdline && machine->kernel_cmdline[0]) { 10655ced7895SAlexey Kardashevskiy _FDT(fdt_setprop_string(fdt, chosen, "bootargs", 10665ced7895SAlexey Kardashevskiy machine->kernel_cmdline)); 10675ced7895SAlexey Kardashevskiy } 10681e0e1108SDavid Gibson 10695ced7895SAlexey Kardashevskiy if (spapr->initrd_size) { 10707c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-start", 10717c866c6aSDavid Gibson spapr->initrd_base)); 10727c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-end", 10737c866c6aSDavid Gibson spapr->initrd_base + spapr->initrd_size)); 10745ced7895SAlexey Kardashevskiy } 10757c866c6aSDavid Gibson 10767c866c6aSDavid Gibson if (spapr->kernel_size) { 107787262806SAlexey Kardashevskiy uint64_t kprop[2] = { cpu_to_be64(spapr->kernel_addr), 10787c866c6aSDavid Gibson cpu_to_be64(spapr->kernel_size) }; 10797c866c6aSDavid Gibson 10807c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel", 10817c866c6aSDavid Gibson &kprop, sizeof(kprop))); 10827c866c6aSDavid Gibson if (spapr->kernel_le) { 10837c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel-le", NULL, 0)); 10847c866c6aSDavid Gibson } 10857c866c6aSDavid Gibson } 10867c866c6aSDavid Gibson if (boot_menu) { 10877c866c6aSDavid Gibson _FDT((fdt_setprop_cell(fdt, chosen, "qemu,boot-menu", boot_menu))); 10887c866c6aSDavid Gibson } 10897c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-width", graphic_width)); 10907c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-height", graphic_height)); 10917c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-depth", graphic_depth)); 10927c866c6aSDavid Gibson 10937c866c6aSDavid Gibson if (cb && bootlist) { 10947c866c6aSDavid Gibson int i; 10957c866c6aSDavid Gibson 10967c866c6aSDavid Gibson for (i = 0; i < cb; i++) { 10977c866c6aSDavid Gibson if (bootlist[i] == '\n') { 10987c866c6aSDavid Gibson bootlist[i] = ' '; 10997c866c6aSDavid Gibson } 11007c866c6aSDavid Gibson } 11017c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-list", bootlist)); 11027c866c6aSDavid Gibson } 11037c866c6aSDavid Gibson 11047c866c6aSDavid Gibson if (boot_device && strlen(boot_device)) { 11057c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-device", boot_device)); 11067c866c6aSDavid Gibson } 11077c866c6aSDavid Gibson 11087c866c6aSDavid Gibson if (!spapr->has_graphics && stdout_path) { 110990ee4e01SNikunj A Dadhania /* 11101e0e1108SDavid Gibson * "linux,stdout-path" and "stdout" properties are 11111e0e1108SDavid Gibson * deprecated by linux kernel. New platforms should only 11121e0e1108SDavid Gibson * use the "stdout-path" property. Set the new property 11131e0e1108SDavid Gibson * and continue using older property to remain compatible 11141e0e1108SDavid Gibson * with the existing firmware. 111590ee4e01SNikunj A Dadhania */ 11167c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "linux,stdout-path", stdout_path)); 111790ee4e01SNikunj A Dadhania _FDT(fdt_setprop_string(fdt, chosen, "stdout-path", stdout_path)); 11187c866c6aSDavid Gibson } 11197c866c6aSDavid Gibson 11201e0e1108SDavid Gibson /* 11211e0e1108SDavid Gibson * We can deal with BAR reallocation just fine, advertise it 11221e0e1108SDavid Gibson * to the guest 11231e0e1108SDavid Gibson */ 11246c3829a2SAlexey Kardashevskiy if (smc->linux_pci_probe) { 11256c3829a2SAlexey Kardashevskiy _FDT(fdt_setprop_cell(fdt, chosen, "linux,pci-probe-only", 0)); 11266c3829a2SAlexey Kardashevskiy } 11276c3829a2SAlexey Kardashevskiy 1128db592b5bSCédric Le Goater spapr_dt_ov5_platform_support(spapr, fdt, chosen); 11299fb4541fSSam Bobroff 11307c866c6aSDavid Gibson g_free(stdout_path); 11317c866c6aSDavid Gibson g_free(bootlist); 11327c866c6aSDavid Gibson } 11337c866c6aSDavid Gibson 113491335a5eSDavid Gibson _FDT(spapr_dt_ovec(fdt, chosen, spapr->ov5_cas, "ibm,architecture-vec-5")); 11351e0e1108SDavid Gibson } 11361e0e1108SDavid Gibson 1137ce2918cbSDavid Gibson static void spapr_dt_hypervisor(SpaprMachineState *spapr, void *fdt) 1138fca5f2dcSDavid Gibson { 1139fca5f2dcSDavid Gibson /* The /hypervisor node isn't in PAPR - this is a hack to allow PR 1140fca5f2dcSDavid Gibson * KVM to work under pHyp with some guest co-operation */ 1141fca5f2dcSDavid Gibson int hypervisor; 1142fca5f2dcSDavid Gibson uint8_t hypercall[16]; 1143fca5f2dcSDavid Gibson 1144fca5f2dcSDavid Gibson _FDT(hypervisor = fdt_add_subnode(fdt, 0, "hypervisor")); 1145fca5f2dcSDavid Gibson /* indicate KVM hypercall interface */ 1146fca5f2dcSDavid Gibson _FDT(fdt_setprop_string(fdt, hypervisor, "compatible", "linux,kvm")); 1147fca5f2dcSDavid Gibson if (kvmppc_has_cap_fixup_hcalls()) { 1148fca5f2dcSDavid Gibson /* 1149fca5f2dcSDavid Gibson * Older KVM versions with older guest kernels were broken 1150fca5f2dcSDavid Gibson * with the magic page, don't allow the guest to map it. 1151fca5f2dcSDavid Gibson */ 1152fca5f2dcSDavid Gibson if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall, 1153fca5f2dcSDavid Gibson sizeof(hypercall))) { 1154fca5f2dcSDavid Gibson _FDT(fdt_setprop(fdt, hypervisor, "hcall-instructions", 1155fca5f2dcSDavid Gibson hypercall, sizeof(hypercall))); 1156fca5f2dcSDavid Gibson } 1157fca5f2dcSDavid Gibson } 1158fca5f2dcSDavid Gibson } 1159fca5f2dcSDavid Gibson 11600c21e073SDavid Gibson void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space) 116153018216SPaolo Bonzini { 1162c86c1affSDaniel Henrique Barboza MachineState *machine = MACHINE(spapr); 11633c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 1164ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 11657c866c6aSDavid Gibson int ret; 116653018216SPaolo Bonzini void *fdt; 1167ce2918cbSDavid Gibson SpaprPhbState *phb; 1168398a0bd5SDavid Gibson char *buf; 116953018216SPaolo Bonzini 117097b32a6aSDavid Gibson fdt = g_malloc0(space); 117197b32a6aSDavid Gibson _FDT((fdt_create_empty_tree(fdt, space))); 117253018216SPaolo Bonzini 1173398a0bd5SDavid Gibson /* Root node */ 1174398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "device_type", "chrp")); 1175398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "model", "IBM pSeries (emulated by qemu)")); 1176398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "compatible", "qemu,pseries")); 1177398a0bd5SDavid Gibson 11780a794529SDavid Gibson /* Guest UUID & Name*/ 1179398a0bd5SDavid Gibson buf = qemu_uuid_unparse_strdup(&qemu_uuid); 1180398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "vm,uuid", buf)); 1181398a0bd5SDavid Gibson if (qemu_uuid_set) { 1182398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "system-id", buf)); 1183398a0bd5SDavid Gibson } 1184398a0bd5SDavid Gibson g_free(buf); 1185398a0bd5SDavid Gibson 1186398a0bd5SDavid Gibson if (qemu_get_vm_name()) { 1187398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "ibm,partition-name", 1188398a0bd5SDavid Gibson qemu_get_vm_name())); 1189398a0bd5SDavid Gibson } 1190398a0bd5SDavid Gibson 11910a794529SDavid Gibson /* Host Model & Serial Number */ 11920a794529SDavid Gibson if (spapr->host_model) { 11930a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model)); 11940a794529SDavid Gibson } else if (smc->broken_host_serial_model && kvmppc_get_host_model(&buf)) { 11950a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-model", buf)); 11960a794529SDavid Gibson g_free(buf); 11970a794529SDavid Gibson } 11980a794529SDavid Gibson 11990a794529SDavid Gibson if (spapr->host_serial) { 12000a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial)); 12010a794529SDavid Gibson } else if (smc->broken_host_serial_model && kvmppc_get_host_serial(&buf)) { 12020a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf)); 12030a794529SDavid Gibson g_free(buf); 12040a794529SDavid Gibson } 12050a794529SDavid Gibson 1206398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#address-cells", 2)); 1207398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2)); 120853018216SPaolo Bonzini 1209fc7e0765SDavid Gibson /* /interrupt controller */ 121005289273SDavid Gibson spapr_irq_dt(spapr, spapr_max_server_number(spapr), fdt, PHANDLE_INTC); 1211fc7e0765SDavid Gibson 121291335a5eSDavid Gibson ret = spapr_dt_memory(spapr, fdt); 1213e8f986fcSBharata B Rao if (ret < 0) { 1214ce9863b7SCédric Le Goater error_report("couldn't setup memory nodes in fdt"); 1215e8f986fcSBharata B Rao exit(1); 121653018216SPaolo Bonzini } 121753018216SPaolo Bonzini 1218bf5a6696SDavid Gibson /* /vdevice */ 1219bf5a6696SDavid Gibson spapr_dt_vdevice(spapr->vio_bus, fdt); 122053018216SPaolo Bonzini 12214d9392beSThomas Huth if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) { 122291335a5eSDavid Gibson ret = spapr_dt_rng(fdt); 12234d9392beSThomas Huth if (ret < 0) { 1224ce9863b7SCédric Le Goater error_report("could not set up rng device in the fdt"); 12254d9392beSThomas Huth exit(1); 12264d9392beSThomas Huth } 12274d9392beSThomas Huth } 12284d9392beSThomas Huth 122953018216SPaolo Bonzini QLIST_FOREACH(phb, &spapr->phbs, list) { 12308cbe71ecSDavid Gibson ret = spapr_dt_phb(spapr, phb, PHANDLE_INTC, fdt, NULL); 123153018216SPaolo Bonzini if (ret < 0) { 1232da34fed7SThomas Huth error_report("couldn't setup PCI devices in fdt"); 123353018216SPaolo Bonzini exit(1); 123453018216SPaolo Bonzini } 1235da34fed7SThomas Huth } 123653018216SPaolo Bonzini 123791335a5eSDavid Gibson spapr_dt_cpus(fdt, spapr); 123853018216SPaolo Bonzini 1239c20d332aSBharata B Rao if (smc->dr_lmb_enabled) { 12409e7d38e8SDavid Gibson _FDT(spapr_dt_drc(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB)); 1241c20d332aSBharata B Rao } 1242c20d332aSBharata B Rao 1243c5514d0eSIgor Mammedov if (mc->has_hotpluggable_cpus) { 1244af81cf32SBharata B Rao int offset = fdt_path_offset(fdt, "/cpus"); 12459e7d38e8SDavid Gibson ret = spapr_dt_drc(fdt, offset, NULL, SPAPR_DR_CONNECTOR_TYPE_CPU); 1246af81cf32SBharata B Rao if (ret < 0) { 1247af81cf32SBharata B Rao error_report("Couldn't set up CPU DR device tree properties"); 1248af81cf32SBharata B Rao exit(1); 1249af81cf32SBharata B Rao } 1250af81cf32SBharata B Rao } 1251af81cf32SBharata B Rao 1252ffb1e275SDavid Gibson /* /event-sources */ 1253ffbb1705SMichael Roth spapr_dt_events(spapr, fdt); 1254ffb1e275SDavid Gibson 12553f5dabceSDavid Gibson /* /rtas */ 12563f5dabceSDavid Gibson spapr_dt_rtas(spapr, fdt); 12573f5dabceSDavid Gibson 12587c866c6aSDavid Gibson /* /chosen */ 12591e0e1108SDavid Gibson spapr_dt_chosen(spapr, fdt, reset); 1260cf6e5223SDavid Gibson 1261fca5f2dcSDavid Gibson /* /hypervisor */ 1262fca5f2dcSDavid Gibson if (kvm_enabled()) { 1263fca5f2dcSDavid Gibson spapr_dt_hypervisor(spapr, fdt); 1264fca5f2dcSDavid Gibson } 1265fca5f2dcSDavid Gibson 1266cf6e5223SDavid Gibson /* Build memory reserve map */ 1267a49f62b9SAlexey Kardashevskiy if (reset) { 1268cf6e5223SDavid Gibson if (spapr->kernel_size) { 126987262806SAlexey Kardashevskiy _FDT((fdt_add_mem_rsv(fdt, spapr->kernel_addr, 127087262806SAlexey Kardashevskiy spapr->kernel_size))); 1271cf6e5223SDavid Gibson } 1272cf6e5223SDavid Gibson if (spapr->initrd_size) { 1273a49f62b9SAlexey Kardashevskiy _FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base, 1274a49f62b9SAlexey Kardashevskiy spapr->initrd_size))); 1275a49f62b9SAlexey Kardashevskiy } 1276cf6e5223SDavid Gibson } 1277cf6e5223SDavid Gibson 12783998ccd0SNathan Fontenot if (smc->dr_phb_enabled) { 12799e7d38e8SDavid Gibson ret = spapr_dt_drc(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_PHB); 12803998ccd0SNathan Fontenot if (ret < 0) { 12813998ccd0SNathan Fontenot error_report("Couldn't set up PHB DR device tree properties"); 12823998ccd0SNathan Fontenot exit(1); 12833998ccd0SNathan Fontenot } 12843998ccd0SNathan Fontenot } 12853998ccd0SNathan Fontenot 1286ee3a71e3SShivaprasad G Bhat /* NVDIMM devices */ 1287ee3a71e3SShivaprasad G Bhat if (mc->nvdimm_supported) { 1288ee3a71e3SShivaprasad G Bhat spapr_dt_persistent_memory(fdt); 1289ee3a71e3SShivaprasad G Bhat } 1290ee3a71e3SShivaprasad G Bhat 1291997b6cfcSDavid Gibson return fdt; 129253018216SPaolo Bonzini } 129353018216SPaolo Bonzini 129453018216SPaolo Bonzini static uint64_t translate_kernel_address(void *opaque, uint64_t addr) 129553018216SPaolo Bonzini { 129687262806SAlexey Kardashevskiy SpaprMachineState *spapr = opaque; 129787262806SAlexey Kardashevskiy 129887262806SAlexey Kardashevskiy return (addr & 0x0fffffff) + spapr->kernel_addr; 129953018216SPaolo Bonzini } 130053018216SPaolo Bonzini 13011d1be34dSDavid Gibson static void emulate_spapr_hypercall(PPCVirtualHypervisor *vhyp, 13021d1be34dSDavid Gibson PowerPCCPU *cpu) 130353018216SPaolo Bonzini { 130453018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 130553018216SPaolo Bonzini 13068d04fb55SJan Kiszka /* The TCG path should also be holding the BQL at this point */ 13078d04fb55SJan Kiszka g_assert(qemu_mutex_iothread_locked()); 13088d04fb55SJan Kiszka 130953018216SPaolo Bonzini if (msr_pr) { 131053018216SPaolo Bonzini hcall_dprintf("Hypercall made with MSR[PR]=1\n"); 131153018216SPaolo Bonzini env->gpr[3] = H_PRIVILEGE; 131253018216SPaolo Bonzini } else { 131353018216SPaolo Bonzini env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]); 131453018216SPaolo Bonzini } 131553018216SPaolo Bonzini } 131653018216SPaolo Bonzini 131700fd075eSBenjamin Herrenschmidt struct LPCRSyncState { 131800fd075eSBenjamin Herrenschmidt target_ulong value; 131900fd075eSBenjamin Herrenschmidt target_ulong mask; 132000fd075eSBenjamin Herrenschmidt }; 132100fd075eSBenjamin Herrenschmidt 132200fd075eSBenjamin Herrenschmidt static void do_lpcr_sync(CPUState *cs, run_on_cpu_data arg) 132300fd075eSBenjamin Herrenschmidt { 132400fd075eSBenjamin Herrenschmidt struct LPCRSyncState *s = arg.host_ptr; 132500fd075eSBenjamin Herrenschmidt PowerPCCPU *cpu = POWERPC_CPU(cs); 132600fd075eSBenjamin Herrenschmidt CPUPPCState *env = &cpu->env; 132700fd075eSBenjamin Herrenschmidt target_ulong lpcr; 132800fd075eSBenjamin Herrenschmidt 132900fd075eSBenjamin Herrenschmidt cpu_synchronize_state(cs); 133000fd075eSBenjamin Herrenschmidt lpcr = env->spr[SPR_LPCR]; 133100fd075eSBenjamin Herrenschmidt lpcr &= ~s->mask; 133200fd075eSBenjamin Herrenschmidt lpcr |= s->value; 133300fd075eSBenjamin Herrenschmidt ppc_store_lpcr(cpu, lpcr); 133400fd075eSBenjamin Herrenschmidt } 133500fd075eSBenjamin Herrenschmidt 133600fd075eSBenjamin Herrenschmidt void spapr_set_all_lpcrs(target_ulong value, target_ulong mask) 133700fd075eSBenjamin Herrenschmidt { 133800fd075eSBenjamin Herrenschmidt CPUState *cs; 133900fd075eSBenjamin Herrenschmidt struct LPCRSyncState s = { 134000fd075eSBenjamin Herrenschmidt .value = value, 134100fd075eSBenjamin Herrenschmidt .mask = mask 134200fd075eSBenjamin Herrenschmidt }; 134300fd075eSBenjamin Herrenschmidt CPU_FOREACH(cs) { 134400fd075eSBenjamin Herrenschmidt run_on_cpu(cs, do_lpcr_sync, RUN_ON_CPU_HOST_PTR(&s)); 134500fd075eSBenjamin Herrenschmidt } 134600fd075eSBenjamin Herrenschmidt } 134700fd075eSBenjamin Herrenschmidt 134879825f4dSBenjamin Herrenschmidt static void spapr_get_pate(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry) 13499861bb3eSSuraj Jitindar Singh { 1350ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 13519861bb3eSSuraj Jitindar Singh 135279825f4dSBenjamin Herrenschmidt /* Copy PATE1:GR into PATE0:HR */ 135379825f4dSBenjamin Herrenschmidt entry->dw0 = spapr->patb_entry & PATE0_HR; 135479825f4dSBenjamin Herrenschmidt entry->dw1 = spapr->patb_entry; 13559861bb3eSSuraj Jitindar Singh } 13569861bb3eSSuraj Jitindar Singh 1357e6b8fd24SSamuel Mendoza-Jonas #define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2)) 1358e6b8fd24SSamuel Mendoza-Jonas #define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID) 1359e6b8fd24SSamuel Mendoza-Jonas #define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY) 1360e6b8fd24SSamuel Mendoza-Jonas #define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY)) 1361e6b8fd24SSamuel Mendoza-Jonas #define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY)) 1362e6b8fd24SSamuel Mendoza-Jonas 1363715c5407SDavid Gibson /* 1364715c5407SDavid Gibson * Get the fd to access the kernel htab, re-opening it if necessary 1365715c5407SDavid Gibson */ 1366ce2918cbSDavid Gibson static int get_htab_fd(SpaprMachineState *spapr) 1367715c5407SDavid Gibson { 136814b0d748SGreg Kurz Error *local_err = NULL; 136914b0d748SGreg Kurz 1370715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1371715c5407SDavid Gibson return spapr->htab_fd; 1372715c5407SDavid Gibson } 1373715c5407SDavid Gibson 137414b0d748SGreg Kurz spapr->htab_fd = kvmppc_get_htab_fd(false, 0, &local_err); 1375715c5407SDavid Gibson if (spapr->htab_fd < 0) { 137614b0d748SGreg Kurz error_report_err(local_err); 1377715c5407SDavid Gibson } 1378715c5407SDavid Gibson 1379715c5407SDavid Gibson return spapr->htab_fd; 1380715c5407SDavid Gibson } 1381715c5407SDavid Gibson 1382ce2918cbSDavid Gibson void close_htab_fd(SpaprMachineState *spapr) 1383715c5407SDavid Gibson { 1384715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1385715c5407SDavid Gibson close(spapr->htab_fd); 1386715c5407SDavid Gibson } 1387715c5407SDavid Gibson spapr->htab_fd = -1; 1388715c5407SDavid Gibson } 1389715c5407SDavid Gibson 1390e57ca75cSDavid Gibson static hwaddr spapr_hpt_mask(PPCVirtualHypervisor *vhyp) 1391e57ca75cSDavid Gibson { 1392ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1393e57ca75cSDavid Gibson 1394e57ca75cSDavid Gibson return HTAB_SIZE(spapr) / HASH_PTEG_SIZE_64 - 1; 1395e57ca75cSDavid Gibson } 1396e57ca75cSDavid Gibson 13971ec26c75SGreg Kurz static target_ulong spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp) 13981ec26c75SGreg Kurz { 1399ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 14001ec26c75SGreg Kurz 14011ec26c75SGreg Kurz assert(kvm_enabled()); 14021ec26c75SGreg Kurz 14031ec26c75SGreg Kurz if (!spapr->htab) { 14041ec26c75SGreg Kurz return 0; 14051ec26c75SGreg Kurz } 14061ec26c75SGreg Kurz 14071ec26c75SGreg Kurz return (target_ulong)(uintptr_t)spapr->htab | (spapr->htab_shift - 18); 14081ec26c75SGreg Kurz } 14091ec26c75SGreg Kurz 1410e57ca75cSDavid Gibson static const ppc_hash_pte64_t *spapr_map_hptes(PPCVirtualHypervisor *vhyp, 1411e57ca75cSDavid Gibson hwaddr ptex, int n) 1412e57ca75cSDavid Gibson { 1413ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1414e57ca75cSDavid Gibson hwaddr pte_offset = ptex * HASH_PTE_SIZE_64; 1415e57ca75cSDavid Gibson 1416e57ca75cSDavid Gibson if (!spapr->htab) { 1417e57ca75cSDavid Gibson /* 1418e57ca75cSDavid Gibson * HTAB is controlled by KVM. Fetch into temporary buffer 1419e57ca75cSDavid Gibson */ 1420e57ca75cSDavid Gibson ppc_hash_pte64_t *hptes = g_malloc(n * HASH_PTE_SIZE_64); 1421e57ca75cSDavid Gibson kvmppc_read_hptes(hptes, ptex, n); 1422e57ca75cSDavid Gibson return hptes; 1423e57ca75cSDavid Gibson } 1424e57ca75cSDavid Gibson 1425e57ca75cSDavid Gibson /* 1426e57ca75cSDavid Gibson * HTAB is controlled by QEMU. Just point to the internally 1427e57ca75cSDavid Gibson * accessible PTEG. 1428e57ca75cSDavid Gibson */ 1429e57ca75cSDavid Gibson return (const ppc_hash_pte64_t *)(spapr->htab + pte_offset); 1430e57ca75cSDavid Gibson } 1431e57ca75cSDavid Gibson 1432e57ca75cSDavid Gibson static void spapr_unmap_hptes(PPCVirtualHypervisor *vhyp, 1433e57ca75cSDavid Gibson const ppc_hash_pte64_t *hptes, 1434e57ca75cSDavid Gibson hwaddr ptex, int n) 1435e57ca75cSDavid Gibson { 1436ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1437e57ca75cSDavid Gibson 1438e57ca75cSDavid Gibson if (!spapr->htab) { 1439e57ca75cSDavid Gibson g_free((void *)hptes); 1440e57ca75cSDavid Gibson } 1441e57ca75cSDavid Gibson 1442e57ca75cSDavid Gibson /* Nothing to do for qemu managed HPT */ 1443e57ca75cSDavid Gibson } 1444e57ca75cSDavid Gibson 1445a2dd4e83SBenjamin Herrenschmidt void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex, 1446e57ca75cSDavid Gibson uint64_t pte0, uint64_t pte1) 1447e57ca75cSDavid Gibson { 1448a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(cpu->vhyp); 1449e57ca75cSDavid Gibson hwaddr offset = ptex * HASH_PTE_SIZE_64; 1450e57ca75cSDavid Gibson 1451e57ca75cSDavid Gibson if (!spapr->htab) { 1452e57ca75cSDavid Gibson kvmppc_write_hpte(ptex, pte0, pte1); 1453e57ca75cSDavid Gibson } else { 14543054b0caSBenjamin Herrenschmidt if (pte0 & HPTE64_V_VALID) { 1455e57ca75cSDavid Gibson stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); 14563054b0caSBenjamin Herrenschmidt /* 14573054b0caSBenjamin Herrenschmidt * When setting valid, we write PTE1 first. This ensures 14583054b0caSBenjamin Herrenschmidt * proper synchronization with the reading code in 14593054b0caSBenjamin Herrenschmidt * ppc_hash64_pteg_search() 14603054b0caSBenjamin Herrenschmidt */ 14613054b0caSBenjamin Herrenschmidt smp_wmb(); 14623054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset, pte0); 14633054b0caSBenjamin Herrenschmidt } else { 14643054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset, pte0); 14653054b0caSBenjamin Herrenschmidt /* 14663054b0caSBenjamin Herrenschmidt * When clearing it we set PTE0 first. This ensures proper 14673054b0caSBenjamin Herrenschmidt * synchronization with the reading code in 14683054b0caSBenjamin Herrenschmidt * ppc_hash64_pteg_search() 14693054b0caSBenjamin Herrenschmidt */ 14703054b0caSBenjamin Herrenschmidt smp_wmb(); 14713054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); 14723054b0caSBenjamin Herrenschmidt } 1473e57ca75cSDavid Gibson } 1474e57ca75cSDavid Gibson } 1475e57ca75cSDavid Gibson 1476a2dd4e83SBenjamin Herrenschmidt static void spapr_hpte_set_c(PPCVirtualHypervisor *vhyp, hwaddr ptex, 1477a2dd4e83SBenjamin Herrenschmidt uint64_t pte1) 1478a2dd4e83SBenjamin Herrenschmidt { 1479a2dd4e83SBenjamin Herrenschmidt hwaddr offset = ptex * HASH_PTE_SIZE_64 + 15; 1480a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1481a2dd4e83SBenjamin Herrenschmidt 1482a2dd4e83SBenjamin Herrenschmidt if (!spapr->htab) { 1483a2dd4e83SBenjamin Herrenschmidt /* There should always be a hash table when this is called */ 1484a2dd4e83SBenjamin Herrenschmidt error_report("spapr_hpte_set_c called with no hash table !"); 1485a2dd4e83SBenjamin Herrenschmidt return; 1486a2dd4e83SBenjamin Herrenschmidt } 1487a2dd4e83SBenjamin Herrenschmidt 1488a2dd4e83SBenjamin Herrenschmidt /* The HW performs a non-atomic byte update */ 1489a2dd4e83SBenjamin Herrenschmidt stb_p(spapr->htab + offset, (pte1 & 0xff) | 0x80); 1490a2dd4e83SBenjamin Herrenschmidt } 1491a2dd4e83SBenjamin Herrenschmidt 1492a2dd4e83SBenjamin Herrenschmidt static void spapr_hpte_set_r(PPCVirtualHypervisor *vhyp, hwaddr ptex, 1493a2dd4e83SBenjamin Herrenschmidt uint64_t pte1) 1494a2dd4e83SBenjamin Herrenschmidt { 1495a2dd4e83SBenjamin Herrenschmidt hwaddr offset = ptex * HASH_PTE_SIZE_64 + 14; 1496a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1497a2dd4e83SBenjamin Herrenschmidt 1498a2dd4e83SBenjamin Herrenschmidt if (!spapr->htab) { 1499a2dd4e83SBenjamin Herrenschmidt /* There should always be a hash table when this is called */ 1500a2dd4e83SBenjamin Herrenschmidt error_report("spapr_hpte_set_r called with no hash table !"); 1501a2dd4e83SBenjamin Herrenschmidt return; 1502a2dd4e83SBenjamin Herrenschmidt } 1503a2dd4e83SBenjamin Herrenschmidt 1504a2dd4e83SBenjamin Herrenschmidt /* The HW performs a non-atomic byte update */ 1505a2dd4e83SBenjamin Herrenschmidt stb_p(spapr->htab + offset, ((pte1 >> 8) & 0xff) | 0x01); 1506a2dd4e83SBenjamin Herrenschmidt } 1507a2dd4e83SBenjamin Herrenschmidt 15080b0b8310SDavid Gibson int spapr_hpt_shift_for_ramsize(uint64_t ramsize) 15098dfe8e7fSDavid Gibson { 15108dfe8e7fSDavid Gibson int shift; 15118dfe8e7fSDavid Gibson 15128dfe8e7fSDavid Gibson /* We aim for a hash table of size 1/128 the size of RAM (rounded 15138dfe8e7fSDavid Gibson * up). The PAPR recommendation is actually 1/64 of RAM size, but 15148dfe8e7fSDavid Gibson * that's much more than is needed for Linux guests */ 15158dfe8e7fSDavid Gibson shift = ctz64(pow2ceil(ramsize)) - 7; 15168dfe8e7fSDavid Gibson shift = MAX(shift, 18); /* Minimum architected size */ 15178dfe8e7fSDavid Gibson shift = MIN(shift, 46); /* Maximum architected size */ 15188dfe8e7fSDavid Gibson return shift; 15198dfe8e7fSDavid Gibson } 15208dfe8e7fSDavid Gibson 1521ce2918cbSDavid Gibson void spapr_free_hpt(SpaprMachineState *spapr) 152206ec79e8SBharata B Rao { 152306ec79e8SBharata B Rao g_free(spapr->htab); 152406ec79e8SBharata B Rao spapr->htab = NULL; 152506ec79e8SBharata B Rao spapr->htab_shift = 0; 152606ec79e8SBharata B Rao close_htab_fd(spapr); 152706ec79e8SBharata B Rao } 152806ec79e8SBharata B Rao 1529ce2918cbSDavid Gibson void spapr_reallocate_hpt(SpaprMachineState *spapr, int shift, 1530c5f54f3eSDavid Gibson Error **errp) 153153018216SPaolo Bonzini { 1532c5f54f3eSDavid Gibson long rc; 153353018216SPaolo Bonzini 1534c5f54f3eSDavid Gibson /* Clean up any HPT info from a previous boot */ 153506ec79e8SBharata B Rao spapr_free_hpt(spapr); 153653018216SPaolo Bonzini 1537c5f54f3eSDavid Gibson rc = kvmppc_reset_htab(shift); 1538c5f54f3eSDavid Gibson if (rc < 0) { 1539c5f54f3eSDavid Gibson /* kernel-side HPT needed, but couldn't allocate one */ 1540c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1541c5f54f3eSDavid Gibson "Failed to allocate KVM HPT of order %d (try smaller maxmem?)", 1542c5f54f3eSDavid Gibson shift); 1543c5f54f3eSDavid Gibson /* This is almost certainly fatal, but if the caller really 1544c5f54f3eSDavid Gibson * wants to carry on with shift == 0, it's welcome to try */ 1545c5f54f3eSDavid Gibson } else if (rc > 0) { 1546c5f54f3eSDavid Gibson /* kernel-side HPT allocated */ 1547c5f54f3eSDavid Gibson if (rc != shift) { 1548c5f54f3eSDavid Gibson error_setg(errp, 1549c5f54f3eSDavid Gibson "Requested order %d HPT, but kernel allocated order %ld (try smaller maxmem?)", 1550c5f54f3eSDavid Gibson shift, rc); 15517735fedaSBharata B Rao } 15527735fedaSBharata B Rao 155353018216SPaolo Bonzini spapr->htab_shift = shift; 1554c18ad9a5SDavid Gibson spapr->htab = NULL; 1555b817772aSBharata B Rao } else { 1556c5f54f3eSDavid Gibson /* kernel-side HPT not needed, allocate in userspace instead */ 1557c5f54f3eSDavid Gibson size_t size = 1ULL << shift; 1558c5f54f3eSDavid Gibson int i; 155901a57972SSamuel Mendoza-Jonas 1560c5f54f3eSDavid Gibson spapr->htab = qemu_memalign(size, size); 1561c5f54f3eSDavid Gibson if (!spapr->htab) { 1562c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1563c5f54f3eSDavid Gibson "Could not allocate HPT of order %d", shift); 1564c5f54f3eSDavid Gibson return; 1565b817772aSBharata B Rao } 1566b817772aSBharata B Rao 1567c5f54f3eSDavid Gibson memset(spapr->htab, 0, size); 1568c5f54f3eSDavid Gibson spapr->htab_shift = shift; 1569b817772aSBharata B Rao 1570c5f54f3eSDavid Gibson for (i = 0; i < size / HASH_PTE_SIZE_64; i++) { 1571c5f54f3eSDavid Gibson DIRTY_HPTE(HPTE(spapr->htab, i)); 15727735fedaSBharata B Rao } 157353018216SPaolo Bonzini } 1574ee4d9eccSSuraj Jitindar Singh /* We're setting up a hash table, so that means we're not radix */ 1575176dcceeSSuraj Jitindar Singh spapr->patb_entry = 0; 157600fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(0, LPCR_HR | LPCR_UPRT); 157753018216SPaolo Bonzini } 157853018216SPaolo Bonzini 15798897ea5aSDavid Gibson void spapr_setup_hpt(SpaprMachineState *spapr) 1580b4db5413SSuraj Jitindar Singh { 15812772cf6bSDavid Gibson int hpt_shift; 15822772cf6bSDavid Gibson 1583087820e3SGreg Kurz if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DISABLED) { 15842772cf6bSDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(MACHINE(spapr)->maxram_size); 15852772cf6bSDavid Gibson } else { 1586768a20f3SDavid Gibson uint64_t current_ram_size; 1587768a20f3SDavid Gibson 1588768a20f3SDavid Gibson current_ram_size = MACHINE(spapr)->ram_size + get_plugged_memory_size(); 1589768a20f3SDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(current_ram_size); 15902772cf6bSDavid Gibson } 15912772cf6bSDavid Gibson spapr_reallocate_hpt(spapr, hpt_shift, &error_fatal); 15922772cf6bSDavid Gibson 15938897ea5aSDavid Gibson if (kvm_enabled()) { 15946a84737cSDavid Gibson hwaddr vrma_limit = kvmppc_vrma_limit(spapr->htab_shift); 15956a84737cSDavid Gibson 15968897ea5aSDavid Gibson /* Check our RMA fits in the possible VRMA */ 15978897ea5aSDavid Gibson if (vrma_limit < spapr->rma_size) { 15988897ea5aSDavid Gibson error_report("Unable to create %" HWADDR_PRIu 15998897ea5aSDavid Gibson "MiB RMA (VRMA only allows %" HWADDR_PRIu "MiB", 16008897ea5aSDavid Gibson spapr->rma_size / MiB, vrma_limit / MiB); 16018897ea5aSDavid Gibson exit(EXIT_FAILURE); 16028897ea5aSDavid Gibson } 1603b4db5413SSuraj Jitindar Singh } 1604b4db5413SSuraj Jitindar Singh } 1605b4db5413SSuraj Jitindar Singh 160682512483SGreg Kurz static int spapr_reset_drcs(Object *child, void *opaque) 160782512483SGreg Kurz { 1608ce2918cbSDavid Gibson SpaprDrc *drc = 1609ce2918cbSDavid Gibson (SpaprDrc *) object_dynamic_cast(child, 161082512483SGreg Kurz TYPE_SPAPR_DR_CONNECTOR); 161182512483SGreg Kurz 161282512483SGreg Kurz if (drc) { 161382512483SGreg Kurz spapr_drc_reset(drc); 161482512483SGreg Kurz } 161582512483SGreg Kurz 161682512483SGreg Kurz return 0; 161782512483SGreg Kurz } 161882512483SGreg Kurz 1619a0628599SLike Xu static void spapr_machine_reset(MachineState *machine) 162053018216SPaolo Bonzini { 1621ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(machine); 1622182735efSAndreas Färber PowerPCCPU *first_ppc_cpu; 1623744a928cSAlexey Kardashevskiy hwaddr fdt_addr; 1624997b6cfcSDavid Gibson void *fdt; 1625997b6cfcSDavid Gibson int rc; 1626259186a7SAndreas Färber 1627905db916SBharata B Rao kvmppc_svm_off(&error_fatal); 16289f6edd06SDavid Gibson spapr_caps_apply(spapr); 162933face6bSDavid Gibson 16301481fe5fSLaurent Vivier first_ppc_cpu = POWERPC_CPU(first_cpu); 16311481fe5fSLaurent Vivier if (kvm_enabled() && kvmppc_has_cap_mmu_radix() && 1632ad99d04cSDavid Gibson ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, 16331481fe5fSLaurent Vivier spapr->max_compat_pvr)) { 163479825f4dSBenjamin Herrenschmidt /* 163579825f4dSBenjamin Herrenschmidt * If using KVM with radix mode available, VCPUs can be started 1636b4db5413SSuraj Jitindar Singh * without a HPT because KVM will start them in radix mode. 163779825f4dSBenjamin Herrenschmidt * Set the GR bit in PATE so that we know there is no HPT. 163879825f4dSBenjamin Herrenschmidt */ 163979825f4dSBenjamin Herrenschmidt spapr->patb_entry = PATE1_GR; 164000fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(LPCR_HR | LPCR_UPRT, LPCR_HR | LPCR_UPRT); 1641b4db5413SSuraj Jitindar Singh } else { 16428897ea5aSDavid Gibson spapr_setup_hpt(spapr); 1643c5f54f3eSDavid Gibson } 164453018216SPaolo Bonzini 164525c9780dSDavid Gibson qemu_devices_reset(); 164625c9780dSDavid Gibson 16479012a53fSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas); 16489012a53fSGreg Kurz spapr->ov5_cas = spapr_ovec_new(); 16499012a53fSGreg Kurz 1650ce03a193SLaurent Vivier ppc_set_compat_all(spapr->max_compat_pvr, &error_fatal); 16519012a53fSGreg Kurz 1652ec132efaSAlexey Kardashevskiy /* 1653b2e22477SCédric Le Goater * This is fixing some of the default configuration of the XIVE 1654b2e22477SCédric Le Goater * devices. To be called after the reset of the machine devices. 1655b2e22477SCédric Le Goater */ 1656b2e22477SCédric Le Goater spapr_irq_reset(spapr, &error_fatal); 1657b2e22477SCédric Le Goater 165823ff81bdSGreg Kurz /* 165923ff81bdSGreg Kurz * There is no CAS under qtest. Simulate one to please the code that 166023ff81bdSGreg Kurz * depends on spapr->ov5_cas. This is especially needed to test device 166123ff81bdSGreg Kurz * unplug, so we do that before resetting the DRCs. 166223ff81bdSGreg Kurz */ 166323ff81bdSGreg Kurz if (qtest_enabled()) { 166423ff81bdSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas); 166523ff81bdSGreg Kurz spapr->ov5_cas = spapr_ovec_clone(spapr->ov5); 166623ff81bdSGreg Kurz } 166723ff81bdSGreg Kurz 166882512483SGreg Kurz /* DRC reset may cause a device to be unplugged. This will cause troubles 166982512483SGreg Kurz * if this device is used by another device (eg, a running vhost backend 167082512483SGreg Kurz * will crash QEMU if the DIMM holding the vring goes away). To avoid such 167182512483SGreg Kurz * situations, we reset DRCs after all devices have been reset. 167282512483SGreg Kurz */ 167382512483SGreg Kurz object_child_foreach_recursive(object_get_root(), spapr_reset_drcs, NULL); 167482512483SGreg Kurz 167556258174SDaniel Henrique Barboza spapr_clear_pending_events(spapr); 167653018216SPaolo Bonzini 1677b7d1f77aSBenjamin Herrenschmidt /* 1678b7d1f77aSBenjamin Herrenschmidt * We place the device tree and RTAS just below either the top of the RMA, 1679df269271SAlexey Kardashevskiy * or just below 2GB, whichever is lower, so that it can be 1680b7d1f77aSBenjamin Herrenschmidt * processed with 32-bit real mode code if necessary 1681b7d1f77aSBenjamin Herrenschmidt */ 1682744a928cSAlexey Kardashevskiy fdt_addr = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FDT_MAX_SIZE; 1683b7d1f77aSBenjamin Herrenschmidt 168497b32a6aSDavid Gibson fdt = spapr_build_fdt(spapr, true, FDT_MAX_SIZE); 168553018216SPaolo Bonzini 1686997b6cfcSDavid Gibson rc = fdt_pack(fdt); 1687997b6cfcSDavid Gibson 1688997b6cfcSDavid Gibson /* Should only fail if we've built a corrupted tree */ 1689997b6cfcSDavid Gibson assert(rc == 0); 1690997b6cfcSDavid Gibson 1691997b6cfcSDavid Gibson /* Load the fdt */ 1692997b6cfcSDavid Gibson qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 1693cae172abSDavid Gibson cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); 1694fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob); 1695fea35ca4SAlexey Kardashevskiy spapr->fdt_size = fdt_totalsize(fdt); 1696fea35ca4SAlexey Kardashevskiy spapr->fdt_initial_size = spapr->fdt_size; 1697fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = fdt; 1698997b6cfcSDavid Gibson 169953018216SPaolo Bonzini /* Set up the entry state */ 1700395a20d3SAlexey Kardashevskiy spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT, 0, fdt_addr, 0); 1701182735efSAndreas Färber first_ppc_cpu->env.gpr[5] = 0; 170253018216SPaolo Bonzini 1703edfdbf9cSNicholas Piggin spapr->fwnmi_system_reset_addr = -1; 17048af7e1feSNicholas Piggin spapr->fwnmi_machine_check_addr = -1; 17058af7e1feSNicholas Piggin spapr->fwnmi_machine_check_interlock = -1; 17069ac703acSAravinda Prasad 17079ac703acSAravinda Prasad /* Signal all vCPUs waiting on this condition */ 17088af7e1feSNicholas Piggin qemu_cond_broadcast(&spapr->fwnmi_machine_check_interlock_cond); 17092500fb42SAravinda Prasad 17102500fb42SAravinda Prasad migrate_del_blocker(spapr->fwnmi_migration_blocker); 171153018216SPaolo Bonzini } 171253018216SPaolo Bonzini 1713ce2918cbSDavid Gibson static void spapr_create_nvram(SpaprMachineState *spapr) 171453018216SPaolo Bonzini { 17152ff3de68SMarkus Armbruster DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); 17163978b863SPaolo Bonzini DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); 171753018216SPaolo Bonzini 17183978b863SPaolo Bonzini if (dinfo) { 17196231a6daSMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo), 17206231a6daSMarkus Armbruster &error_fatal); 172153018216SPaolo Bonzini } 172253018216SPaolo Bonzini 172353018216SPaolo Bonzini qdev_init_nofail(dev); 172453018216SPaolo Bonzini 1725ce2918cbSDavid Gibson spapr->nvram = (struct SpaprNvram *)dev; 172653018216SPaolo Bonzini } 172753018216SPaolo Bonzini 1728ce2918cbSDavid Gibson static void spapr_rtc_create(SpaprMachineState *spapr) 172928df36a1SDavid Gibson { 1730f6d4dca8SThomas Huth object_initialize_child(OBJECT(spapr), "rtc", 1731f6d4dca8SThomas Huth &spapr->rtc, sizeof(spapr->rtc), TYPE_SPAPR_RTC, 1732f6d4dca8SThomas Huth &error_fatal, NULL); 1733147ff807SCédric Le Goater object_property_set_bool(OBJECT(&spapr->rtc), true, "realized", 1734147ff807SCédric Le Goater &error_fatal); 1735147ff807SCédric Le Goater object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc), 1736d2623129SMarkus Armbruster "date"); 173728df36a1SDavid Gibson } 173828df36a1SDavid Gibson 173953018216SPaolo Bonzini /* Returns whether we want to use VGA or not */ 174014c6a894SDavid Gibson static bool spapr_vga_init(PCIBus *pci_bus, Error **errp) 174153018216SPaolo Bonzini { 174253018216SPaolo Bonzini switch (vga_interface_type) { 174353018216SPaolo Bonzini case VGA_NONE: 17447effdaa3SMark Wu return false; 17457effdaa3SMark Wu case VGA_DEVICE: 17467effdaa3SMark Wu return true; 174753018216SPaolo Bonzini case VGA_STD: 1748b798c190SBenjamin Herrenschmidt case VGA_VIRTIO: 17496e66d0c6SThomas Huth case VGA_CIRRUS: 175053018216SPaolo Bonzini return pci_vga_init(pci_bus) != NULL; 175153018216SPaolo Bonzini default: 175214c6a894SDavid Gibson error_setg(errp, 175314c6a894SDavid Gibson "Unsupported VGA mode, only -vga std or -vga virtio is supported"); 175414c6a894SDavid Gibson return false; 175553018216SPaolo Bonzini } 175653018216SPaolo Bonzini } 175753018216SPaolo Bonzini 17584e5fe368SSuraj Jitindar Singh static int spapr_pre_load(void *opaque) 17594e5fe368SSuraj Jitindar Singh { 17604e5fe368SSuraj Jitindar Singh int rc; 17614e5fe368SSuraj Jitindar Singh 17624e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_load(opaque); 17634e5fe368SSuraj Jitindar Singh if (rc) { 17644e5fe368SSuraj Jitindar Singh return rc; 17654e5fe368SSuraj Jitindar Singh } 17664e5fe368SSuraj Jitindar Singh 17674e5fe368SSuraj Jitindar Singh return 0; 17684e5fe368SSuraj Jitindar Singh } 17694e5fe368SSuraj Jitindar Singh 1770880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id) 1771880ae7deSDavid Gibson { 1772ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 1773880ae7deSDavid Gibson int err = 0; 1774880ae7deSDavid Gibson 1775be85537dSDavid Gibson err = spapr_caps_post_migration(spapr); 1776be85537dSDavid Gibson if (err) { 1777be85537dSDavid Gibson return err; 1778be85537dSDavid Gibson } 1779be85537dSDavid Gibson 1780e502202cSCédric Le Goater /* 1781e502202cSCédric Le Goater * In earlier versions, there was no separate qdev for the PAPR 1782880ae7deSDavid Gibson * RTC, so the RTC offset was stored directly in sPAPREnvironment. 1783880ae7deSDavid Gibson * So when migrating from those versions, poke the incoming offset 1784e502202cSCédric Le Goater * value into the RTC device 1785e502202cSCédric Le Goater */ 1786880ae7deSDavid Gibson if (version_id < 3) { 1787147ff807SCédric Le Goater err = spapr_rtc_import_offset(&spapr->rtc, spapr->rtc_offset); 1788e502202cSCédric Le Goater if (err) { 1789e502202cSCédric Le Goater return err; 1790e502202cSCédric Le Goater } 1791880ae7deSDavid Gibson } 1792880ae7deSDavid Gibson 17930c86b2dfSLaurent Vivier if (kvm_enabled() && spapr->patb_entry) { 1794d39c90f5SBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(first_cpu); 179579825f4dSBenjamin Herrenschmidt bool radix = !!(spapr->patb_entry & PATE1_GR); 1796d39c90f5SBharata B Rao bool gtse = !!(cpu->env.spr[SPR_LPCR] & LPCR_GTSE); 1797d39c90f5SBharata B Rao 179800fd075eSBenjamin Herrenschmidt /* 179900fd075eSBenjamin Herrenschmidt * Update LPCR:HR and UPRT as they may not be set properly in 180000fd075eSBenjamin Herrenschmidt * the stream 180100fd075eSBenjamin Herrenschmidt */ 180200fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(radix ? (LPCR_HR | LPCR_UPRT) : 0, 180300fd075eSBenjamin Herrenschmidt LPCR_HR | LPCR_UPRT); 180400fd075eSBenjamin Herrenschmidt 1805d39c90f5SBharata B Rao err = kvmppc_configure_v3_mmu(cpu, radix, gtse, spapr->patb_entry); 1806d39c90f5SBharata B Rao if (err) { 1807d39c90f5SBharata B Rao error_report("Process table config unsupported by the host"); 1808d39c90f5SBharata B Rao return -EINVAL; 1809d39c90f5SBharata B Rao } 1810d39c90f5SBharata B Rao } 1811d39c90f5SBharata B Rao 18121c53b06cSCédric Le Goater err = spapr_irq_post_load(spapr, version_id); 18131c53b06cSCédric Le Goater if (err) { 18141c53b06cSCédric Le Goater return err; 18151c53b06cSCédric Le Goater } 18161c53b06cSCédric Le Goater 1817880ae7deSDavid Gibson return err; 1818880ae7deSDavid Gibson } 1819880ae7deSDavid Gibson 18204e5fe368SSuraj Jitindar Singh static int spapr_pre_save(void *opaque) 18214e5fe368SSuraj Jitindar Singh { 18224e5fe368SSuraj Jitindar Singh int rc; 18234e5fe368SSuraj Jitindar Singh 18244e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_save(opaque); 18254e5fe368SSuraj Jitindar Singh if (rc) { 18264e5fe368SSuraj Jitindar Singh return rc; 18274e5fe368SSuraj Jitindar Singh } 18284e5fe368SSuraj Jitindar Singh 18294e5fe368SSuraj Jitindar Singh return 0; 18304e5fe368SSuraj Jitindar Singh } 18314e5fe368SSuraj Jitindar Singh 1832880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id) 1833880ae7deSDavid Gibson { 1834880ae7deSDavid Gibson return version_id < 3; 1835880ae7deSDavid Gibson } 1836880ae7deSDavid Gibson 1837fd38804bSDaniel Henrique Barboza static bool spapr_pending_events_needed(void *opaque) 1838fd38804bSDaniel Henrique Barboza { 1839ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 1840fd38804bSDaniel Henrique Barboza return !QTAILQ_EMPTY(&spapr->pending_events); 1841fd38804bSDaniel Henrique Barboza } 1842fd38804bSDaniel Henrique Barboza 1843fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_event_entry = { 1844fd38804bSDaniel Henrique Barboza .name = "spapr_event_log_entry", 1845fd38804bSDaniel Henrique Barboza .version_id = 1, 1846fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1847fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 1848ce2918cbSDavid Gibson VMSTATE_UINT32(summary, SpaprEventLogEntry), 1849ce2918cbSDavid Gibson VMSTATE_UINT32(extended_length, SpaprEventLogEntry), 1850ce2918cbSDavid Gibson VMSTATE_VBUFFER_ALLOC_UINT32(extended_log, SpaprEventLogEntry, 0, 18515341258eSDavid Gibson NULL, extended_length), 1852fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1853fd38804bSDaniel Henrique Barboza }, 1854fd38804bSDaniel Henrique Barboza }; 1855fd38804bSDaniel Henrique Barboza 1856fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_pending_events = { 1857fd38804bSDaniel Henrique Barboza .name = "spapr_pending_events", 1858fd38804bSDaniel Henrique Barboza .version_id = 1, 1859fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1860fd38804bSDaniel Henrique Barboza .needed = spapr_pending_events_needed, 1861fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 1862ce2918cbSDavid Gibson VMSTATE_QTAILQ_V(pending_events, SpaprMachineState, 1, 1863ce2918cbSDavid Gibson vmstate_spapr_event_entry, SpaprEventLogEntry, next), 1864fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1865fd38804bSDaniel Henrique Barboza }, 1866fd38804bSDaniel Henrique Barboza }; 1867fd38804bSDaniel Henrique Barboza 186862ef3760SMichael Roth static bool spapr_ov5_cas_needed(void *opaque) 186962ef3760SMichael Roth { 1870ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 1871ce2918cbSDavid Gibson SpaprOptionVector *ov5_mask = spapr_ovec_new(); 187262ef3760SMichael Roth bool cas_needed; 187362ef3760SMichael Roth 1874ce2918cbSDavid Gibson /* Prior to the introduction of SpaprOptionVector, we had two option 187562ef3760SMichael Roth * vectors we dealt with: OV5_FORM1_AFFINITY, and OV5_DRCONF_MEMORY. 187662ef3760SMichael Roth * Both of these options encode machine topology into the device-tree 187762ef3760SMichael Roth * in such a way that the now-booted OS should still be able to interact 187862ef3760SMichael Roth * appropriately with QEMU regardless of what options were actually 187962ef3760SMichael Roth * negotiatied on the source side. 188062ef3760SMichael Roth * 188162ef3760SMichael Roth * As such, we can avoid migrating the CAS-negotiated options if these 188262ef3760SMichael Roth * are the only options available on the current machine/platform. 188362ef3760SMichael Roth * Since these are the only options available for pseries-2.7 and 188462ef3760SMichael Roth * earlier, this allows us to maintain old->new/new->old migration 188562ef3760SMichael Roth * compatibility. 188662ef3760SMichael Roth * 188762ef3760SMichael Roth * For QEMU 2.8+, there are additional CAS-negotiatable options available 188862ef3760SMichael Roth * via default pseries-2.8 machines and explicit command-line parameters. 188962ef3760SMichael Roth * Some of these options, like OV5_HP_EVT, *do* require QEMU to be aware 189062ef3760SMichael Roth * of the actual CAS-negotiated values to continue working properly. For 189162ef3760SMichael Roth * example, availability of memory unplug depends on knowing whether 189262ef3760SMichael Roth * OV5_HP_EVT was negotiated via CAS. 189362ef3760SMichael Roth * 189462ef3760SMichael Roth * Thus, for any cases where the set of available CAS-negotiatable 189562ef3760SMichael Roth * options extends beyond OV5_FORM1_AFFINITY and OV5_DRCONF_MEMORY, we 1896aef19c04SGreg Kurz * include the CAS-negotiated options in the migration stream, unless 1897aef19c04SGreg Kurz * if they affect boot time behaviour only. 189862ef3760SMichael Roth */ 189962ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_FORM1_AFFINITY); 190062ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_DRCONF_MEMORY); 1901aef19c04SGreg Kurz spapr_ovec_set(ov5_mask, OV5_DRMEM_V2); 190262ef3760SMichael Roth 1903d1d32d62SDavid Gibson /* We need extra information if we have any bits outside the mask 1904d1d32d62SDavid Gibson * defined above */ 1905d1d32d62SDavid Gibson cas_needed = !spapr_ovec_subset(spapr->ov5, ov5_mask); 190662ef3760SMichael Roth 190762ef3760SMichael Roth spapr_ovec_cleanup(ov5_mask); 190862ef3760SMichael Roth 190962ef3760SMichael Roth return cas_needed; 191062ef3760SMichael Roth } 191162ef3760SMichael Roth 191262ef3760SMichael Roth static const VMStateDescription vmstate_spapr_ov5_cas = { 191362ef3760SMichael Roth .name = "spapr_option_vector_ov5_cas", 191462ef3760SMichael Roth .version_id = 1, 191562ef3760SMichael Roth .minimum_version_id = 1, 191662ef3760SMichael Roth .needed = spapr_ov5_cas_needed, 191762ef3760SMichael Roth .fields = (VMStateField[]) { 1918ce2918cbSDavid Gibson VMSTATE_STRUCT_POINTER_V(ov5_cas, SpaprMachineState, 1, 1919ce2918cbSDavid Gibson vmstate_spapr_ovec, SpaprOptionVector), 192062ef3760SMichael Roth VMSTATE_END_OF_LIST() 192162ef3760SMichael Roth }, 192262ef3760SMichael Roth }; 192362ef3760SMichael Roth 19249861bb3eSSuraj Jitindar Singh static bool spapr_patb_entry_needed(void *opaque) 19259861bb3eSSuraj Jitindar Singh { 1926ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 19279861bb3eSSuraj Jitindar Singh 19289861bb3eSSuraj Jitindar Singh return !!spapr->patb_entry; 19299861bb3eSSuraj Jitindar Singh } 19309861bb3eSSuraj Jitindar Singh 19319861bb3eSSuraj Jitindar Singh static const VMStateDescription vmstate_spapr_patb_entry = { 19329861bb3eSSuraj Jitindar Singh .name = "spapr_patb_entry", 19339861bb3eSSuraj Jitindar Singh .version_id = 1, 19349861bb3eSSuraj Jitindar Singh .minimum_version_id = 1, 19359861bb3eSSuraj Jitindar Singh .needed = spapr_patb_entry_needed, 19369861bb3eSSuraj Jitindar Singh .fields = (VMStateField[]) { 1937ce2918cbSDavid Gibson VMSTATE_UINT64(patb_entry, SpaprMachineState), 19389861bb3eSSuraj Jitindar Singh VMSTATE_END_OF_LIST() 19399861bb3eSSuraj Jitindar Singh }, 19409861bb3eSSuraj Jitindar Singh }; 19419861bb3eSSuraj Jitindar Singh 194282cffa2eSCédric Le Goater static bool spapr_irq_map_needed(void *opaque) 194382cffa2eSCédric Le Goater { 1944ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 194582cffa2eSCédric Le Goater 194682cffa2eSCédric Le Goater return spapr->irq_map && !bitmap_empty(spapr->irq_map, spapr->irq_map_nr); 194782cffa2eSCédric Le Goater } 194882cffa2eSCédric Le Goater 194982cffa2eSCédric Le Goater static const VMStateDescription vmstate_spapr_irq_map = { 195082cffa2eSCédric Le Goater .name = "spapr_irq_map", 195182cffa2eSCédric Le Goater .version_id = 1, 195282cffa2eSCédric Le Goater .minimum_version_id = 1, 195382cffa2eSCédric Le Goater .needed = spapr_irq_map_needed, 195482cffa2eSCédric Le Goater .fields = (VMStateField[]) { 1955ce2918cbSDavid Gibson VMSTATE_BITMAP(irq_map, SpaprMachineState, 0, irq_map_nr), 195682cffa2eSCédric Le Goater VMSTATE_END_OF_LIST() 195782cffa2eSCédric Le Goater }, 195882cffa2eSCédric Le Goater }; 195982cffa2eSCédric Le Goater 1960fea35ca4SAlexey Kardashevskiy static bool spapr_dtb_needed(void *opaque) 1961fea35ca4SAlexey Kardashevskiy { 1962ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(opaque); 1963fea35ca4SAlexey Kardashevskiy 1964fea35ca4SAlexey Kardashevskiy return smc->update_dt_enabled; 1965fea35ca4SAlexey Kardashevskiy } 1966fea35ca4SAlexey Kardashevskiy 1967fea35ca4SAlexey Kardashevskiy static int spapr_dtb_pre_load(void *opaque) 1968fea35ca4SAlexey Kardashevskiy { 1969ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 1970fea35ca4SAlexey Kardashevskiy 1971fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob); 1972fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = NULL; 1973fea35ca4SAlexey Kardashevskiy spapr->fdt_size = 0; 1974fea35ca4SAlexey Kardashevskiy 1975fea35ca4SAlexey Kardashevskiy return 0; 1976fea35ca4SAlexey Kardashevskiy } 1977fea35ca4SAlexey Kardashevskiy 1978fea35ca4SAlexey Kardashevskiy static const VMStateDescription vmstate_spapr_dtb = { 1979fea35ca4SAlexey Kardashevskiy .name = "spapr_dtb", 1980fea35ca4SAlexey Kardashevskiy .version_id = 1, 1981fea35ca4SAlexey Kardashevskiy .minimum_version_id = 1, 1982fea35ca4SAlexey Kardashevskiy .needed = spapr_dtb_needed, 1983fea35ca4SAlexey Kardashevskiy .pre_load = spapr_dtb_pre_load, 1984fea35ca4SAlexey Kardashevskiy .fields = (VMStateField[]) { 1985ce2918cbSDavid Gibson VMSTATE_UINT32(fdt_initial_size, SpaprMachineState), 1986ce2918cbSDavid Gibson VMSTATE_UINT32(fdt_size, SpaprMachineState), 1987ce2918cbSDavid Gibson VMSTATE_VBUFFER_ALLOC_UINT32(fdt_blob, SpaprMachineState, 0, NULL, 1988fea35ca4SAlexey Kardashevskiy fdt_size), 1989fea35ca4SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 1990fea35ca4SAlexey Kardashevskiy }, 1991fea35ca4SAlexey Kardashevskiy }; 1992fea35ca4SAlexey Kardashevskiy 19932500fb42SAravinda Prasad static bool spapr_fwnmi_needed(void *opaque) 19942500fb42SAravinda Prasad { 19952500fb42SAravinda Prasad SpaprMachineState *spapr = (SpaprMachineState *)opaque; 19962500fb42SAravinda Prasad 19978af7e1feSNicholas Piggin return spapr->fwnmi_machine_check_addr != -1; 19982500fb42SAravinda Prasad } 19992500fb42SAravinda Prasad 20002500fb42SAravinda Prasad static int spapr_fwnmi_pre_save(void *opaque) 20012500fb42SAravinda Prasad { 20022500fb42SAravinda Prasad SpaprMachineState *spapr = (SpaprMachineState *)opaque; 20032500fb42SAravinda Prasad 20042500fb42SAravinda Prasad /* 20052500fb42SAravinda Prasad * Check if machine check handling is in progress and print a 20062500fb42SAravinda Prasad * warning message. 20072500fb42SAravinda Prasad */ 20088af7e1feSNicholas Piggin if (spapr->fwnmi_machine_check_interlock != -1) { 20092500fb42SAravinda Prasad warn_report("A machine check is being handled during migration. The" 20102500fb42SAravinda Prasad "handler may run and log hardware error on the destination"); 20112500fb42SAravinda Prasad } 20122500fb42SAravinda Prasad 20132500fb42SAravinda Prasad return 0; 20142500fb42SAravinda Prasad } 20152500fb42SAravinda Prasad 20168af7e1feSNicholas Piggin static const VMStateDescription vmstate_spapr_fwnmi = { 20178af7e1feSNicholas Piggin .name = "spapr_fwnmi", 20182500fb42SAravinda Prasad .version_id = 1, 20192500fb42SAravinda Prasad .minimum_version_id = 1, 20202500fb42SAravinda Prasad .needed = spapr_fwnmi_needed, 20212500fb42SAravinda Prasad .pre_save = spapr_fwnmi_pre_save, 20222500fb42SAravinda Prasad .fields = (VMStateField[]) { 2023edfdbf9cSNicholas Piggin VMSTATE_UINT64(fwnmi_system_reset_addr, SpaprMachineState), 20248af7e1feSNicholas Piggin VMSTATE_UINT64(fwnmi_machine_check_addr, SpaprMachineState), 20258af7e1feSNicholas Piggin VMSTATE_INT32(fwnmi_machine_check_interlock, SpaprMachineState), 20262500fb42SAravinda Prasad VMSTATE_END_OF_LIST() 20272500fb42SAravinda Prasad }, 20282500fb42SAravinda Prasad }; 20292500fb42SAravinda Prasad 20304be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = { 20314be21d56SDavid Gibson .name = "spapr", 2032880ae7deSDavid Gibson .version_id = 3, 20334be21d56SDavid Gibson .minimum_version_id = 1, 20344e5fe368SSuraj Jitindar Singh .pre_load = spapr_pre_load, 2035880ae7deSDavid Gibson .post_load = spapr_post_load, 20364e5fe368SSuraj Jitindar Singh .pre_save = spapr_pre_save, 20374be21d56SDavid Gibson .fields = (VMStateField[]) { 2038880ae7deSDavid Gibson /* used to be @next_irq */ 2039880ae7deSDavid Gibson VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4), 20404be21d56SDavid Gibson 20414be21d56SDavid Gibson /* RTC offset */ 2042ce2918cbSDavid Gibson VMSTATE_UINT64_TEST(rtc_offset, SpaprMachineState, version_before_3), 2043880ae7deSDavid Gibson 2044ce2918cbSDavid Gibson VMSTATE_PPC_TIMEBASE_V(tb, SpaprMachineState, 2), 20454be21d56SDavid Gibson VMSTATE_END_OF_LIST() 20464be21d56SDavid Gibson }, 204762ef3760SMichael Roth .subsections = (const VMStateDescription*[]) { 204862ef3760SMichael Roth &vmstate_spapr_ov5_cas, 20499861bb3eSSuraj Jitindar Singh &vmstate_spapr_patb_entry, 2050fd38804bSDaniel Henrique Barboza &vmstate_spapr_pending_events, 20514e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_htm, 20524e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_vsx, 20534e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_dfp, 20548f38eaf8SSuraj Jitindar Singh &vmstate_spapr_cap_cfpc, 205509114fd8SSuraj Jitindar Singh &vmstate_spapr_cap_sbbc, 20564be8d4e7SSuraj Jitindar Singh &vmstate_spapr_cap_ibs, 205764d4a534SDavid Gibson &vmstate_spapr_cap_hpt_maxpagesize, 205882cffa2eSCédric Le Goater &vmstate_spapr_irq_map, 2059b9a477b7SSuraj Jitindar Singh &vmstate_spapr_cap_nested_kvm_hv, 2060fea35ca4SAlexey Kardashevskiy &vmstate_spapr_dtb, 2061c982f5cfSSuraj Jitindar Singh &vmstate_spapr_cap_large_decr, 20628ff43ee4SSuraj Jitindar Singh &vmstate_spapr_cap_ccf_assist, 20639d953ce4SAravinda Prasad &vmstate_spapr_cap_fwnmi, 20648af7e1feSNicholas Piggin &vmstate_spapr_fwnmi, 206562ef3760SMichael Roth NULL 206662ef3760SMichael Roth } 20674be21d56SDavid Gibson }; 20684be21d56SDavid Gibson 20694be21d56SDavid Gibson static int htab_save_setup(QEMUFile *f, void *opaque) 20704be21d56SDavid Gibson { 2071ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 20724be21d56SDavid Gibson 20734be21d56SDavid Gibson /* "Iteration" header */ 20743a384297SBharata B Rao if (!spapr->htab_shift) { 20753a384297SBharata B Rao qemu_put_be32(f, -1); 20763a384297SBharata B Rao } else { 20774be21d56SDavid Gibson qemu_put_be32(f, spapr->htab_shift); 20783a384297SBharata B Rao } 20794be21d56SDavid Gibson 2080e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 2081e68cb8b4SAlexey Kardashevskiy spapr->htab_save_index = 0; 2082e68cb8b4SAlexey Kardashevskiy spapr->htab_first_pass = true; 2083e68cb8b4SAlexey Kardashevskiy } else { 20843a384297SBharata B Rao if (spapr->htab_shift) { 2085e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 20864be21d56SDavid Gibson } 20873a384297SBharata B Rao } 20884be21d56SDavid Gibson 2089e68cb8b4SAlexey Kardashevskiy 2090e68cb8b4SAlexey Kardashevskiy return 0; 2091e68cb8b4SAlexey Kardashevskiy } 20924be21d56SDavid Gibson 2093ce2918cbSDavid Gibson static void htab_save_chunk(QEMUFile *f, SpaprMachineState *spapr, 2094332f7721SGreg Kurz int chunkstart, int n_valid, int n_invalid) 2095332f7721SGreg Kurz { 2096332f7721SGreg Kurz qemu_put_be32(f, chunkstart); 2097332f7721SGreg Kurz qemu_put_be16(f, n_valid); 2098332f7721SGreg Kurz qemu_put_be16(f, n_invalid); 2099332f7721SGreg Kurz qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 2100332f7721SGreg Kurz HASH_PTE_SIZE_64 * n_valid); 2101332f7721SGreg Kurz } 2102332f7721SGreg Kurz 2103332f7721SGreg Kurz static void htab_save_end_marker(QEMUFile *f) 2104332f7721SGreg Kurz { 2105332f7721SGreg Kurz qemu_put_be32(f, 0); 2106332f7721SGreg Kurz qemu_put_be16(f, 0); 2107332f7721SGreg Kurz qemu_put_be16(f, 0); 2108332f7721SGreg Kurz } 2109332f7721SGreg Kurz 2110ce2918cbSDavid Gibson static void htab_save_first_pass(QEMUFile *f, SpaprMachineState *spapr, 21114be21d56SDavid Gibson int64_t max_ns) 21124be21d56SDavid Gibson { 2113378bc217SDavid Gibson bool has_timeout = max_ns != -1; 21144be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 21154be21d56SDavid Gibson int index = spapr->htab_save_index; 2116bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 21174be21d56SDavid Gibson 21184be21d56SDavid Gibson assert(spapr->htab_first_pass); 21194be21d56SDavid Gibson 21204be21d56SDavid Gibson do { 21214be21d56SDavid Gibson int chunkstart; 21224be21d56SDavid Gibson 21234be21d56SDavid Gibson /* Consume invalid HPTEs */ 21244be21d56SDavid Gibson while ((index < htabslots) 21254be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 21264be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 212724ec2863SMarc-André Lureau index++; 21284be21d56SDavid Gibson } 21294be21d56SDavid Gibson 21304be21d56SDavid Gibson /* Consume valid HPTEs */ 21314be21d56SDavid Gibson chunkstart = index; 2132338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 21334be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 21344be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 213524ec2863SMarc-André Lureau index++; 21364be21d56SDavid Gibson } 21374be21d56SDavid Gibson 21384be21d56SDavid Gibson if (index > chunkstart) { 21394be21d56SDavid Gibson int n_valid = index - chunkstart; 21404be21d56SDavid Gibson 2141332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, 0); 21424be21d56SDavid Gibson 2143378bc217SDavid Gibson if (has_timeout && 2144378bc217SDavid Gibson (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 21454be21d56SDavid Gibson break; 21464be21d56SDavid Gibson } 21474be21d56SDavid Gibson } 21484be21d56SDavid Gibson } while ((index < htabslots) && !qemu_file_rate_limit(f)); 21494be21d56SDavid Gibson 21504be21d56SDavid Gibson if (index >= htabslots) { 21514be21d56SDavid Gibson assert(index == htabslots); 21524be21d56SDavid Gibson index = 0; 21534be21d56SDavid Gibson spapr->htab_first_pass = false; 21544be21d56SDavid Gibson } 21554be21d56SDavid Gibson spapr->htab_save_index = index; 21564be21d56SDavid Gibson } 21574be21d56SDavid Gibson 2158ce2918cbSDavid Gibson static int htab_save_later_pass(QEMUFile *f, SpaprMachineState *spapr, 21594be21d56SDavid Gibson int64_t max_ns) 21604be21d56SDavid Gibson { 21614be21d56SDavid Gibson bool final = max_ns < 0; 21624be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 21634be21d56SDavid Gibson int examined = 0, sent = 0; 21644be21d56SDavid Gibson int index = spapr->htab_save_index; 2165bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 21664be21d56SDavid Gibson 21674be21d56SDavid Gibson assert(!spapr->htab_first_pass); 21684be21d56SDavid Gibson 21694be21d56SDavid Gibson do { 21704be21d56SDavid Gibson int chunkstart, invalidstart; 21714be21d56SDavid Gibson 21724be21d56SDavid Gibson /* Consume non-dirty HPTEs */ 21734be21d56SDavid Gibson while ((index < htabslots) 21744be21d56SDavid Gibson && !HPTE_DIRTY(HPTE(spapr->htab, index))) { 21754be21d56SDavid Gibson index++; 21764be21d56SDavid Gibson examined++; 21774be21d56SDavid Gibson } 21784be21d56SDavid Gibson 21794be21d56SDavid Gibson chunkstart = index; 21804be21d56SDavid Gibson /* Consume valid dirty HPTEs */ 2181338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 21824be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 21834be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 21844be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 21854be21d56SDavid Gibson index++; 21864be21d56SDavid Gibson examined++; 21874be21d56SDavid Gibson } 21884be21d56SDavid Gibson 21894be21d56SDavid Gibson invalidstart = index; 21904be21d56SDavid Gibson /* Consume invalid dirty HPTEs */ 2191338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - invalidstart < USHRT_MAX) 21924be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 21934be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 21944be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 21954be21d56SDavid Gibson index++; 21964be21d56SDavid Gibson examined++; 21974be21d56SDavid Gibson } 21984be21d56SDavid Gibson 21994be21d56SDavid Gibson if (index > chunkstart) { 22004be21d56SDavid Gibson int n_valid = invalidstart - chunkstart; 22014be21d56SDavid Gibson int n_invalid = index - invalidstart; 22024be21d56SDavid Gibson 2203332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, n_invalid); 22044be21d56SDavid Gibson sent += index - chunkstart; 22054be21d56SDavid Gibson 2206bc72ad67SAlex Bligh if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 22074be21d56SDavid Gibson break; 22084be21d56SDavid Gibson } 22094be21d56SDavid Gibson } 22104be21d56SDavid Gibson 22114be21d56SDavid Gibson if (examined >= htabslots) { 22124be21d56SDavid Gibson break; 22134be21d56SDavid Gibson } 22144be21d56SDavid Gibson 22154be21d56SDavid Gibson if (index >= htabslots) { 22164be21d56SDavid Gibson assert(index == htabslots); 22174be21d56SDavid Gibson index = 0; 22184be21d56SDavid Gibson } 22194be21d56SDavid Gibson } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final)); 22204be21d56SDavid Gibson 22214be21d56SDavid Gibson if (index >= htabslots) { 22224be21d56SDavid Gibson assert(index == htabslots); 22234be21d56SDavid Gibson index = 0; 22244be21d56SDavid Gibson } 22254be21d56SDavid Gibson 22264be21d56SDavid Gibson spapr->htab_save_index = index; 22274be21d56SDavid Gibson 2228e68cb8b4SAlexey Kardashevskiy return (examined >= htabslots) && (sent == 0) ? 1 : 0; 22294be21d56SDavid Gibson } 22304be21d56SDavid Gibson 2231e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS 5000000 /* 5 ms */ 2232e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE 2048 2233e68cb8b4SAlexey Kardashevskiy 22344be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque) 22354be21d56SDavid Gibson { 2236ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2237715c5407SDavid Gibson int fd; 2238e68cb8b4SAlexey Kardashevskiy int rc = 0; 22394be21d56SDavid Gibson 22404be21d56SDavid Gibson /* Iteration header */ 22413a384297SBharata B Rao if (!spapr->htab_shift) { 22423a384297SBharata B Rao qemu_put_be32(f, -1); 2243e8cd4247SLaurent Vivier return 1; 22443a384297SBharata B Rao } else { 22454be21d56SDavid Gibson qemu_put_be32(f, 0); 22463a384297SBharata B Rao } 22474be21d56SDavid Gibson 2248e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2249e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2250e68cb8b4SAlexey Kardashevskiy 2251715c5407SDavid Gibson fd = get_htab_fd(spapr); 2252715c5407SDavid Gibson if (fd < 0) { 2253715c5407SDavid Gibson return fd; 225401a57972SSamuel Mendoza-Jonas } 225501a57972SSamuel Mendoza-Jonas 2256715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); 2257e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2258e68cb8b4SAlexey Kardashevskiy return rc; 2259e68cb8b4SAlexey Kardashevskiy } 2260e68cb8b4SAlexey Kardashevskiy } else if (spapr->htab_first_pass) { 22614be21d56SDavid Gibson htab_save_first_pass(f, spapr, MAX_ITERATION_NS); 22624be21d56SDavid Gibson } else { 2263e68cb8b4SAlexey Kardashevskiy rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS); 22644be21d56SDavid Gibson } 22654be21d56SDavid Gibson 2266332f7721SGreg Kurz htab_save_end_marker(f); 22674be21d56SDavid Gibson 2268e68cb8b4SAlexey Kardashevskiy return rc; 22694be21d56SDavid Gibson } 22704be21d56SDavid Gibson 22714be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque) 22724be21d56SDavid Gibson { 2273ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2274715c5407SDavid Gibson int fd; 22754be21d56SDavid Gibson 22764be21d56SDavid Gibson /* Iteration header */ 22773a384297SBharata B Rao if (!spapr->htab_shift) { 22783a384297SBharata B Rao qemu_put_be32(f, -1); 22793a384297SBharata B Rao return 0; 22803a384297SBharata B Rao } else { 22814be21d56SDavid Gibson qemu_put_be32(f, 0); 22823a384297SBharata B Rao } 22834be21d56SDavid Gibson 2284e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2285e68cb8b4SAlexey Kardashevskiy int rc; 2286e68cb8b4SAlexey Kardashevskiy 2287e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2288e68cb8b4SAlexey Kardashevskiy 2289715c5407SDavid Gibson fd = get_htab_fd(spapr); 2290715c5407SDavid Gibson if (fd < 0) { 2291715c5407SDavid Gibson return fd; 229201a57972SSamuel Mendoza-Jonas } 229301a57972SSamuel Mendoza-Jonas 2294715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1); 2295e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2296e68cb8b4SAlexey Kardashevskiy return rc; 2297e68cb8b4SAlexey Kardashevskiy } 2298e68cb8b4SAlexey Kardashevskiy } else { 2299378bc217SDavid Gibson if (spapr->htab_first_pass) { 2300378bc217SDavid Gibson htab_save_first_pass(f, spapr, -1); 2301378bc217SDavid Gibson } 23024be21d56SDavid Gibson htab_save_later_pass(f, spapr, -1); 2303e68cb8b4SAlexey Kardashevskiy } 23044be21d56SDavid Gibson 23054be21d56SDavid Gibson /* End marker */ 2306332f7721SGreg Kurz htab_save_end_marker(f); 23074be21d56SDavid Gibson 23084be21d56SDavid Gibson return 0; 23094be21d56SDavid Gibson } 23104be21d56SDavid Gibson 23114be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id) 23124be21d56SDavid Gibson { 2313ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 23144be21d56SDavid Gibson uint32_t section_hdr; 2315e68cb8b4SAlexey Kardashevskiy int fd = -1; 231614b0d748SGreg Kurz Error *local_err = NULL; 23174be21d56SDavid Gibson 23184be21d56SDavid Gibson if (version_id < 1 || version_id > 1) { 231998a5d100SDavid Gibson error_report("htab_load() bad version"); 23204be21d56SDavid Gibson return -EINVAL; 23214be21d56SDavid Gibson } 23224be21d56SDavid Gibson 23234be21d56SDavid Gibson section_hdr = qemu_get_be32(f); 23244be21d56SDavid Gibson 23253a384297SBharata B Rao if (section_hdr == -1) { 23263a384297SBharata B Rao spapr_free_hpt(spapr); 23273a384297SBharata B Rao return 0; 23283a384297SBharata B Rao } 23293a384297SBharata B Rao 23304be21d56SDavid Gibson if (section_hdr) { 2331c5f54f3eSDavid Gibson /* First section gives the htab size */ 2332c5f54f3eSDavid Gibson spapr_reallocate_hpt(spapr, section_hdr, &local_err); 2333c5f54f3eSDavid Gibson if (local_err) { 2334c5f54f3eSDavid Gibson error_report_err(local_err); 23354be21d56SDavid Gibson return -EINVAL; 23364be21d56SDavid Gibson } 23374be21d56SDavid Gibson return 0; 23384be21d56SDavid Gibson } 23394be21d56SDavid Gibson 2340e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2341e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2342e68cb8b4SAlexey Kardashevskiy 234314b0d748SGreg Kurz fd = kvmppc_get_htab_fd(true, 0, &local_err); 2344e68cb8b4SAlexey Kardashevskiy if (fd < 0) { 234514b0d748SGreg Kurz error_report_err(local_err); 234682be8e73SGreg Kurz return fd; 2347e68cb8b4SAlexey Kardashevskiy } 2348e68cb8b4SAlexey Kardashevskiy } 2349e68cb8b4SAlexey Kardashevskiy 23504be21d56SDavid Gibson while (true) { 23514be21d56SDavid Gibson uint32_t index; 23524be21d56SDavid Gibson uint16_t n_valid, n_invalid; 23534be21d56SDavid Gibson 23544be21d56SDavid Gibson index = qemu_get_be32(f); 23554be21d56SDavid Gibson n_valid = qemu_get_be16(f); 23564be21d56SDavid Gibson n_invalid = qemu_get_be16(f); 23574be21d56SDavid Gibson 23584be21d56SDavid Gibson if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) { 23594be21d56SDavid Gibson /* End of Stream */ 23604be21d56SDavid Gibson break; 23614be21d56SDavid Gibson } 23624be21d56SDavid Gibson 2363e68cb8b4SAlexey Kardashevskiy if ((index + n_valid + n_invalid) > 23644be21d56SDavid Gibson (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) { 23654be21d56SDavid Gibson /* Bad index in stream */ 236698a5d100SDavid Gibson error_report( 236798a5d100SDavid Gibson "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)", 236898a5d100SDavid Gibson index, n_valid, n_invalid, spapr->htab_shift); 23694be21d56SDavid Gibson return -EINVAL; 23704be21d56SDavid Gibson } 23714be21d56SDavid Gibson 2372e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 23734be21d56SDavid Gibson if (n_valid) { 23744be21d56SDavid Gibson qemu_get_buffer(f, HPTE(spapr->htab, index), 23754be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 23764be21d56SDavid Gibson } 23774be21d56SDavid Gibson if (n_invalid) { 23784be21d56SDavid Gibson memset(HPTE(spapr->htab, index + n_valid), 0, 23794be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_invalid); 23804be21d56SDavid Gibson } 2381e68cb8b4SAlexey Kardashevskiy } else { 2382e68cb8b4SAlexey Kardashevskiy int rc; 2383e68cb8b4SAlexey Kardashevskiy 2384e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2385e68cb8b4SAlexey Kardashevskiy 2386e68cb8b4SAlexey Kardashevskiy rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid); 2387e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2388e68cb8b4SAlexey Kardashevskiy return rc; 2389e68cb8b4SAlexey Kardashevskiy } 2390e68cb8b4SAlexey Kardashevskiy } 2391e68cb8b4SAlexey Kardashevskiy } 2392e68cb8b4SAlexey Kardashevskiy 2393e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2394e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2395e68cb8b4SAlexey Kardashevskiy close(fd); 23964be21d56SDavid Gibson } 23974be21d56SDavid Gibson 23984be21d56SDavid Gibson return 0; 23994be21d56SDavid Gibson } 24004be21d56SDavid Gibson 240170f794fcSJuan Quintela static void htab_save_cleanup(void *opaque) 2402c573fc03SThomas Huth { 2403ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2404c573fc03SThomas Huth 2405c573fc03SThomas Huth close_htab_fd(spapr); 2406c573fc03SThomas Huth } 2407c573fc03SThomas Huth 24084be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = { 24099907e842SJuan Quintela .save_setup = htab_save_setup, 24104be21d56SDavid Gibson .save_live_iterate = htab_save_iterate, 2411a3e06c3dSDr. David Alan Gilbert .save_live_complete_precopy = htab_save_complete, 241270f794fcSJuan Quintela .save_cleanup = htab_save_cleanup, 24134be21d56SDavid Gibson .load_state = htab_load, 24144be21d56SDavid Gibson }; 24154be21d56SDavid Gibson 24165b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device, 24175b2128d2SAlexander Graf Error **errp) 24185b2128d2SAlexander Graf { 2419c86c1affSDaniel Henrique Barboza MachineState *machine = MACHINE(opaque); 24205b2128d2SAlexander Graf machine->boot_order = g_strdup(boot_device); 24215b2128d2SAlexander Graf } 24225b2128d2SAlexander Graf 2423ce2918cbSDavid Gibson static void spapr_create_lmb_dr_connectors(SpaprMachineState *spapr) 2424224245bfSDavid Gibson { 2425224245bfSDavid Gibson MachineState *machine = MACHINE(spapr); 2426224245bfSDavid Gibson uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 2427e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 2428224245bfSDavid Gibson int i; 2429224245bfSDavid Gibson 2430224245bfSDavid Gibson for (i = 0; i < nr_lmbs; i++) { 2431224245bfSDavid Gibson uint64_t addr; 2432224245bfSDavid Gibson 2433b0c14ec4SDavid Hildenbrand addr = i * lmb_size + machine->device_memory->base; 24346caf3ac6SDavid Gibson spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_LMB, 2435224245bfSDavid Gibson addr / lmb_size); 2436224245bfSDavid Gibson } 2437224245bfSDavid Gibson } 2438224245bfSDavid Gibson 2439224245bfSDavid Gibson /* 2440224245bfSDavid Gibson * If RAM size, maxmem size and individual node mem sizes aren't aligned 2441224245bfSDavid Gibson * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest 2442224245bfSDavid Gibson * since we can't support such unaligned sizes with DRCONF_MEMORY. 2443224245bfSDavid Gibson */ 24447c150d6fSDavid Gibson static void spapr_validate_node_memory(MachineState *machine, Error **errp) 2445224245bfSDavid Gibson { 2446224245bfSDavid Gibson int i; 2447224245bfSDavid Gibson 24487c150d6fSDavid Gibson if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) { 24497c150d6fSDavid Gibson error_setg(errp, "Memory size 0x" RAM_ADDR_FMT 2450ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 24517c150d6fSDavid Gibson machine->ram_size, 2452d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 24537c150d6fSDavid Gibson return; 24547c150d6fSDavid Gibson } 24557c150d6fSDavid Gibson 24567c150d6fSDavid Gibson if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) { 24577c150d6fSDavid Gibson error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT 2458ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 24597c150d6fSDavid Gibson machine->ram_size, 2460d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 24617c150d6fSDavid Gibson return; 2462224245bfSDavid Gibson } 2463224245bfSDavid Gibson 2464aa570207STao Xu for (i = 0; i < machine->numa_state->num_nodes; i++) { 24657e721e7bSTao Xu if (machine->numa_state->nodes[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) { 24667c150d6fSDavid Gibson error_setg(errp, 24677c150d6fSDavid Gibson "Node %d memory size 0x%" PRIx64 2468ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 24697e721e7bSTao Xu i, machine->numa_state->nodes[i].node_mem, 2470d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 24717c150d6fSDavid Gibson return; 2472224245bfSDavid Gibson } 2473224245bfSDavid Gibson } 2474224245bfSDavid Gibson } 2475224245bfSDavid Gibson 2476535455fdSIgor Mammedov /* find cpu slot in machine->possible_cpus by core_id */ 2477535455fdSIgor Mammedov static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx) 2478535455fdSIgor Mammedov { 2479fe6b6346SLike Xu int index = id / ms->smp.threads; 2480535455fdSIgor Mammedov 2481535455fdSIgor Mammedov if (index >= ms->possible_cpus->len) { 2482535455fdSIgor Mammedov return NULL; 2483535455fdSIgor Mammedov } 2484535455fdSIgor Mammedov if (idx) { 2485535455fdSIgor Mammedov *idx = index; 2486535455fdSIgor Mammedov } 2487535455fdSIgor Mammedov return &ms->possible_cpus->cpus[index]; 2488535455fdSIgor Mammedov } 2489535455fdSIgor Mammedov 2490ce2918cbSDavid Gibson static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp) 2491fa98fbfcSSam Bobroff { 2492fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 249329cb4187SGreg Kurz SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 2494fa98fbfcSSam Bobroff Error *local_err = NULL; 2495fa98fbfcSSam Bobroff bool vsmt_user = !!spapr->vsmt; 2496fa98fbfcSSam Bobroff int kvm_smt = kvmppc_smt_threads(); 2497fa98fbfcSSam Bobroff int ret; 2498fe6b6346SLike Xu unsigned int smp_threads = ms->smp.threads; 2499fa98fbfcSSam Bobroff 2500fa98fbfcSSam Bobroff if (!kvm_enabled() && (smp_threads > 1)) { 2501fa98fbfcSSam Bobroff error_setg(&local_err, "TCG cannot support more than 1 thread/core " 2502fa98fbfcSSam Bobroff "on a pseries machine"); 2503fa98fbfcSSam Bobroff goto out; 2504fa98fbfcSSam Bobroff } 2505fa98fbfcSSam Bobroff if (!is_power_of_2(smp_threads)) { 2506fa98fbfcSSam Bobroff error_setg(&local_err, "Cannot support %d threads/core on a pseries " 2507fa98fbfcSSam Bobroff "machine because it must be a power of 2", smp_threads); 2508fa98fbfcSSam Bobroff goto out; 2509fa98fbfcSSam Bobroff } 2510fa98fbfcSSam Bobroff 2511fa98fbfcSSam Bobroff /* Detemine the VSMT mode to use: */ 2512fa98fbfcSSam Bobroff if (vsmt_user) { 2513fa98fbfcSSam Bobroff if (spapr->vsmt < smp_threads) { 2514fa98fbfcSSam Bobroff error_setg(&local_err, "Cannot support VSMT mode %d" 2515fa98fbfcSSam Bobroff " because it must be >= threads/core (%d)", 2516fa98fbfcSSam Bobroff spapr->vsmt, smp_threads); 2517fa98fbfcSSam Bobroff goto out; 2518fa98fbfcSSam Bobroff } 2519fa98fbfcSSam Bobroff /* In this case, spapr->vsmt has been set by the command line */ 252029cb4187SGreg Kurz } else if (!smc->smp_threads_vsmt) { 25218904e5a7SDavid Gibson /* 25228904e5a7SDavid Gibson * Default VSMT value is tricky, because we need it to be as 25238904e5a7SDavid Gibson * consistent as possible (for migration), but this requires 25248904e5a7SDavid Gibson * changing it for at least some existing cases. We pick 8 as 25258904e5a7SDavid Gibson * the value that we'd get with KVM on POWER8, the 25268904e5a7SDavid Gibson * overwhelmingly common case in production systems. 25278904e5a7SDavid Gibson */ 25284ad64cbdSLaurent Vivier spapr->vsmt = MAX(8, smp_threads); 252929cb4187SGreg Kurz } else { 253029cb4187SGreg Kurz spapr->vsmt = smp_threads; 2531fa98fbfcSSam Bobroff } 2532fa98fbfcSSam Bobroff 2533fa98fbfcSSam Bobroff /* KVM: If necessary, set the SMT mode: */ 2534fa98fbfcSSam Bobroff if (kvm_enabled() && (spapr->vsmt != kvm_smt)) { 2535fa98fbfcSSam Bobroff ret = kvmppc_set_smt_threads(spapr->vsmt); 2536fa98fbfcSSam Bobroff if (ret) { 25371f20f2e0SDavid Gibson /* Looks like KVM isn't able to change VSMT mode */ 2538fa98fbfcSSam Bobroff error_setg(&local_err, 2539fa98fbfcSSam Bobroff "Failed to set KVM's VSMT mode to %d (errno %d)", 2540fa98fbfcSSam Bobroff spapr->vsmt, ret); 25411f20f2e0SDavid Gibson /* We can live with that if the default one is big enough 25421f20f2e0SDavid Gibson * for the number of threads, and a submultiple of the one 25431f20f2e0SDavid Gibson * we want. In this case we'll waste some vcpu ids, but 25441f20f2e0SDavid Gibson * behaviour will be correct */ 25451f20f2e0SDavid Gibson if ((kvm_smt >= smp_threads) && ((spapr->vsmt % kvm_smt) == 0)) { 25461f20f2e0SDavid Gibson warn_report_err(local_err); 25471f20f2e0SDavid Gibson local_err = NULL; 25481f20f2e0SDavid Gibson goto out; 25491f20f2e0SDavid Gibson } else { 2550fa98fbfcSSam Bobroff if (!vsmt_user) { 25511f20f2e0SDavid Gibson error_append_hint(&local_err, 25521f20f2e0SDavid Gibson "On PPC, a VM with %d threads/core" 25531f20f2e0SDavid Gibson " on a host with %d threads/core" 25541f20f2e0SDavid Gibson " requires the use of VSMT mode %d.\n", 2555fa98fbfcSSam Bobroff smp_threads, kvm_smt, spapr->vsmt); 2556fa98fbfcSSam Bobroff } 2557cdcca22aSVladimir Sementsov-Ogievskiy kvmppc_error_append_smt_possible_hint(&local_err); 2558fa98fbfcSSam Bobroff goto out; 2559fa98fbfcSSam Bobroff } 2560fa98fbfcSSam Bobroff } 25611f20f2e0SDavid Gibson } 2562fa98fbfcSSam Bobroff /* else TCG: nothing to do currently */ 2563fa98fbfcSSam Bobroff out: 2564fa98fbfcSSam Bobroff error_propagate(errp, local_err); 2565fa98fbfcSSam Bobroff } 2566fa98fbfcSSam Bobroff 2567ce2918cbSDavid Gibson static void spapr_init_cpus(SpaprMachineState *spapr) 25681a5008fcSGreg Kurz { 25691a5008fcSGreg Kurz MachineState *machine = MACHINE(spapr); 25701a5008fcSGreg Kurz MachineClass *mc = MACHINE_GET_CLASS(machine); 2571ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 25721a5008fcSGreg Kurz const char *type = spapr_get_cpu_core_type(machine->cpu_type); 25731a5008fcSGreg Kurz const CPUArchIdList *possible_cpus; 2574fe6b6346SLike Xu unsigned int smp_cpus = machine->smp.cpus; 2575fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 2576fe6b6346SLike Xu unsigned int max_cpus = machine->smp.max_cpus; 25771a5008fcSGreg Kurz int boot_cores_nr = smp_cpus / smp_threads; 25781a5008fcSGreg Kurz int i; 25791a5008fcSGreg Kurz 25801a5008fcSGreg Kurz possible_cpus = mc->possible_cpu_arch_ids(machine); 25811a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 25821a5008fcSGreg Kurz if (smp_cpus % smp_threads) { 25831a5008fcSGreg Kurz error_report("smp_cpus (%u) must be multiple of threads (%u)", 25841a5008fcSGreg Kurz smp_cpus, smp_threads); 25851a5008fcSGreg Kurz exit(1); 25861a5008fcSGreg Kurz } 25871a5008fcSGreg Kurz if (max_cpus % smp_threads) { 25881a5008fcSGreg Kurz error_report("max_cpus (%u) must be multiple of threads (%u)", 25891a5008fcSGreg Kurz max_cpus, smp_threads); 25901a5008fcSGreg Kurz exit(1); 25911a5008fcSGreg Kurz } 25921a5008fcSGreg Kurz } else { 25931a5008fcSGreg Kurz if (max_cpus != smp_cpus) { 25941a5008fcSGreg Kurz error_report("This machine version does not support CPU hotplug"); 25951a5008fcSGreg Kurz exit(1); 25961a5008fcSGreg Kurz } 25971a5008fcSGreg Kurz boot_cores_nr = possible_cpus->len; 25981a5008fcSGreg Kurz } 25991a5008fcSGreg Kurz 26001a5008fcSGreg Kurz if (smc->pre_2_10_has_unused_icps) { 26011a5008fcSGreg Kurz int i; 26021a5008fcSGreg Kurz 26031a518e76SCédric Le Goater for (i = 0; i < spapr_max_server_number(spapr); i++) { 26041a5008fcSGreg Kurz /* Dummy entries get deregistered when real ICPState objects 26051a5008fcSGreg Kurz * are registered during CPU core hotplug. 26061a5008fcSGreg Kurz */ 26071a5008fcSGreg Kurz pre_2_10_vmstate_register_dummy_icp(i); 26081a5008fcSGreg Kurz } 26091a5008fcSGreg Kurz } 26101a5008fcSGreg Kurz 26111a5008fcSGreg Kurz for (i = 0; i < possible_cpus->len; i++) { 26121a5008fcSGreg Kurz int core_id = i * smp_threads; 26131a5008fcSGreg Kurz 26141a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 26151a5008fcSGreg Kurz spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU, 26161a5008fcSGreg Kurz spapr_vcpu_id(spapr, core_id)); 26171a5008fcSGreg Kurz } 26181a5008fcSGreg Kurz 26191a5008fcSGreg Kurz if (i < boot_cores_nr) { 26201a5008fcSGreg Kurz Object *core = object_new(type); 26211a5008fcSGreg Kurz int nr_threads = smp_threads; 26221a5008fcSGreg Kurz 26231a5008fcSGreg Kurz /* Handle the partially filled core for older machine types */ 26241a5008fcSGreg Kurz if ((i + 1) * smp_threads >= smp_cpus) { 26251a5008fcSGreg Kurz nr_threads = smp_cpus - i * smp_threads; 26261a5008fcSGreg Kurz } 26271a5008fcSGreg Kurz 26281a5008fcSGreg Kurz object_property_set_int(core, nr_threads, "nr-threads", 26291a5008fcSGreg Kurz &error_fatal); 26301a5008fcSGreg Kurz object_property_set_int(core, core_id, CPU_CORE_PROP_CORE_ID, 26311a5008fcSGreg Kurz &error_fatal); 26321a5008fcSGreg Kurz object_property_set_bool(core, true, "realized", &error_fatal); 2633ecda255eSSam Bobroff 2634ecda255eSSam Bobroff object_unref(core); 26351a5008fcSGreg Kurz } 26361a5008fcSGreg Kurz } 26371a5008fcSGreg Kurz } 26381a5008fcSGreg Kurz 2639999c9cafSGreg Kurz static PCIHostState *spapr_create_default_phb(void) 2640999c9cafSGreg Kurz { 2641999c9cafSGreg Kurz DeviceState *dev; 2642999c9cafSGreg Kurz 2643999c9cafSGreg Kurz dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE); 2644999c9cafSGreg Kurz qdev_prop_set_uint32(dev, "index", 0); 2645999c9cafSGreg Kurz qdev_init_nofail(dev); 2646999c9cafSGreg Kurz 2647999c9cafSGreg Kurz return PCI_HOST_BRIDGE(dev); 2648999c9cafSGreg Kurz } 2649999c9cafSGreg Kurz 2650425f0b7aSDavid Gibson static hwaddr spapr_rma_size(SpaprMachineState *spapr, Error **errp) 2651425f0b7aSDavid Gibson { 2652425f0b7aSDavid Gibson MachineState *machine = MACHINE(spapr); 2653425f0b7aSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 2654425f0b7aSDavid Gibson hwaddr rma_size = machine->ram_size; 2655425f0b7aSDavid Gibson hwaddr node0_size = spapr_node0_size(machine); 2656425f0b7aSDavid Gibson 2657425f0b7aSDavid Gibson /* RMA has to fit in the first NUMA node */ 2658425f0b7aSDavid Gibson rma_size = MIN(rma_size, node0_size); 2659425f0b7aSDavid Gibson 2660425f0b7aSDavid Gibson /* 2661425f0b7aSDavid Gibson * VRMA access is via a special 1TiB SLB mapping, so the RMA can 2662425f0b7aSDavid Gibson * never exceed that 2663425f0b7aSDavid Gibson */ 2664425f0b7aSDavid Gibson rma_size = MIN(rma_size, 1 * TiB); 2665425f0b7aSDavid Gibson 2666425f0b7aSDavid Gibson /* 2667425f0b7aSDavid Gibson * Clamp the RMA size based on machine type. This is for 2668425f0b7aSDavid Gibson * migration compatibility with older qemu versions, which limited 2669425f0b7aSDavid Gibson * the RMA size for complicated and mostly bad reasons. 2670425f0b7aSDavid Gibson */ 2671425f0b7aSDavid Gibson if (smc->rma_limit) { 2672425f0b7aSDavid Gibson rma_size = MIN(rma_size, smc->rma_limit); 2673425f0b7aSDavid Gibson } 2674425f0b7aSDavid Gibson 2675425f0b7aSDavid Gibson if (rma_size < MIN_RMA_SLOF) { 2676425f0b7aSDavid Gibson error_setg(errp, 2677425f0b7aSDavid Gibson "pSeries SLOF firmware requires >= %" HWADDR_PRIx 2678425f0b7aSDavid Gibson "ldMiB guest RMA (Real Mode Area memory)", 2679425f0b7aSDavid Gibson MIN_RMA_SLOF / MiB); 2680425f0b7aSDavid Gibson return 0; 2681425f0b7aSDavid Gibson } 2682425f0b7aSDavid Gibson 2683425f0b7aSDavid Gibson return rma_size; 2684425f0b7aSDavid Gibson } 2685425f0b7aSDavid Gibson 268653018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */ 2687bcb5ce08SDavid Gibson static void spapr_machine_init(MachineState *machine) 268853018216SPaolo Bonzini { 2689ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(machine); 2690ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 2691ee3a71e3SShivaprasad G Bhat MachineClass *mc = MACHINE_GET_CLASS(machine); 26923ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 26933ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 269453018216SPaolo Bonzini PCIHostState *phb; 269553018216SPaolo Bonzini int i; 269653018216SPaolo Bonzini MemoryRegion *sysmem = get_system_memory(); 2697b7d1f77aSBenjamin Herrenschmidt long load_limit, fw_size; 269853018216SPaolo Bonzini char *filename; 269930f4b05bSDavid Gibson Error *resize_hpt_err = NULL; 270053018216SPaolo Bonzini 2701226419d6SMichael S. Tsirkin msi_nonbroken = true; 270253018216SPaolo Bonzini 270353018216SPaolo Bonzini QLIST_INIT(&spapr->phbs); 27040cffce56SDavid Gibson QTAILQ_INIT(&spapr->pending_dimm_unplugs); 270553018216SPaolo Bonzini 27069f6edd06SDavid Gibson /* Determine capabilities to run with */ 27079f6edd06SDavid Gibson spapr_caps_init(spapr); 27089f6edd06SDavid Gibson 270930f4b05bSDavid Gibson kvmppc_check_papr_resize_hpt(&resize_hpt_err); 271030f4b05bSDavid Gibson if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) { 271130f4b05bSDavid Gibson /* 271230f4b05bSDavid Gibson * If the user explicitly requested a mode we should either 271330f4b05bSDavid Gibson * supply it, or fail completely (which we do below). But if 271430f4b05bSDavid Gibson * it's not set explicitly, we reset our mode to something 271530f4b05bSDavid Gibson * that works 271630f4b05bSDavid Gibson */ 271730f4b05bSDavid Gibson if (resize_hpt_err) { 271830f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 271930f4b05bSDavid Gibson error_free(resize_hpt_err); 272030f4b05bSDavid Gibson resize_hpt_err = NULL; 272130f4b05bSDavid Gibson } else { 272230f4b05bSDavid Gibson spapr->resize_hpt = smc->resize_hpt_default; 272330f4b05bSDavid Gibson } 272430f4b05bSDavid Gibson } 272530f4b05bSDavid Gibson 272630f4b05bSDavid Gibson assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT); 272730f4b05bSDavid Gibson 272830f4b05bSDavid Gibson if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && resize_hpt_err) { 272930f4b05bSDavid Gibson /* 273030f4b05bSDavid Gibson * User requested HPT resize, but this host can't supply it. Bail out 273130f4b05bSDavid Gibson */ 273230f4b05bSDavid Gibson error_report_err(resize_hpt_err); 273330f4b05bSDavid Gibson exit(1); 273430f4b05bSDavid Gibson } 273530f4b05bSDavid Gibson 2736425f0b7aSDavid Gibson spapr->rma_size = spapr_rma_size(spapr, &error_fatal); 2737c4177479SAlexey Kardashevskiy 2738b7d1f77aSBenjamin Herrenschmidt /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */ 2739b7d1f77aSBenjamin Herrenschmidt load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; 274053018216SPaolo Bonzini 2741482969d6SCédric Le Goater /* 2742482969d6SCédric Le Goater * VSMT must be set in order to be able to compute VCPU ids, ie to 27431a518e76SCédric Le Goater * call spapr_max_server_number() or spapr_vcpu_id(). 2744482969d6SCédric Le Goater */ 2745482969d6SCédric Le Goater spapr_set_vsmt_mode(spapr, &error_fatal); 2746482969d6SCédric Le Goater 27477b565160SDavid Gibson /* Set up Interrupt Controller before we create the VCPUs */ 2748fab397d8SCédric Le Goater spapr_irq_init(spapr, &error_fatal); 27497b565160SDavid Gibson 2750dc1b5eeeSGreg Kurz /* Set up containers for ibm,client-architecture-support negotiated options 2751dc1b5eeeSGreg Kurz */ 2752facdb8b6SMichael Roth spapr->ov5 = spapr_ovec_new(); 2753facdb8b6SMichael Roth spapr->ov5_cas = spapr_ovec_new(); 2754facdb8b6SMichael Roth 2755224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2756facdb8b6SMichael Roth spapr_ovec_set(spapr->ov5, OV5_DRCONF_MEMORY); 27577c150d6fSDavid Gibson spapr_validate_node_memory(machine, &error_fatal); 2758224245bfSDavid Gibson } 2759224245bfSDavid Gibson 2760417ece33SMichael Roth spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY); 2761417ece33SMichael Roth 2762ffbb1705SMichael Roth /* advertise support for dedicated HP event source to guests */ 2763ffbb1705SMichael Roth if (spapr->use_hotplug_event_source) { 2764ffbb1705SMichael Roth spapr_ovec_set(spapr->ov5, OV5_HP_EVT); 2765ffbb1705SMichael Roth } 2766ffbb1705SMichael Roth 27672772cf6bSDavid Gibson /* advertise support for HPT resizing */ 27682772cf6bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { 27692772cf6bSDavid Gibson spapr_ovec_set(spapr->ov5, OV5_HPT_RESIZE); 27702772cf6bSDavid Gibson } 27712772cf6bSDavid Gibson 2772a324d6f1SBharata B Rao /* advertise support for ibm,dyamic-memory-v2 */ 2773a324d6f1SBharata B Rao spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2); 2774a324d6f1SBharata B Rao 2775db592b5bSCédric Le Goater /* advertise XIVE on POWER9 machines */ 2776ca62823bSDavid Gibson if (spapr->irq->xive) { 2777db592b5bSCédric Le Goater spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT); 2778db592b5bSCédric Le Goater } 2779db592b5bSCédric Le Goater 278053018216SPaolo Bonzini /* init CPUs */ 27810c86d0fdSDavid Gibson spapr_init_cpus(spapr); 278253018216SPaolo Bonzini 278358c46efaSLaurent Vivier /* 278458c46efaSLaurent Vivier * check we don't have a memory-less/cpu-less NUMA node 278558c46efaSLaurent Vivier * Firmware relies on the existing memory/cpu topology to provide the 278658c46efaSLaurent Vivier * NUMA topology to the kernel. 278758c46efaSLaurent Vivier * And the linux kernel needs to know the NUMA topology at start 278858c46efaSLaurent Vivier * to be able to hotplug CPUs later. 278958c46efaSLaurent Vivier */ 279058c46efaSLaurent Vivier if (machine->numa_state->num_nodes) { 279158c46efaSLaurent Vivier for (i = 0; i < machine->numa_state->num_nodes; ++i) { 279258c46efaSLaurent Vivier /* check for memory-less node */ 279358c46efaSLaurent Vivier if (machine->numa_state->nodes[i].node_mem == 0) { 279458c46efaSLaurent Vivier CPUState *cs; 279558c46efaSLaurent Vivier int found = 0; 279658c46efaSLaurent Vivier /* check for cpu-less node */ 279758c46efaSLaurent Vivier CPU_FOREACH(cs) { 279858c46efaSLaurent Vivier PowerPCCPU *cpu = POWERPC_CPU(cs); 279958c46efaSLaurent Vivier if (cpu->node_id == i) { 280058c46efaSLaurent Vivier found = 1; 280158c46efaSLaurent Vivier break; 280258c46efaSLaurent Vivier } 280358c46efaSLaurent Vivier } 280458c46efaSLaurent Vivier /* memory-less and cpu-less node */ 280558c46efaSLaurent Vivier if (!found) { 280658c46efaSLaurent Vivier error_report( 280758c46efaSLaurent Vivier "Memory-less/cpu-less nodes are not supported (node %d)", 280858c46efaSLaurent Vivier i); 280958c46efaSLaurent Vivier exit(1); 281058c46efaSLaurent Vivier } 281158c46efaSLaurent Vivier } 281258c46efaSLaurent Vivier } 281358c46efaSLaurent Vivier 281458c46efaSLaurent Vivier } 281558c46efaSLaurent Vivier 2816db5127b2SDavid Gibson /* 2817db5127b2SDavid Gibson * NVLink2-connected GPU RAM needs to be placed on a separate NUMA node. 2818db5127b2SDavid Gibson * We assign a new numa ID per GPU in spapr_pci_collect_nvgpu() which is 2819db5127b2SDavid Gibson * called from vPHB reset handler so we initialize the counter here. 2820db5127b2SDavid Gibson * If no NUMA is configured from the QEMU side, we start from 1 as GPU RAM 2821db5127b2SDavid Gibson * must be equally distant from any other node. 2822db5127b2SDavid Gibson * The final value of spapr->gpu_numa_id is going to be written to 2823db5127b2SDavid Gibson * max-associativity-domains in spapr_build_fdt(). 2824db5127b2SDavid Gibson */ 2825db5127b2SDavid Gibson spapr->gpu_numa_id = MAX(1, machine->numa_state->num_nodes); 2826db5127b2SDavid Gibson 28270550b120SGreg Kurz if ((!kvm_enabled() || kvmppc_has_cap_mmu_radix()) && 2828ad99d04cSDavid Gibson ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, 28290550b120SGreg Kurz spapr->max_compat_pvr)) { 2830b4b83312SGreg Kurz spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_300); 28310550b120SGreg Kurz /* KVM and TCG always allow GTSE with radix... */ 28320550b120SGreg Kurz spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE); 28330550b120SGreg Kurz } 28340550b120SGreg Kurz /* ... but not with hash (currently). */ 28350550b120SGreg Kurz 2836026bfd89SDavid Gibson if (kvm_enabled()) { 2837026bfd89SDavid Gibson /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ 2838026bfd89SDavid Gibson kvmppc_enable_logical_ci_hcalls(); 2839ef9971ddSAlexey Kardashevskiy kvmppc_enable_set_mode_hcall(); 28405145ad4fSNathan Whitehorn 28415145ad4fSNathan Whitehorn /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */ 28425145ad4fSNathan Whitehorn kvmppc_enable_clear_ref_mod_hcalls(); 284368f9f708SSuraj Jitindar Singh 284468f9f708SSuraj Jitindar Singh /* Enable H_PAGE_INIT */ 284568f9f708SSuraj Jitindar Singh kvmppc_enable_h_page_init(); 2846026bfd89SDavid Gibson } 2847026bfd89SDavid Gibson 2848ab74e543SIgor Mammedov /* map RAM */ 2849ab74e543SIgor Mammedov memory_region_add_subregion(sysmem, 0, machine->ram); 285053018216SPaolo Bonzini 2851b0c14ec4SDavid Hildenbrand /* always allocate the device memory information */ 2852b0c14ec4SDavid Hildenbrand machine->device_memory = g_malloc0(sizeof(*machine->device_memory)); 2853b0c14ec4SDavid Hildenbrand 28544a1c9cf0SBharata B Rao /* initialize hotplug memory address space */ 28554a1c9cf0SBharata B Rao if (machine->ram_size < machine->maxram_size) { 28560c9269a5SDavid Hildenbrand ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size; 285771c9a3ddSBharata B Rao /* 285871c9a3ddSBharata B Rao * Limit the number of hotpluggable memory slots to half the number 285971c9a3ddSBharata B Rao * slots that KVM supports, leaving the other half for PCI and other 286071c9a3ddSBharata B Rao * devices. However ensure that number of slots doesn't drop below 32. 286171c9a3ddSBharata B Rao */ 286271c9a3ddSBharata B Rao int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 : 286371c9a3ddSBharata B Rao SPAPR_MAX_RAM_SLOTS; 28644a1c9cf0SBharata B Rao 286571c9a3ddSBharata B Rao if (max_memslots < SPAPR_MAX_RAM_SLOTS) { 286671c9a3ddSBharata B Rao max_memslots = SPAPR_MAX_RAM_SLOTS; 286771c9a3ddSBharata B Rao } 286871c9a3ddSBharata B Rao if (machine->ram_slots > max_memslots) { 2869d54e4d76SDavid Gibson error_report("Specified number of memory slots %" 2870d54e4d76SDavid Gibson PRIu64" exceeds max supported %d", 287171c9a3ddSBharata B Rao machine->ram_slots, max_memslots); 2872d54e4d76SDavid Gibson exit(1); 28734a1c9cf0SBharata B Rao } 28744a1c9cf0SBharata B Rao 2875b0c14ec4SDavid Hildenbrand machine->device_memory->base = ROUND_UP(machine->ram_size, 28760c9269a5SDavid Hildenbrand SPAPR_DEVICE_MEM_ALIGN); 2877b0c14ec4SDavid Hildenbrand memory_region_init(&machine->device_memory->mr, OBJECT(spapr), 28780c9269a5SDavid Hildenbrand "device-memory", device_mem_size); 2879b0c14ec4SDavid Hildenbrand memory_region_add_subregion(sysmem, machine->device_memory->base, 2880b0c14ec4SDavid Hildenbrand &machine->device_memory->mr); 28814a1c9cf0SBharata B Rao } 28824a1c9cf0SBharata B Rao 2883224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2884224245bfSDavid Gibson spapr_create_lmb_dr_connectors(spapr); 2885224245bfSDavid Gibson } 2886224245bfSDavid Gibson 28878af7e1feSNicholas Piggin if (spapr_get_cap(spapr, SPAPR_CAP_FWNMI) == SPAPR_CAP_ON) { 28882500fb42SAravinda Prasad /* Create the error string for live migration blocker */ 28892500fb42SAravinda Prasad error_setg(&spapr->fwnmi_migration_blocker, 28902500fb42SAravinda Prasad "A machine check is being handled during migration. The handler" 28912500fb42SAravinda Prasad "may run and log hardware error on the destination"); 28922500fb42SAravinda Prasad } 28932500fb42SAravinda Prasad 2894ee3a71e3SShivaprasad G Bhat if (mc->nvdimm_supported) { 2895ee3a71e3SShivaprasad G Bhat spapr_create_nvdimm_dr_connectors(spapr); 2896ee3a71e3SShivaprasad G Bhat } 2897ee3a71e3SShivaprasad G Bhat 2898ffbb1705SMichael Roth /* Set up RTAS event infrastructure */ 289953018216SPaolo Bonzini spapr_events_init(spapr); 290053018216SPaolo Bonzini 290112f42174SDavid Gibson /* Set up the RTC RTAS interfaces */ 290228df36a1SDavid Gibson spapr_rtc_create(spapr); 290312f42174SDavid Gibson 290453018216SPaolo Bonzini /* Set up VIO bus */ 290553018216SPaolo Bonzini spapr->vio_bus = spapr_vio_bus_init(); 290653018216SPaolo Bonzini 2907b8846a4dSPeter Maydell for (i = 0; i < serial_max_hds(); i++) { 29089bca0edbSPeter Maydell if (serial_hd(i)) { 29099bca0edbSPeter Maydell spapr_vty_create(spapr->vio_bus, serial_hd(i)); 291053018216SPaolo Bonzini } 291153018216SPaolo Bonzini } 291253018216SPaolo Bonzini 291353018216SPaolo Bonzini /* We always have at least the nvram device on VIO */ 291453018216SPaolo Bonzini spapr_create_nvram(spapr); 291553018216SPaolo Bonzini 2916962b6c36SMichael Roth /* 2917962b6c36SMichael Roth * Setup hotplug / dynamic-reconfiguration connectors. top-level 2918962b6c36SMichael Roth * connectors (described in root DT node's "ibm,drc-types" property) 2919962b6c36SMichael Roth * are pre-initialized here. additional child connectors (such as 2920962b6c36SMichael Roth * connectors for a PHBs PCI slots) are added as needed during their 2921962b6c36SMichael Roth * parent's realization. 2922962b6c36SMichael Roth */ 2923962b6c36SMichael Roth if (smc->dr_phb_enabled) { 2924962b6c36SMichael Roth for (i = 0; i < SPAPR_MAX_PHBS; i++) { 2925962b6c36SMichael Roth spapr_dr_connector_new(OBJECT(machine), TYPE_SPAPR_DRC_PHB, i); 2926962b6c36SMichael Roth } 2927962b6c36SMichael Roth } 2928962b6c36SMichael Roth 292953018216SPaolo Bonzini /* Set up PCI */ 293053018216SPaolo Bonzini spapr_pci_rtas_init(); 293153018216SPaolo Bonzini 2932999c9cafSGreg Kurz phb = spapr_create_default_phb(); 293353018216SPaolo Bonzini 293453018216SPaolo Bonzini for (i = 0; i < nb_nics; i++) { 293553018216SPaolo Bonzini NICInfo *nd = &nd_table[i]; 293653018216SPaolo Bonzini 293753018216SPaolo Bonzini if (!nd->model) { 29383c3a4e7aSThomas Huth nd->model = g_strdup("spapr-vlan"); 293953018216SPaolo Bonzini } 294053018216SPaolo Bonzini 29413c3a4e7aSThomas Huth if (g_str_equal(nd->model, "spapr-vlan") || 29423c3a4e7aSThomas Huth g_str_equal(nd->model, "ibmveth")) { 294353018216SPaolo Bonzini spapr_vlan_create(spapr->vio_bus, nd); 294453018216SPaolo Bonzini } else { 294529b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL); 294653018216SPaolo Bonzini } 294753018216SPaolo Bonzini } 294853018216SPaolo Bonzini 294953018216SPaolo Bonzini for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { 295053018216SPaolo Bonzini spapr_vscsi_create(spapr->vio_bus); 295153018216SPaolo Bonzini } 295253018216SPaolo Bonzini 295353018216SPaolo Bonzini /* Graphics */ 295414c6a894SDavid Gibson if (spapr_vga_init(phb->bus, &error_fatal)) { 295553018216SPaolo Bonzini spapr->has_graphics = true; 2956c6e76503SPaolo Bonzini machine->usb |= defaults_enabled() && !machine->usb_disabled; 295753018216SPaolo Bonzini } 295853018216SPaolo Bonzini 29594ee9ced9SMarcel Apfelbaum if (machine->usb) { 296057040d45SThomas Huth if (smc->use_ohci_by_default) { 296153018216SPaolo Bonzini pci_create_simple(phb->bus, -1, "pci-ohci"); 296257040d45SThomas Huth } else { 296357040d45SThomas Huth pci_create_simple(phb->bus, -1, "nec-usb-xhci"); 296457040d45SThomas Huth } 2965c86580b8SMarkus Armbruster 296653018216SPaolo Bonzini if (spapr->has_graphics) { 2967c86580b8SMarkus Armbruster USBBus *usb_bus = usb_bus_find(-1); 2968c86580b8SMarkus Armbruster 2969c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-kbd"); 2970c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-mouse"); 297153018216SPaolo Bonzini } 297253018216SPaolo Bonzini } 297353018216SPaolo Bonzini 297453018216SPaolo Bonzini if (kernel_filename) { 297553018216SPaolo Bonzini uint64_t lowaddr = 0; 297653018216SPaolo Bonzini 29774366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL, 297887262806SAlexey Kardashevskiy translate_kernel_address, spapr, 29796cdda0ffSAleksandar Markovic NULL, &lowaddr, NULL, NULL, 1, 2980a19f7fb0SDavid Gibson PPC_ELF_MACHINE, 0, 0); 2981a19f7fb0SDavid Gibson if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) { 29824366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL, 298387262806SAlexey Kardashevskiy translate_kernel_address, spapr, NULL, 29846cdda0ffSAleksandar Markovic &lowaddr, NULL, NULL, 0, 298587262806SAlexey Kardashevskiy PPC_ELF_MACHINE, 298687262806SAlexey Kardashevskiy 0, 0); 2987a19f7fb0SDavid Gibson spapr->kernel_le = spapr->kernel_size > 0; 298816457e7fSBenjamin Herrenschmidt } 2989a19f7fb0SDavid Gibson if (spapr->kernel_size < 0) { 2990a19f7fb0SDavid Gibson error_report("error loading %s: %s", kernel_filename, 2991a19f7fb0SDavid Gibson load_elf_strerror(spapr->kernel_size)); 299253018216SPaolo Bonzini exit(1); 299353018216SPaolo Bonzini } 299453018216SPaolo Bonzini 299553018216SPaolo Bonzini /* load initrd */ 299653018216SPaolo Bonzini if (initrd_filename) { 299753018216SPaolo Bonzini /* Try to locate the initrd in the gap between the kernel 299853018216SPaolo Bonzini * and the firmware. Add a bit of space just in case 299953018216SPaolo Bonzini */ 300087262806SAlexey Kardashevskiy spapr->initrd_base = (spapr->kernel_addr + spapr->kernel_size 3001a19f7fb0SDavid Gibson + 0x1ffff) & ~0xffff; 3002a19f7fb0SDavid Gibson spapr->initrd_size = load_image_targphys(initrd_filename, 3003a19f7fb0SDavid Gibson spapr->initrd_base, 3004a19f7fb0SDavid Gibson load_limit 3005a19f7fb0SDavid Gibson - spapr->initrd_base); 3006a19f7fb0SDavid Gibson if (spapr->initrd_size < 0) { 3007d54e4d76SDavid Gibson error_report("could not load initial ram disk '%s'", 300853018216SPaolo Bonzini initrd_filename); 300953018216SPaolo Bonzini exit(1); 301053018216SPaolo Bonzini } 301153018216SPaolo Bonzini } 301253018216SPaolo Bonzini } 301353018216SPaolo Bonzini 30148e7ea787SAndreas Färber if (bios_name == NULL) { 30158e7ea787SAndreas Färber bios_name = FW_FILE_NAME; 30168e7ea787SAndreas Färber } 30178e7ea787SAndreas Färber filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 30184c56440dSStefan Weil if (!filename) { 301968fea5a0SThomas Huth error_report("Could not find LPAR firmware '%s'", bios_name); 30204c56440dSStefan Weil exit(1); 30214c56440dSStefan Weil } 302253018216SPaolo Bonzini fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); 302368fea5a0SThomas Huth if (fw_size <= 0) { 302468fea5a0SThomas Huth error_report("Could not load LPAR firmware '%s'", filename); 302553018216SPaolo Bonzini exit(1); 302653018216SPaolo Bonzini } 302753018216SPaolo Bonzini g_free(filename); 302853018216SPaolo Bonzini 302928e02042SDavid Gibson /* FIXME: Should register things through the MachineState's qdev 303028e02042SDavid Gibson * interface, this is a legacy from the sPAPREnvironment structure 303128e02042SDavid Gibson * which predated MachineState but had a similar function */ 30324be21d56SDavid Gibson vmstate_register(NULL, 0, &vmstate_spapr, spapr); 30331df2c9a2SPeter Xu register_savevm_live("spapr/htab", VMSTATE_INSTANCE_ID_ANY, 1, 30344be21d56SDavid Gibson &savevm_htab_handlers, spapr); 30354be21d56SDavid Gibson 3036bb2bdd81SGreg Kurz qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine), 3037bb2bdd81SGreg Kurz &error_fatal); 3038bb2bdd81SGreg Kurz 30395b2128d2SAlexander Graf qemu_register_boot_set(spapr_boot_set, spapr); 304042043e4fSLaurent Vivier 304193eac7b8SNicholas Piggin /* 304293eac7b8SNicholas Piggin * Nothing needs to be done to resume a suspended guest because 304393eac7b8SNicholas Piggin * suspending does not change the machine state, so no need for 304493eac7b8SNicholas Piggin * a ->wakeup method. 304593eac7b8SNicholas Piggin */ 304693eac7b8SNicholas Piggin qemu_register_wakeup_support(); 304793eac7b8SNicholas Piggin 304842043e4fSLaurent Vivier if (kvm_enabled()) { 30493dc410aeSAlexey Kardashevskiy /* to stop and start vmclock */ 305042043e4fSLaurent Vivier qemu_add_vm_change_state_handler(cpu_ppc_clock_vm_state_change, 305142043e4fSLaurent Vivier &spapr->tb); 30523dc410aeSAlexey Kardashevskiy 30533dc410aeSAlexey Kardashevskiy kvmppc_spapr_enable_inkernel_multitce(); 305442043e4fSLaurent Vivier } 30559ac703acSAravinda Prasad 30568af7e1feSNicholas Piggin qemu_cond_init(&spapr->fwnmi_machine_check_interlock_cond); 305753018216SPaolo Bonzini } 305853018216SPaolo Bonzini 3059dc0ca80eSEric Auger static int spapr_kvm_type(MachineState *machine, const char *vm_type) 3060135a129aSAneesh Kumar K.V { 3061135a129aSAneesh Kumar K.V if (!vm_type) { 3062135a129aSAneesh Kumar K.V return 0; 3063135a129aSAneesh Kumar K.V } 3064135a129aSAneesh Kumar K.V 3065135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "HV")) { 3066135a129aSAneesh Kumar K.V return 1; 3067135a129aSAneesh Kumar K.V } 3068135a129aSAneesh Kumar K.V 3069135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "PR")) { 3070135a129aSAneesh Kumar K.V return 2; 3071135a129aSAneesh Kumar K.V } 3072135a129aSAneesh Kumar K.V 3073135a129aSAneesh Kumar K.V error_report("Unknown kvm-type specified '%s'", vm_type); 3074135a129aSAneesh Kumar K.V exit(1); 3075135a129aSAneesh Kumar K.V } 3076135a129aSAneesh Kumar K.V 307771461b0fSAlexey Kardashevskiy /* 3078627b84f4SGonglei * Implementation of an interface to adjust firmware path 307971461b0fSAlexey Kardashevskiy * for the bootindex property handling. 308071461b0fSAlexey Kardashevskiy */ 308171461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, 308271461b0fSAlexey Kardashevskiy DeviceState *dev) 308371461b0fSAlexey Kardashevskiy { 308471461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \ 308571461b0fSAlexey Kardashevskiy ((type *)object_dynamic_cast(OBJECT(obj), (name))) 308671461b0fSAlexey Kardashevskiy SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); 3087ce2918cbSDavid Gibson SpaprPhbState *phb = CAST(SpaprPhbState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); 3088c4e13492SFelipe Franciosi VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON); 308971461b0fSAlexey Kardashevskiy 309071461b0fSAlexey Kardashevskiy if (d) { 309171461b0fSAlexey Kardashevskiy void *spapr = CAST(void, bus->parent, "spapr-vscsi"); 309271461b0fSAlexey Kardashevskiy VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); 309371461b0fSAlexey Kardashevskiy USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); 309471461b0fSAlexey Kardashevskiy 309571461b0fSAlexey Kardashevskiy if (spapr) { 309671461b0fSAlexey Kardashevskiy /* 309771461b0fSAlexey Kardashevskiy * Replace "channel@0/disk@0,0" with "disk@8000000000000000": 30981ac24c91SThomas Huth * In the top 16 bits of the 64-bit LUN, we use SRP luns of the form 30991ac24c91SThomas Huth * 0x8000 | (target << 8) | (bus << 5) | lun 31001ac24c91SThomas Huth * (see the "Logical unit addressing format" table in SAM5) 310171461b0fSAlexey Kardashevskiy */ 31021ac24c91SThomas Huth unsigned id = 0x8000 | (d->id << 8) | (d->channel << 5) | d->lun; 310371461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 310471461b0fSAlexey Kardashevskiy (uint64_t)id << 48); 310571461b0fSAlexey Kardashevskiy } else if (virtio) { 310671461b0fSAlexey Kardashevskiy /* 310771461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (target << 8) | lun 310871461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 310971461b0fSAlexey Kardashevskiy * Note: the quote above is from SLOF and it is wrong, 311071461b0fSAlexey Kardashevskiy * the actual binding is: 311171461b0fSAlexey Kardashevskiy * swap 0100 or 10 << or 20 << ( target lun-id -- srplun ) 311271461b0fSAlexey Kardashevskiy */ 311371461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (d->id << 16) | d->lun; 3114bac658d1SThomas Huth if (d->lun >= 256) { 3115bac658d1SThomas Huth /* Use the LUN "flat space addressing method" */ 3116bac658d1SThomas Huth id |= 0x4000; 3117bac658d1SThomas Huth } 311871461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 311971461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 312071461b0fSAlexey Kardashevskiy } else if (usb) { 312171461b0fSAlexey Kardashevskiy /* 312271461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (usb-port << 16) | lun 312371461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 312471461b0fSAlexey Kardashevskiy */ 312571461b0fSAlexey Kardashevskiy unsigned usb_port = atoi(usb->port->path); 312671461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (usb_port << 16) | d->lun; 312771461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 312871461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 312971461b0fSAlexey Kardashevskiy } 313071461b0fSAlexey Kardashevskiy } 313171461b0fSAlexey Kardashevskiy 3132b99260ebSThomas Huth /* 3133b99260ebSThomas Huth * SLOF probes the USB devices, and if it recognizes that the device is a 3134b99260ebSThomas Huth * storage device, it changes its name to "storage" instead of "usb-host", 3135b99260ebSThomas Huth * and additionally adds a child node for the SCSI LUN, so the correct 3136b99260ebSThomas Huth * boot path in SLOF is something like .../storage@1/disk@xxx" instead. 3137b99260ebSThomas Huth */ 3138b99260ebSThomas Huth if (strcmp("usb-host", qdev_fw_name(dev)) == 0) { 3139b99260ebSThomas Huth USBDevice *usbdev = CAST(USBDevice, dev, TYPE_USB_DEVICE); 3140b99260ebSThomas Huth if (usb_host_dev_is_scsi_storage(usbdev)) { 3141b99260ebSThomas Huth return g_strdup_printf("storage@%s/disk", usbdev->port->path); 3142b99260ebSThomas Huth } 3143b99260ebSThomas Huth } 3144b99260ebSThomas Huth 314571461b0fSAlexey Kardashevskiy if (phb) { 314671461b0fSAlexey Kardashevskiy /* Replace "pci" with "pci@800000020000000" */ 314771461b0fSAlexey Kardashevskiy return g_strdup_printf("pci@%"PRIX64, phb->buid); 314871461b0fSAlexey Kardashevskiy } 314971461b0fSAlexey Kardashevskiy 3150c4e13492SFelipe Franciosi if (vsc) { 3151c4e13492SFelipe Franciosi /* Same logic as virtio above */ 3152c4e13492SFelipe Franciosi unsigned id = 0x1000000 | (vsc->target << 16) | vsc->lun; 3153c4e13492SFelipe Franciosi return g_strdup_printf("disk@%"PRIX64, (uint64_t)id << 32); 3154c4e13492SFelipe Franciosi } 3155c4e13492SFelipe Franciosi 31564871dd4cSThomas Huth if (g_str_equal("pci-bridge", qdev_fw_name(dev))) { 31574871dd4cSThomas Huth /* SLOF uses "pci" instead of "pci-bridge" for PCI bridges */ 31584871dd4cSThomas Huth PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); 31594871dd4cSThomas Huth return g_strdup_printf("pci@%x", PCI_SLOT(pcidev->devfn)); 31604871dd4cSThomas Huth } 31614871dd4cSThomas Huth 316271461b0fSAlexey Kardashevskiy return NULL; 316371461b0fSAlexey Kardashevskiy } 316471461b0fSAlexey Kardashevskiy 316523825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp) 316623825581SEduardo Habkost { 3167ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 316823825581SEduardo Habkost 316928e02042SDavid Gibson return g_strdup(spapr->kvm_type); 317023825581SEduardo Habkost } 317123825581SEduardo Habkost 317223825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp) 317323825581SEduardo Habkost { 3174ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 317523825581SEduardo Habkost 317628e02042SDavid Gibson g_free(spapr->kvm_type); 317728e02042SDavid Gibson spapr->kvm_type = g_strdup(value); 317823825581SEduardo Habkost } 317923825581SEduardo Habkost 3180f6229214SMichael Roth static bool spapr_get_modern_hotplug_events(Object *obj, Error **errp) 3181f6229214SMichael Roth { 3182ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3183f6229214SMichael Roth 3184f6229214SMichael Roth return spapr->use_hotplug_event_source; 3185f6229214SMichael Roth } 3186f6229214SMichael Roth 3187f6229214SMichael Roth static void spapr_set_modern_hotplug_events(Object *obj, bool value, 3188f6229214SMichael Roth Error **errp) 3189f6229214SMichael Roth { 3190ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3191f6229214SMichael Roth 3192f6229214SMichael Roth spapr->use_hotplug_event_source = value; 3193f6229214SMichael Roth } 3194f6229214SMichael Roth 3195fcad0d21SAlexey Kardashevskiy static bool spapr_get_msix_emulation(Object *obj, Error **errp) 3196fcad0d21SAlexey Kardashevskiy { 3197fcad0d21SAlexey Kardashevskiy return true; 3198fcad0d21SAlexey Kardashevskiy } 3199fcad0d21SAlexey Kardashevskiy 320030f4b05bSDavid Gibson static char *spapr_get_resize_hpt(Object *obj, Error **errp) 320130f4b05bSDavid Gibson { 3202ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 320330f4b05bSDavid Gibson 320430f4b05bSDavid Gibson switch (spapr->resize_hpt) { 320530f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DEFAULT: 320630f4b05bSDavid Gibson return g_strdup("default"); 320730f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DISABLED: 320830f4b05bSDavid Gibson return g_strdup("disabled"); 320930f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_ENABLED: 321030f4b05bSDavid Gibson return g_strdup("enabled"); 321130f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_REQUIRED: 321230f4b05bSDavid Gibson return g_strdup("required"); 321330f4b05bSDavid Gibson } 321430f4b05bSDavid Gibson g_assert_not_reached(); 321530f4b05bSDavid Gibson } 321630f4b05bSDavid Gibson 321730f4b05bSDavid Gibson static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp) 321830f4b05bSDavid Gibson { 3219ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 322030f4b05bSDavid Gibson 322130f4b05bSDavid Gibson if (strcmp(value, "default") == 0) { 322230f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DEFAULT; 322330f4b05bSDavid Gibson } else if (strcmp(value, "disabled") == 0) { 322430f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 322530f4b05bSDavid Gibson } else if (strcmp(value, "enabled") == 0) { 322630f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_ENABLED; 322730f4b05bSDavid Gibson } else if (strcmp(value, "required") == 0) { 322830f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_REQUIRED; 322930f4b05bSDavid Gibson } else { 323030f4b05bSDavid Gibson error_setg(errp, "Bad value for \"resize-hpt\" property"); 323130f4b05bSDavid Gibson } 323230f4b05bSDavid Gibson } 323330f4b05bSDavid Gibson 32343ba3d0bcSCédric Le Goater static char *spapr_get_ic_mode(Object *obj, Error **errp) 32353ba3d0bcSCédric Le Goater { 3236ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 32373ba3d0bcSCédric Le Goater 32383ba3d0bcSCédric Le Goater if (spapr->irq == &spapr_irq_xics_legacy) { 32393ba3d0bcSCédric Le Goater return g_strdup("legacy"); 32403ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xics) { 32413ba3d0bcSCédric Le Goater return g_strdup("xics"); 32423ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xive) { 32433ba3d0bcSCédric Le Goater return g_strdup("xive"); 324413db0cd9SCédric Le Goater } else if (spapr->irq == &spapr_irq_dual) { 324513db0cd9SCédric Le Goater return g_strdup("dual"); 32463ba3d0bcSCédric Le Goater } 32473ba3d0bcSCédric Le Goater g_assert_not_reached(); 32483ba3d0bcSCédric Le Goater } 32493ba3d0bcSCédric Le Goater 32503ba3d0bcSCédric Le Goater static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp) 32513ba3d0bcSCédric Le Goater { 3252ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 32533ba3d0bcSCédric Le Goater 325421df5e4fSGreg Kurz if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { 325521df5e4fSGreg Kurz error_setg(errp, "This machine only uses the legacy XICS backend, don't pass ic-mode"); 325621df5e4fSGreg Kurz return; 325721df5e4fSGreg Kurz } 325821df5e4fSGreg Kurz 32593ba3d0bcSCédric Le Goater /* The legacy IRQ backend can not be set */ 32603ba3d0bcSCédric Le Goater if (strcmp(value, "xics") == 0) { 32613ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xics; 32623ba3d0bcSCédric Le Goater } else if (strcmp(value, "xive") == 0) { 32633ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xive; 326413db0cd9SCédric Le Goater } else if (strcmp(value, "dual") == 0) { 326513db0cd9SCédric Le Goater spapr->irq = &spapr_irq_dual; 32663ba3d0bcSCédric Le Goater } else { 32673ba3d0bcSCédric Le Goater error_setg(errp, "Bad value for \"ic-mode\" property"); 32683ba3d0bcSCédric Le Goater } 32693ba3d0bcSCédric Le Goater } 32703ba3d0bcSCédric Le Goater 327127461d69SPrasad J Pandit static char *spapr_get_host_model(Object *obj, Error **errp) 327227461d69SPrasad J Pandit { 3273ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 327427461d69SPrasad J Pandit 327527461d69SPrasad J Pandit return g_strdup(spapr->host_model); 327627461d69SPrasad J Pandit } 327727461d69SPrasad J Pandit 327827461d69SPrasad J Pandit static void spapr_set_host_model(Object *obj, const char *value, Error **errp) 327927461d69SPrasad J Pandit { 3280ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 328127461d69SPrasad J Pandit 328227461d69SPrasad J Pandit g_free(spapr->host_model); 328327461d69SPrasad J Pandit spapr->host_model = g_strdup(value); 328427461d69SPrasad J Pandit } 328527461d69SPrasad J Pandit 328627461d69SPrasad J Pandit static char *spapr_get_host_serial(Object *obj, Error **errp) 328727461d69SPrasad J Pandit { 3288ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 328927461d69SPrasad J Pandit 329027461d69SPrasad J Pandit return g_strdup(spapr->host_serial); 329127461d69SPrasad J Pandit } 329227461d69SPrasad J Pandit 329327461d69SPrasad J Pandit static void spapr_set_host_serial(Object *obj, const char *value, Error **errp) 329427461d69SPrasad J Pandit { 3295ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 329627461d69SPrasad J Pandit 329727461d69SPrasad J Pandit g_free(spapr->host_serial); 329827461d69SPrasad J Pandit spapr->host_serial = g_strdup(value); 329927461d69SPrasad J Pandit } 330027461d69SPrasad J Pandit 3301bcb5ce08SDavid Gibson static void spapr_instance_init(Object *obj) 330223825581SEduardo Habkost { 3303ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3304ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 3305715c5407SDavid Gibson 3306715c5407SDavid Gibson spapr->htab_fd = -1; 3307f6229214SMichael Roth spapr->use_hotplug_event_source = true; 330823825581SEduardo Habkost object_property_add_str(obj, "kvm-type", 3309d2623129SMarkus Armbruster spapr_get_kvm_type, spapr_set_kvm_type); 331049d2e648SMarcel Apfelbaum object_property_set_description(obj, "kvm-type", 33117eecec7dSMarkus Armbruster "Specifies the KVM virtualization mode (HV, PR)"); 3312f6229214SMichael Roth object_property_add_bool(obj, "modern-hotplug-events", 3313f6229214SMichael Roth spapr_get_modern_hotplug_events, 3314d2623129SMarkus Armbruster spapr_set_modern_hotplug_events); 3315f6229214SMichael Roth object_property_set_description(obj, "modern-hotplug-events", 3316f6229214SMichael Roth "Use dedicated hotplug event mechanism in" 3317f6229214SMichael Roth " place of standard EPOW events when possible" 33187eecec7dSMarkus Armbruster " (required for memory hot-unplug support)"); 33197843c0d6SDavid Gibson ppc_compat_add_property(obj, "max-cpu-compat", &spapr->max_compat_pvr, 332040c2281cSMarkus Armbruster "Maximum permitted CPU compatibility mode"); 332130f4b05bSDavid Gibson 332230f4b05bSDavid Gibson object_property_add_str(obj, "resize-hpt", 3323d2623129SMarkus Armbruster spapr_get_resize_hpt, spapr_set_resize_hpt); 332430f4b05bSDavid Gibson object_property_set_description(obj, "resize-hpt", 33257eecec7dSMarkus Armbruster "Resizing of the Hash Page Table (enabled, disabled, required)"); 332664a7b8deSFelipe Franciosi object_property_add_uint32_ptr(obj, "vsmt", 3327d2623129SMarkus Armbruster &spapr->vsmt, OBJ_PROP_FLAG_READWRITE); 3328fa98fbfcSSam Bobroff object_property_set_description(obj, "vsmt", 3329fa98fbfcSSam Bobroff "Virtual SMT: KVM behaves as if this were" 33307eecec7dSMarkus Armbruster " the host's SMT mode"); 333164a7b8deSFelipe Franciosi 3332fcad0d21SAlexey Kardashevskiy object_property_add_bool(obj, "vfio-no-msix-emulation", 3333d2623129SMarkus Armbruster spapr_get_msix_emulation, NULL); 33343ba3d0bcSCédric Le Goater 333564a7b8deSFelipe Franciosi object_property_add_uint64_ptr(obj, "kernel-addr", 3336d2623129SMarkus Armbruster &spapr->kernel_addr, OBJ_PROP_FLAG_READWRITE); 333787262806SAlexey Kardashevskiy object_property_set_description(obj, "kernel-addr", 333887262806SAlexey Kardashevskiy stringify(KERNEL_LOAD_ADDR) 33397eecec7dSMarkus Armbruster " for -kernel is the default"); 334087262806SAlexey Kardashevskiy spapr->kernel_addr = KERNEL_LOAD_ADDR; 33413ba3d0bcSCédric Le Goater /* The machine class defines the default interrupt controller mode */ 33423ba3d0bcSCédric Le Goater spapr->irq = smc->irq; 33433ba3d0bcSCédric Le Goater object_property_add_str(obj, "ic-mode", spapr_get_ic_mode, 3344d2623129SMarkus Armbruster spapr_set_ic_mode); 33453ba3d0bcSCédric Le Goater object_property_set_description(obj, "ic-mode", 33467eecec7dSMarkus Armbruster "Specifies the interrupt controller mode (xics, xive, dual)"); 334727461d69SPrasad J Pandit 334827461d69SPrasad J Pandit object_property_add_str(obj, "host-model", 3349d2623129SMarkus Armbruster spapr_get_host_model, spapr_set_host_model); 335027461d69SPrasad J Pandit object_property_set_description(obj, "host-model", 33517eecec7dSMarkus Armbruster "Host model to advertise in guest device tree"); 335227461d69SPrasad J Pandit object_property_add_str(obj, "host-serial", 3353d2623129SMarkus Armbruster spapr_get_host_serial, spapr_set_host_serial); 335427461d69SPrasad J Pandit object_property_set_description(obj, "host-serial", 33557eecec7dSMarkus Armbruster "Host serial number to advertise in guest device tree"); 335623825581SEduardo Habkost } 335723825581SEduardo Habkost 335887bbdd9cSDavid Gibson static void spapr_machine_finalizefn(Object *obj) 335987bbdd9cSDavid Gibson { 3360ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 336187bbdd9cSDavid Gibson 336287bbdd9cSDavid Gibson g_free(spapr->kvm_type); 336387bbdd9cSDavid Gibson } 336487bbdd9cSDavid Gibson 33651c7ad77eSNicholas Piggin void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg) 336634316482SAlexey Kardashevskiy { 33670e236d34SNicholas Piggin SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 3368b5b7f391SNicholas Piggin PowerPCCPU *cpu = POWERPC_CPU(cs); 3369b5b7f391SNicholas Piggin CPUPPCState *env = &cpu->env; 33700e236d34SNicholas Piggin 337134316482SAlexey Kardashevskiy cpu_synchronize_state(cs); 33720e236d34SNicholas Piggin /* If FWNMI is inactive, addr will be -1, which will deliver to 0x100 */ 33730e236d34SNicholas Piggin if (spapr->fwnmi_system_reset_addr != -1) { 33740e236d34SNicholas Piggin uint64_t rtas_addr, addr; 33750e236d34SNicholas Piggin 33760e236d34SNicholas Piggin /* get rtas addr from fdt */ 33770e236d34SNicholas Piggin rtas_addr = spapr_get_rtas_addr(); 33780e236d34SNicholas Piggin if (!rtas_addr) { 33790e236d34SNicholas Piggin qemu_system_guest_panicked(NULL); 33800e236d34SNicholas Piggin return; 33810e236d34SNicholas Piggin } 33820e236d34SNicholas Piggin 33830e236d34SNicholas Piggin addr = rtas_addr + RTAS_ERROR_LOG_MAX + cs->cpu_index * sizeof(uint64_t)*2; 33840e236d34SNicholas Piggin stq_be_phys(&address_space_memory, addr, env->gpr[3]); 33850e236d34SNicholas Piggin stq_be_phys(&address_space_memory, addr + sizeof(uint64_t), 0); 33860e236d34SNicholas Piggin env->gpr[3] = addr; 33870e236d34SNicholas Piggin } 3388b5b7f391SNicholas Piggin ppc_cpu_do_system_reset(cs); 3389b5b7f391SNicholas Piggin if (spapr->fwnmi_system_reset_addr != -1) { 3390b5b7f391SNicholas Piggin env->nip = spapr->fwnmi_system_reset_addr; 3391b5b7f391SNicholas Piggin } 339234316482SAlexey Kardashevskiy } 339334316482SAlexey Kardashevskiy 339434316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) 339534316482SAlexey Kardashevskiy { 339634316482SAlexey Kardashevskiy CPUState *cs; 339734316482SAlexey Kardashevskiy 339834316482SAlexey Kardashevskiy CPU_FOREACH(cs) { 33991c7ad77eSNicholas Piggin async_run_on_cpu(cs, spapr_do_system_reset_on_cpu, RUN_ON_CPU_NULL); 340034316482SAlexey Kardashevskiy } 340134316482SAlexey Kardashevskiy } 340234316482SAlexey Kardashevskiy 3403ce2918cbSDavid Gibson int spapr_lmb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 340462d38c9bSGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 340562d38c9bSGreg Kurz { 340662d38c9bSGreg Kurz uint64_t addr; 340762d38c9bSGreg Kurz uint32_t node; 340862d38c9bSGreg Kurz 340962d38c9bSGreg Kurz addr = spapr_drc_index(drc) * SPAPR_MEMORY_BLOCK_SIZE; 341062d38c9bSGreg Kurz node = object_property_get_uint(OBJECT(drc->dev), PC_DIMM_NODE_PROP, 341162d38c9bSGreg Kurz &error_abort); 341291335a5eSDavid Gibson *fdt_start_offset = spapr_dt_memory_node(fdt, node, addr, 341362d38c9bSGreg Kurz SPAPR_MEMORY_BLOCK_SIZE); 341462d38c9bSGreg Kurz return 0; 341562d38c9bSGreg Kurz } 341662d38c9bSGreg Kurz 341779b78a6bSMichael Roth static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, 341862d38c9bSGreg Kurz bool dedicated_hp_event_source, Error **errp) 3419c20d332aSBharata B Rao { 3420ce2918cbSDavid Gibson SpaprDrc *drc; 3421c20d332aSBharata B Rao uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; 342262d38c9bSGreg Kurz int i; 342379b78a6bSMichael Roth uint64_t addr = addr_start; 342494fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 3425160bb678SGreg Kurz Error *local_err = NULL; 3426c20d332aSBharata B Rao 3427c20d332aSBharata B Rao for (i = 0; i < nr_lmbs; i++) { 3428fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 3429c20d332aSBharata B Rao addr / SPAPR_MEMORY_BLOCK_SIZE); 3430c20d332aSBharata B Rao g_assert(drc); 3431c20d332aSBharata B Rao 343209d876ceSGreg Kurz spapr_drc_attach(drc, dev, &local_err); 3433160bb678SGreg Kurz if (local_err) { 3434160bb678SGreg Kurz while (addr > addr_start) { 3435160bb678SGreg Kurz addr -= SPAPR_MEMORY_BLOCK_SIZE; 3436160bb678SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 3437160bb678SGreg Kurz addr / SPAPR_MEMORY_BLOCK_SIZE); 3438a8dc47fdSDavid Gibson spapr_drc_detach(drc); 3439160bb678SGreg Kurz } 3440160bb678SGreg Kurz error_propagate(errp, local_err); 3441160bb678SGreg Kurz return; 3442160bb678SGreg Kurz } 344394fd9cbaSLaurent Vivier if (!hotplugged) { 344494fd9cbaSLaurent Vivier spapr_drc_reset(drc); 344594fd9cbaSLaurent Vivier } 3446c20d332aSBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE; 3447c20d332aSBharata B Rao } 34485dd5238cSJianjun Duan /* send hotplug notification to the 34495dd5238cSJianjun Duan * guest only in case of hotplugged memory 34505dd5238cSJianjun Duan */ 345194fd9cbaSLaurent Vivier if (hotplugged) { 345279b78a6bSMichael Roth if (dedicated_hp_event_source) { 3453fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 345479b78a6bSMichael Roth addr_start / SPAPR_MEMORY_BLOCK_SIZE); 345579b78a6bSMichael Roth spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 345679b78a6bSMichael Roth nr_lmbs, 34570b55aa91SDavid Gibson spapr_drc_index(drc)); 345879b78a6bSMichael Roth } else { 345979b78a6bSMichael Roth spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, 346079b78a6bSMichael Roth nr_lmbs); 346179b78a6bSMichael Roth } 3462c20d332aSBharata B Rao } 34635dd5238cSJianjun Duan } 3464c20d332aSBharata B Rao 3465c20d332aSBharata B Rao static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 346681985f3bSDavid Hildenbrand Error **errp) 3467c20d332aSBharata B Rao { 3468c20d332aSBharata B Rao Error *local_err = NULL; 3469ce2918cbSDavid Gibson SpaprMachineState *ms = SPAPR_MACHINE(hotplug_dev); 3470c20d332aSBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 3471ee3a71e3SShivaprasad G Bhat uint64_t size, addr, slot; 3472ee3a71e3SShivaprasad G Bhat bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); 347304790978SThomas Huth 3474946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dev), &error_abort); 3475df587133SThomas Huth 3476fd3416f5SDavid Hildenbrand pc_dimm_plug(dimm, MACHINE(ms), &local_err); 3477c20d332aSBharata B Rao if (local_err) { 3478c20d332aSBharata B Rao goto out; 3479c20d332aSBharata B Rao } 3480c20d332aSBharata B Rao 3481ee3a71e3SShivaprasad G Bhat if (!is_nvdimm) { 34829ed442b8SMarc-André Lureau addr = object_property_get_uint(OBJECT(dimm), 34839ed442b8SMarc-André Lureau PC_DIMM_ADDR_PROP, &local_err); 3484c20d332aSBharata B Rao if (local_err) { 3485160bb678SGreg Kurz goto out_unplug; 3486c20d332aSBharata B Rao } 3487ee3a71e3SShivaprasad G Bhat spapr_add_lmbs(dev, addr, size, 3488ee3a71e3SShivaprasad G Bhat spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), 3489160bb678SGreg Kurz &local_err); 3490ee3a71e3SShivaprasad G Bhat } else { 3491ee3a71e3SShivaprasad G Bhat slot = object_property_get_uint(OBJECT(dimm), 3492ee3a71e3SShivaprasad G Bhat PC_DIMM_SLOT_PROP, &local_err); 3493ee3a71e3SShivaprasad G Bhat if (local_err) { 3494ee3a71e3SShivaprasad G Bhat goto out_unplug; 3495ee3a71e3SShivaprasad G Bhat } 3496ee3a71e3SShivaprasad G Bhat spapr_add_nvdimm(dev, slot, &local_err); 3497ee3a71e3SShivaprasad G Bhat } 3498ee3a71e3SShivaprasad G Bhat 3499160bb678SGreg Kurz if (local_err) { 3500160bb678SGreg Kurz goto out_unplug; 3501160bb678SGreg Kurz } 3502c20d332aSBharata B Rao 3503160bb678SGreg Kurz return; 3504160bb678SGreg Kurz 3505160bb678SGreg Kurz out_unplug: 3506fd3416f5SDavid Hildenbrand pc_dimm_unplug(dimm, MACHINE(ms)); 3507c20d332aSBharata B Rao out: 3508c20d332aSBharata B Rao error_propagate(errp, local_err); 3509c20d332aSBharata B Rao } 3510c20d332aSBharata B Rao 3511c871bc70SLaurent Vivier static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3512c871bc70SLaurent Vivier Error **errp) 3513c871bc70SLaurent Vivier { 3514ce2918cbSDavid Gibson const SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev); 3515ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3516ee3a71e3SShivaprasad G Bhat const MachineClass *mc = MACHINE_CLASS(smc); 3517ee3a71e3SShivaprasad G Bhat bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); 3518c871bc70SLaurent Vivier PCDIMMDevice *dimm = PC_DIMM(dev); 35198f1ffe5bSDavid Hildenbrand Error *local_err = NULL; 352004790978SThomas Huth uint64_t size; 3521123eec65SDavid Gibson Object *memdev; 3522123eec65SDavid Gibson hwaddr pagesize; 3523c871bc70SLaurent Vivier 35244e8a01bdSDavid Hildenbrand if (!smc->dr_lmb_enabled) { 35254e8a01bdSDavid Hildenbrand error_setg(errp, "Memory hotplug not supported for this machine"); 35264e8a01bdSDavid Hildenbrand return; 35274e8a01bdSDavid Hildenbrand } 35284e8a01bdSDavid Hildenbrand 3529ee3a71e3SShivaprasad G Bhat if (is_nvdimm && !mc->nvdimm_supported) { 3530ee3a71e3SShivaprasad G Bhat error_setg(errp, "NVDIMM hotplug not supported for this machine"); 3531ee3a71e3SShivaprasad G Bhat return; 3532ee3a71e3SShivaprasad G Bhat } 3533ee3a71e3SShivaprasad G Bhat 3534946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &local_err); 3535946d6154SDavid Hildenbrand if (local_err) { 3536946d6154SDavid Hildenbrand error_propagate(errp, local_err); 353704790978SThomas Huth return; 353804790978SThomas Huth } 353904790978SThomas Huth 3540ee3a71e3SShivaprasad G Bhat if (!is_nvdimm && size % SPAPR_MEMORY_BLOCK_SIZE) { 3541c871bc70SLaurent Vivier error_setg(errp, "Hotplugged memory size must be a multiple of " 3542ab3dd749SPhilippe Mathieu-Daudé "%" PRIu64 " MB", SPAPR_MEMORY_BLOCK_SIZE / MiB); 3543c871bc70SLaurent Vivier return; 3544ee3a71e3SShivaprasad G Bhat } else if (is_nvdimm) { 3545ee3a71e3SShivaprasad G Bhat spapr_nvdimm_validate_opts(NVDIMM(dev), size, &local_err); 3546ee3a71e3SShivaprasad G Bhat if (local_err) { 3547ee3a71e3SShivaprasad G Bhat error_propagate(errp, local_err); 3548ee3a71e3SShivaprasad G Bhat return; 3549ee3a71e3SShivaprasad G Bhat } 3550c871bc70SLaurent Vivier } 3551c871bc70SLaurent Vivier 3552123eec65SDavid Gibson memdev = object_property_get_link(OBJECT(dimm), PC_DIMM_MEMDEV_PROP, 3553123eec65SDavid Gibson &error_abort); 3554123eec65SDavid Gibson pagesize = host_memory_backend_pagesize(MEMORY_BACKEND(memdev)); 35558f1ffe5bSDavid Hildenbrand spapr_check_pagesize(spapr, pagesize, &local_err); 35568f1ffe5bSDavid Hildenbrand if (local_err) { 35578f1ffe5bSDavid Hildenbrand error_propagate(errp, local_err); 35588f1ffe5bSDavid Hildenbrand return; 35598f1ffe5bSDavid Hildenbrand } 35608f1ffe5bSDavid Hildenbrand 3561fd3416f5SDavid Hildenbrand pc_dimm_pre_plug(dimm, MACHINE(hotplug_dev), NULL, errp); 3562c871bc70SLaurent Vivier } 3563c871bc70SLaurent Vivier 3564ce2918cbSDavid Gibson struct SpaprDimmState { 35650cffce56SDavid Gibson PCDIMMDevice *dimm; 3566cf632463SBharata B Rao uint32_t nr_lmbs; 3567ce2918cbSDavid Gibson QTAILQ_ENTRY(SpaprDimmState) next; 35680cffce56SDavid Gibson }; 35690cffce56SDavid Gibson 3570ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_find(SpaprMachineState *s, 35710cffce56SDavid Gibson PCDIMMDevice *dimm) 35720cffce56SDavid Gibson { 3573ce2918cbSDavid Gibson SpaprDimmState *dimm_state = NULL; 35740cffce56SDavid Gibson 35750cffce56SDavid Gibson QTAILQ_FOREACH(dimm_state, &s->pending_dimm_unplugs, next) { 35760cffce56SDavid Gibson if (dimm_state->dimm == dimm) { 35770cffce56SDavid Gibson break; 35780cffce56SDavid Gibson } 35790cffce56SDavid Gibson } 35800cffce56SDavid Gibson return dimm_state; 35810cffce56SDavid Gibson } 35820cffce56SDavid Gibson 3583ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_add(SpaprMachineState *spapr, 35848d5981c4SBharata B Rao uint32_t nr_lmbs, 35858d5981c4SBharata B Rao PCDIMMDevice *dimm) 35860cffce56SDavid Gibson { 3587ce2918cbSDavid Gibson SpaprDimmState *ds = NULL; 35888d5981c4SBharata B Rao 35898d5981c4SBharata B Rao /* 35908d5981c4SBharata B Rao * If this request is for a DIMM whose removal had failed earlier 35918d5981c4SBharata B Rao * (due to guest's refusal to remove the LMBs), we would have this 35928d5981c4SBharata B Rao * dimm already in the pending_dimm_unplugs list. In that 35938d5981c4SBharata B Rao * case don't add again. 35948d5981c4SBharata B Rao */ 35958d5981c4SBharata B Rao ds = spapr_pending_dimm_unplugs_find(spapr, dimm); 35968d5981c4SBharata B Rao if (!ds) { 3597ce2918cbSDavid Gibson ds = g_malloc0(sizeof(SpaprDimmState)); 35988d5981c4SBharata B Rao ds->nr_lmbs = nr_lmbs; 35998d5981c4SBharata B Rao ds->dimm = dimm; 36008d5981c4SBharata B Rao QTAILQ_INSERT_HEAD(&spapr->pending_dimm_unplugs, ds, next); 36018d5981c4SBharata B Rao } 36028d5981c4SBharata B Rao return ds; 36030cffce56SDavid Gibson } 36040cffce56SDavid Gibson 3605ce2918cbSDavid Gibson static void spapr_pending_dimm_unplugs_remove(SpaprMachineState *spapr, 3606ce2918cbSDavid Gibson SpaprDimmState *dimm_state) 36070cffce56SDavid Gibson { 36080cffce56SDavid Gibson QTAILQ_REMOVE(&spapr->pending_dimm_unplugs, dimm_state, next); 36090cffce56SDavid Gibson g_free(dimm_state); 36100cffce56SDavid Gibson } 3611cf632463SBharata B Rao 3612ce2918cbSDavid Gibson static SpaprDimmState *spapr_recover_pending_dimm_state(SpaprMachineState *ms, 361316ee9980SDaniel Henrique Barboza PCDIMMDevice *dimm) 361416ee9980SDaniel Henrique Barboza { 3615ce2918cbSDavid Gibson SpaprDrc *drc; 3616946d6154SDavid Hildenbrand uint64_t size = memory_device_get_region_size(MEMORY_DEVICE(dimm), 3617946d6154SDavid Hildenbrand &error_abort); 361816ee9980SDaniel Henrique Barboza uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 361916ee9980SDaniel Henrique Barboza uint32_t avail_lmbs = 0; 362016ee9980SDaniel Henrique Barboza uint64_t addr_start, addr; 362116ee9980SDaniel Henrique Barboza int i; 362216ee9980SDaniel Henrique Barboza 362316ee9980SDaniel Henrique Barboza addr_start = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, 362416ee9980SDaniel Henrique Barboza &error_abort); 362516ee9980SDaniel Henrique Barboza 362616ee9980SDaniel Henrique Barboza addr = addr_start; 362716ee9980SDaniel Henrique Barboza for (i = 0; i < nr_lmbs; i++) { 3628fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 362916ee9980SDaniel Henrique Barboza addr / SPAPR_MEMORY_BLOCK_SIZE); 363016ee9980SDaniel Henrique Barboza g_assert(drc); 3631454b580aSDavid Gibson if (drc->dev) { 363216ee9980SDaniel Henrique Barboza avail_lmbs++; 363316ee9980SDaniel Henrique Barboza } 363416ee9980SDaniel Henrique Barboza addr += SPAPR_MEMORY_BLOCK_SIZE; 363516ee9980SDaniel Henrique Barboza } 363616ee9980SDaniel Henrique Barboza 36378d5981c4SBharata B Rao return spapr_pending_dimm_unplugs_add(ms, avail_lmbs, dimm); 363816ee9980SDaniel Henrique Barboza } 363916ee9980SDaniel Henrique Barboza 364031834723SDaniel Henrique Barboza /* Callback to be called during DRC release. */ 364131834723SDaniel Henrique Barboza void spapr_lmb_release(DeviceState *dev) 3642cf632463SBharata B Rao { 36433ec71474SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3644ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl); 3645ce2918cbSDavid Gibson SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); 3646cf632463SBharata B Rao 364716ee9980SDaniel Henrique Barboza /* This information will get lost if a migration occurs 364816ee9980SDaniel Henrique Barboza * during the unplug process. In this case recover it. */ 364916ee9980SDaniel Henrique Barboza if (ds == NULL) { 365016ee9980SDaniel Henrique Barboza ds = spapr_recover_pending_dimm_state(spapr, PC_DIMM(dev)); 36518d5981c4SBharata B Rao g_assert(ds); 3652454b580aSDavid Gibson /* The DRC being examined by the caller at least must be counted */ 3653454b580aSDavid Gibson g_assert(ds->nr_lmbs); 365416ee9980SDaniel Henrique Barboza } 3655454b580aSDavid Gibson 3656454b580aSDavid Gibson if (--ds->nr_lmbs) { 3657cf632463SBharata B Rao return; 3658cf632463SBharata B Rao } 3659cf632463SBharata B Rao 3660cf632463SBharata B Rao /* 3661cf632463SBharata B Rao * Now that all the LMBs have been removed by the guest, call the 36623ec71474SDavid Hildenbrand * unplug handler chain. This can never fail. 3663cf632463SBharata B Rao */ 36643ec71474SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 366507578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 36663ec71474SDavid Hildenbrand } 36673ec71474SDavid Hildenbrand 36683ec71474SDavid Hildenbrand static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 36693ec71474SDavid Hildenbrand { 3670ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3671ce2918cbSDavid Gibson SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); 36723ec71474SDavid Hildenbrand 3673fd3416f5SDavid Hildenbrand pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev)); 3674*981c3dcdSMarkus Armbruster qdev_unrealize(dev); 36752a129767SDaniel Henrique Barboza spapr_pending_dimm_unplugs_remove(spapr, ds); 3676cf632463SBharata B Rao } 3677cf632463SBharata B Rao 3678cf632463SBharata B Rao static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, 3679cf632463SBharata B Rao DeviceState *dev, Error **errp) 3680cf632463SBharata B Rao { 3681ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3682cf632463SBharata B Rao Error *local_err = NULL; 3683cf632463SBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 368404790978SThomas Huth uint32_t nr_lmbs; 368504790978SThomas Huth uint64_t size, addr_start, addr; 36860cffce56SDavid Gibson int i; 3687ce2918cbSDavid Gibson SpaprDrc *drc; 368804790978SThomas Huth 3689ee3a71e3SShivaprasad G Bhat if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { 3690ee3a71e3SShivaprasad G Bhat error_setg(&local_err, 3691ee3a71e3SShivaprasad G Bhat "nvdimm device hot unplug is not supported yet."); 3692ee3a71e3SShivaprasad G Bhat goto out; 3693ee3a71e3SShivaprasad G Bhat } 3694ee3a71e3SShivaprasad G Bhat 3695946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &error_abort); 369604790978SThomas Huth nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 369704790978SThomas Huth 36989ed442b8SMarc-André Lureau addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, 36990cffce56SDavid Gibson &local_err); 3700cf632463SBharata B Rao if (local_err) { 3701cf632463SBharata B Rao goto out; 3702cf632463SBharata B Rao } 3703cf632463SBharata B Rao 37042a129767SDaniel Henrique Barboza /* 37052a129767SDaniel Henrique Barboza * An existing pending dimm state for this DIMM means that there is an 37062a129767SDaniel Henrique Barboza * unplug operation in progress, waiting for the spapr_lmb_release 37072a129767SDaniel Henrique Barboza * callback to complete the job (BQL can't cover that far). In this case, 37082a129767SDaniel Henrique Barboza * bail out to avoid detaching DRCs that were already released. 37092a129767SDaniel Henrique Barboza */ 37102a129767SDaniel Henrique Barboza if (spapr_pending_dimm_unplugs_find(spapr, dimm)) { 37112a129767SDaniel Henrique Barboza error_setg(&local_err, 37122a129767SDaniel Henrique Barboza "Memory unplug already in progress for device %s", 37132a129767SDaniel Henrique Barboza dev->id); 37142a129767SDaniel Henrique Barboza goto out; 37152a129767SDaniel Henrique Barboza } 37162a129767SDaniel Henrique Barboza 37178d5981c4SBharata B Rao spapr_pending_dimm_unplugs_add(spapr, nr_lmbs, dimm); 37180cffce56SDavid Gibson 37190cffce56SDavid Gibson addr = addr_start; 37200cffce56SDavid Gibson for (i = 0; i < nr_lmbs; i++) { 3721fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 37220cffce56SDavid Gibson addr / SPAPR_MEMORY_BLOCK_SIZE); 37230cffce56SDavid Gibson g_assert(drc); 37240cffce56SDavid Gibson 3725a8dc47fdSDavid Gibson spapr_drc_detach(drc); 37260cffce56SDavid Gibson addr += SPAPR_MEMORY_BLOCK_SIZE; 37270cffce56SDavid Gibson } 37280cffce56SDavid Gibson 3729fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 37300cffce56SDavid Gibson addr_start / SPAPR_MEMORY_BLOCK_SIZE); 37310cffce56SDavid Gibson spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 37320b55aa91SDavid Gibson nr_lmbs, spapr_drc_index(drc)); 3733cf632463SBharata B Rao out: 3734cf632463SBharata B Rao error_propagate(errp, local_err); 3735cf632463SBharata B Rao } 3736cf632463SBharata B Rao 3737765d1bddSDavid Gibson /* Callback to be called during DRC release. */ 3738765d1bddSDavid Gibson void spapr_core_release(DeviceState *dev) 3739ff9006ddSIgor Mammedov { 3740a4261be1SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3741a4261be1SDavid Hildenbrand 3742a4261be1SDavid Hildenbrand /* Call the unplug handler chain. This can never fail. */ 3743a4261be1SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 374407578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 3745a4261be1SDavid Hildenbrand } 3746a4261be1SDavid Hildenbrand 3747a4261be1SDavid Hildenbrand static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 3748a4261be1SDavid Hildenbrand { 3749a4261be1SDavid Hildenbrand MachineState *ms = MACHINE(hotplug_dev); 3750ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms); 3751ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3752535455fdSIgor Mammedov CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL); 3753ff9006ddSIgor Mammedov 375446f7afa3SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 3755ce2918cbSDavid Gibson SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); 375646f7afa3SGreg Kurz int i; 375746f7afa3SGreg Kurz 375846f7afa3SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 375994ad93bdSGreg Kurz CPUState *cs = CPU(sc->threads[i]); 376046f7afa3SGreg Kurz 376146f7afa3SGreg Kurz pre_2_10_vmstate_register_dummy_icp(cs->cpu_index); 376246f7afa3SGreg Kurz } 376346f7afa3SGreg Kurz } 376446f7afa3SGreg Kurz 376507572c06SGreg Kurz assert(core_slot); 3766535455fdSIgor Mammedov core_slot->cpu = NULL; 3767*981c3dcdSMarkus Armbruster qdev_unrealize(dev); 3768ff9006ddSIgor Mammedov } 3769ff9006ddSIgor Mammedov 3770115debf2SIgor Mammedov static 3771115debf2SIgor Mammedov void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, 3772ff9006ddSIgor Mammedov Error **errp) 3773ff9006ddSIgor Mammedov { 3774ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3775535455fdSIgor Mammedov int index; 3776ce2918cbSDavid Gibson SpaprDrc *drc; 3777535455fdSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3778ff9006ddSIgor Mammedov 3779535455fdSIgor Mammedov if (!spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index)) { 3780535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 3781535455fdSIgor Mammedov cc->core_id); 3782535455fdSIgor Mammedov return; 3783535455fdSIgor Mammedov } 3784ff9006ddSIgor Mammedov if (index == 0) { 3785ff9006ddSIgor Mammedov error_setg(errp, "Boot CPU core may not be unplugged"); 3786ff9006ddSIgor Mammedov return; 3787ff9006ddSIgor Mammedov } 3788ff9006ddSIgor Mammedov 37895d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 37905d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 3791ff9006ddSIgor Mammedov g_assert(drc); 3792ff9006ddSIgor Mammedov 379347c8c915SGreg Kurz if (!spapr_drc_unplug_requested(drc)) { 3794a8dc47fdSDavid Gibson spapr_drc_detach(drc); 3795ff9006ddSIgor Mammedov spapr_hotplug_req_remove_by_index(drc); 3796ff9006ddSIgor Mammedov } 379747c8c915SGreg Kurz } 3798ff9006ddSIgor Mammedov 3799ce2918cbSDavid Gibson int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 3800345b12b9SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 3801345b12b9SGreg Kurz { 3802ce2918cbSDavid Gibson SpaprCpuCore *core = SPAPR_CPU_CORE(drc->dev); 3803345b12b9SGreg Kurz CPUState *cs = CPU(core->threads[0]); 3804345b12b9SGreg Kurz PowerPCCPU *cpu = POWERPC_CPU(cs); 3805345b12b9SGreg Kurz DeviceClass *dc = DEVICE_GET_CLASS(cs); 3806345b12b9SGreg Kurz int id = spapr_get_vcpu_id(cpu); 3807345b12b9SGreg Kurz char *nodename; 3808345b12b9SGreg Kurz int offset; 3809345b12b9SGreg Kurz 3810345b12b9SGreg Kurz nodename = g_strdup_printf("%s@%x", dc->fw_name, id); 3811345b12b9SGreg Kurz offset = fdt_add_subnode(fdt, 0, nodename); 3812345b12b9SGreg Kurz g_free(nodename); 3813345b12b9SGreg Kurz 381491335a5eSDavid Gibson spapr_dt_cpu(cs, fdt, offset, spapr); 3815345b12b9SGreg Kurz 3816345b12b9SGreg Kurz *fdt_start_offset = offset; 3817345b12b9SGreg Kurz return 0; 3818345b12b9SGreg Kurz } 3819345b12b9SGreg Kurz 3820ff9006ddSIgor Mammedov static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3821ff9006ddSIgor Mammedov Error **errp) 3822ff9006ddSIgor Mammedov { 3823ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3824ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(spapr); 3825ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 3826ce2918cbSDavid Gibson SpaprCpuCore *core = SPAPR_CPU_CORE(OBJECT(dev)); 3827ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3828345b12b9SGreg Kurz CPUState *cs; 3829ce2918cbSDavid Gibson SpaprDrc *drc; 3830ff9006ddSIgor Mammedov Error *local_err = NULL; 3831535455fdSIgor Mammedov CPUArchId *core_slot; 3832535455fdSIgor Mammedov int index; 383394fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 3834b1e81567SGreg Kurz int i; 3835ff9006ddSIgor Mammedov 3836535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 3837535455fdSIgor Mammedov if (!core_slot) { 3838535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 3839535455fdSIgor Mammedov cc->core_id); 3840535455fdSIgor Mammedov return; 3841535455fdSIgor Mammedov } 38425d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 38435d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 3844ff9006ddSIgor Mammedov 3845c5514d0eSIgor Mammedov g_assert(drc || !mc->has_hotpluggable_cpus); 3846ff9006ddSIgor Mammedov 3847e49c63d5SGreg Kurz if (drc) { 384809d876ceSGreg Kurz spapr_drc_attach(drc, dev, &local_err); 3849ff9006ddSIgor Mammedov if (local_err) { 3850ff9006ddSIgor Mammedov error_propagate(errp, local_err); 3851ff9006ddSIgor Mammedov return; 3852ff9006ddSIgor Mammedov } 3853ff9006ddSIgor Mammedov 385494fd9cbaSLaurent Vivier if (hotplugged) { 3855ff9006ddSIgor Mammedov /* 385694fd9cbaSLaurent Vivier * Send hotplug notification interrupt to the guest only 385794fd9cbaSLaurent Vivier * in case of hotplugged CPUs. 3858ff9006ddSIgor Mammedov */ 3859ff9006ddSIgor Mammedov spapr_hotplug_req_add_by_index(drc); 386094fd9cbaSLaurent Vivier } else { 386194fd9cbaSLaurent Vivier spapr_drc_reset(drc); 3862ff9006ddSIgor Mammedov } 386394fd9cbaSLaurent Vivier } 386494fd9cbaSLaurent Vivier 3865535455fdSIgor Mammedov core_slot->cpu = OBJECT(dev); 386646f7afa3SGreg Kurz 386746f7afa3SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 386846f7afa3SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 3869bc877283SGreg Kurz cs = CPU(core->threads[i]); 387046f7afa3SGreg Kurz pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index); 387146f7afa3SGreg Kurz } 387246f7afa3SGreg Kurz } 3873b1e81567SGreg Kurz 3874b1e81567SGreg Kurz /* 3875b1e81567SGreg Kurz * Set compatibility mode to match the boot CPU, which was either set 3876b1e81567SGreg Kurz * by the machine reset code or by CAS. 3877b1e81567SGreg Kurz */ 3878b1e81567SGreg Kurz if (hotplugged) { 3879b1e81567SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 3880b1e81567SGreg Kurz ppc_set_compat(core->threads[i], POWERPC_CPU(first_cpu)->compat_pvr, 3881b1e81567SGreg Kurz &local_err); 3882b1e81567SGreg Kurz if (local_err) { 3883b1e81567SGreg Kurz error_propagate(errp, local_err); 3884b1e81567SGreg Kurz return; 3885b1e81567SGreg Kurz } 3886b1e81567SGreg Kurz } 3887b1e81567SGreg Kurz } 3888ff9006ddSIgor Mammedov } 3889ff9006ddSIgor Mammedov 3890ff9006ddSIgor Mammedov static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3891ff9006ddSIgor Mammedov Error **errp) 3892ff9006ddSIgor Mammedov { 3893ff9006ddSIgor Mammedov MachineState *machine = MACHINE(OBJECT(hotplug_dev)); 3894ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); 3895ff9006ddSIgor Mammedov Error *local_err = NULL; 3896ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 38972e9c10ebSIgor Mammedov const char *base_core_type = spapr_get_cpu_core_type(machine->cpu_type); 3898ff9006ddSIgor Mammedov const char *type = object_get_typename(OBJECT(dev)); 3899535455fdSIgor Mammedov CPUArchId *core_slot; 3900535455fdSIgor Mammedov int index; 3901fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 3902ff9006ddSIgor Mammedov 3903c5514d0eSIgor Mammedov if (dev->hotplugged && !mc->has_hotpluggable_cpus) { 3904ff9006ddSIgor Mammedov error_setg(&local_err, "CPU hotplug not supported for this machine"); 3905ff9006ddSIgor Mammedov goto out; 3906ff9006ddSIgor Mammedov } 3907ff9006ddSIgor Mammedov 3908ff9006ddSIgor Mammedov if (strcmp(base_core_type, type)) { 3909ff9006ddSIgor Mammedov error_setg(&local_err, "CPU core type should be %s", base_core_type); 3910ff9006ddSIgor Mammedov goto out; 3911ff9006ddSIgor Mammedov } 3912ff9006ddSIgor Mammedov 3913ff9006ddSIgor Mammedov if (cc->core_id % smp_threads) { 3914ff9006ddSIgor Mammedov error_setg(&local_err, "invalid core id %d", cc->core_id); 3915ff9006ddSIgor Mammedov goto out; 3916ff9006ddSIgor Mammedov } 3917ff9006ddSIgor Mammedov 3918459264efSDavid Gibson /* 3919459264efSDavid Gibson * In general we should have homogeneous threads-per-core, but old 3920459264efSDavid Gibson * (pre hotplug support) machine types allow the last core to have 3921459264efSDavid Gibson * reduced threads as a compatibility hack for when we allowed 3922459264efSDavid Gibson * total vcpus not a multiple of threads-per-core. 3923459264efSDavid Gibson */ 3924459264efSDavid Gibson if (mc->has_hotpluggable_cpus && (cc->nr_threads != smp_threads)) { 3925df8658deSGreg Kurz error_setg(&local_err, "invalid nr-threads %d, must be %d", 39268149e299SDavid Gibson cc->nr_threads, smp_threads); 3927df8658deSGreg Kurz goto out; 39288149e299SDavid Gibson } 39298149e299SDavid Gibson 3930535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 3931535455fdSIgor Mammedov if (!core_slot) { 3932ff9006ddSIgor Mammedov error_setg(&local_err, "core id %d out of range", cc->core_id); 3933ff9006ddSIgor Mammedov goto out; 3934ff9006ddSIgor Mammedov } 3935ff9006ddSIgor Mammedov 3936535455fdSIgor Mammedov if (core_slot->cpu) { 3937ff9006ddSIgor Mammedov error_setg(&local_err, "core %d already populated", cc->core_id); 3938ff9006ddSIgor Mammedov goto out; 3939ff9006ddSIgor Mammedov } 3940ff9006ddSIgor Mammedov 3941a0ceb640SIgor Mammedov numa_cpu_pre_plug(core_slot, dev, &local_err); 39420b8497f0SIgor Mammedov 3943ff9006ddSIgor Mammedov out: 3944ff9006ddSIgor Mammedov error_propagate(errp, local_err); 3945ff9006ddSIgor Mammedov } 3946ff9006ddSIgor Mammedov 3947ce2918cbSDavid Gibson int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 3948bb2bdd81SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 3949bb2bdd81SGreg Kurz { 3950ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(drc->dev); 3951bb2bdd81SGreg Kurz int intc_phandle; 3952bb2bdd81SGreg Kurz 3953bb2bdd81SGreg Kurz intc_phandle = spapr_irq_get_phandle(spapr, spapr->fdt_blob, errp); 3954bb2bdd81SGreg Kurz if (intc_phandle <= 0) { 3955bb2bdd81SGreg Kurz return -1; 3956bb2bdd81SGreg Kurz } 3957bb2bdd81SGreg Kurz 39588cbe71ecSDavid Gibson if (spapr_dt_phb(spapr, sphb, intc_phandle, fdt, fdt_start_offset)) { 3959bb2bdd81SGreg Kurz error_setg(errp, "unable to create FDT node for PHB %d", sphb->index); 3960bb2bdd81SGreg Kurz return -1; 3961bb2bdd81SGreg Kurz } 3962bb2bdd81SGreg Kurz 3963bb2bdd81SGreg Kurz /* generally SLOF creates these, for hotplug it's up to QEMU */ 3964bb2bdd81SGreg Kurz _FDT(fdt_setprop_string(fdt, *fdt_start_offset, "name", "pci")); 3965bb2bdd81SGreg Kurz 3966bb2bdd81SGreg Kurz return 0; 3967bb2bdd81SGreg Kurz } 3968bb2bdd81SGreg Kurz 3969bb2bdd81SGreg Kurz static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3970bb2bdd81SGreg Kurz Error **errp) 3971bb2bdd81SGreg Kurz { 3972ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3973ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 3974ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 3975bb2bdd81SGreg Kurz const unsigned windows_supported = spapr_phb_windows_supported(sphb); 3976bb2bdd81SGreg Kurz 3977bb2bdd81SGreg Kurz if (dev->hotplugged && !smc->dr_phb_enabled) { 3978bb2bdd81SGreg Kurz error_setg(errp, "PHB hotplug not supported for this machine"); 3979bb2bdd81SGreg Kurz return; 3980bb2bdd81SGreg Kurz } 3981bb2bdd81SGreg Kurz 3982bb2bdd81SGreg Kurz if (sphb->index == (uint32_t)-1) { 3983bb2bdd81SGreg Kurz error_setg(errp, "\"index\" for PAPR PHB is mandatory"); 3984bb2bdd81SGreg Kurz return; 3985bb2bdd81SGreg Kurz } 3986bb2bdd81SGreg Kurz 3987bb2bdd81SGreg Kurz /* 3988bb2bdd81SGreg Kurz * This will check that sphb->index doesn't exceed the maximum number of 3989bb2bdd81SGreg Kurz * PHBs for the current machine type. 3990bb2bdd81SGreg Kurz */ 3991bb2bdd81SGreg Kurz smc->phb_placement(spapr, sphb->index, 3992bb2bdd81SGreg Kurz &sphb->buid, &sphb->io_win_addr, 3993bb2bdd81SGreg Kurz &sphb->mem_win_addr, &sphb->mem64_win_addr, 3994ec132efaSAlexey Kardashevskiy windows_supported, sphb->dma_liobn, 3995ec132efaSAlexey Kardashevskiy &sphb->nv2_gpa_win_addr, &sphb->nv2_atsd_win_addr, 3996ec132efaSAlexey Kardashevskiy errp); 3997bb2bdd81SGreg Kurz } 3998bb2bdd81SGreg Kurz 3999bb2bdd81SGreg Kurz static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 4000bb2bdd81SGreg Kurz Error **errp) 4001bb2bdd81SGreg Kurz { 4002ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 4003ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 4004ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 4005ce2918cbSDavid Gibson SpaprDrc *drc; 4006bb2bdd81SGreg Kurz bool hotplugged = spapr_drc_hotplugged(dev); 4007bb2bdd81SGreg Kurz Error *local_err = NULL; 4008bb2bdd81SGreg Kurz 4009bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) { 4010bb2bdd81SGreg Kurz return; 4011bb2bdd81SGreg Kurz } 4012bb2bdd81SGreg Kurz 4013bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); 4014bb2bdd81SGreg Kurz /* hotplug hooks should check it's enabled before getting this far */ 4015bb2bdd81SGreg Kurz assert(drc); 4016bb2bdd81SGreg Kurz 40178e5c952bSPhilippe Mathieu-Daudé spapr_drc_attach(drc, dev, &local_err); 4018bb2bdd81SGreg Kurz if (local_err) { 4019bb2bdd81SGreg Kurz error_propagate(errp, local_err); 4020bb2bdd81SGreg Kurz return; 4021bb2bdd81SGreg Kurz } 4022bb2bdd81SGreg Kurz 4023bb2bdd81SGreg Kurz if (hotplugged) { 4024bb2bdd81SGreg Kurz spapr_hotplug_req_add_by_index(drc); 4025bb2bdd81SGreg Kurz } else { 4026bb2bdd81SGreg Kurz spapr_drc_reset(drc); 4027bb2bdd81SGreg Kurz } 4028bb2bdd81SGreg Kurz } 4029bb2bdd81SGreg Kurz 4030bb2bdd81SGreg Kurz void spapr_phb_release(DeviceState *dev) 4031bb2bdd81SGreg Kurz { 4032bb2bdd81SGreg Kurz HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 4033bb2bdd81SGreg Kurz 4034bb2bdd81SGreg Kurz hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 403507578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 4036bb2bdd81SGreg Kurz } 4037bb2bdd81SGreg Kurz 4038bb2bdd81SGreg Kurz static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 4039bb2bdd81SGreg Kurz { 4040*981c3dcdSMarkus Armbruster qdev_unrealize(dev); 4041bb2bdd81SGreg Kurz } 4042bb2bdd81SGreg Kurz 4043bb2bdd81SGreg Kurz static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev, 4044bb2bdd81SGreg Kurz DeviceState *dev, Error **errp) 4045bb2bdd81SGreg Kurz { 4046ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 4047ce2918cbSDavid Gibson SpaprDrc *drc; 4048bb2bdd81SGreg Kurz 4049bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); 4050bb2bdd81SGreg Kurz assert(drc); 4051bb2bdd81SGreg Kurz 4052bb2bdd81SGreg Kurz if (!spapr_drc_unplug_requested(drc)) { 4053bb2bdd81SGreg Kurz spapr_drc_detach(drc); 4054bb2bdd81SGreg Kurz spapr_hotplug_req_remove_by_index(drc); 4055bb2bdd81SGreg Kurz } 4056bb2bdd81SGreg Kurz } 4057bb2bdd81SGreg Kurz 40580fb6bd07SMichael Roth static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 40590fb6bd07SMichael Roth Error **errp) 40600fb6bd07SMichael Roth { 40610fb6bd07SMichael Roth SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 40620fb6bd07SMichael Roth SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(dev); 40630fb6bd07SMichael Roth 40640fb6bd07SMichael Roth if (spapr->tpm_proxy != NULL) { 40650fb6bd07SMichael Roth error_setg(errp, "Only one TPM proxy can be specified for this machine"); 40660fb6bd07SMichael Roth return; 40670fb6bd07SMichael Roth } 40680fb6bd07SMichael Roth 40690fb6bd07SMichael Roth spapr->tpm_proxy = tpm_proxy; 40700fb6bd07SMichael Roth } 40710fb6bd07SMichael Roth 40720fb6bd07SMichael Roth static void spapr_tpm_proxy_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 40730fb6bd07SMichael Roth { 40740fb6bd07SMichael Roth SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 40750fb6bd07SMichael Roth 4076*981c3dcdSMarkus Armbruster qdev_unrealize(dev); 40770fb6bd07SMichael Roth object_unparent(OBJECT(dev)); 40780fb6bd07SMichael Roth spapr->tpm_proxy = NULL; 40790fb6bd07SMichael Roth } 40800fb6bd07SMichael Roth 4081c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, 4082c20d332aSBharata B Rao DeviceState *dev, Error **errp) 4083c20d332aSBharata B Rao { 4084c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 408581985f3bSDavid Hildenbrand spapr_memory_plug(hotplug_dev, dev, errp); 4086af81cf32SBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4087af81cf32SBharata B Rao spapr_core_plug(hotplug_dev, dev, errp); 4088bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4089bb2bdd81SGreg Kurz spapr_phb_plug(hotplug_dev, dev, errp); 40900fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 40910fb6bd07SMichael Roth spapr_tpm_proxy_plug(hotplug_dev, dev, errp); 4092c20d332aSBharata B Rao } 4093c20d332aSBharata B Rao } 4094c20d332aSBharata B Rao 409588432f44SDavid Hildenbrand static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, 409688432f44SDavid Hildenbrand DeviceState *dev, Error **errp) 409788432f44SDavid Hildenbrand { 40983ec71474SDavid Hildenbrand if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 40993ec71474SDavid Hildenbrand spapr_memory_unplug(hotplug_dev, dev); 4100a4261be1SDavid Hildenbrand } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4101a4261be1SDavid Hildenbrand spapr_core_unplug(hotplug_dev, dev); 4102bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4103bb2bdd81SGreg Kurz spapr_phb_unplug(hotplug_dev, dev); 41040fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 41050fb6bd07SMichael Roth spapr_tpm_proxy_unplug(hotplug_dev, dev); 41063ec71474SDavid Hildenbrand } 410788432f44SDavid Hildenbrand } 410888432f44SDavid Hildenbrand 4109cf632463SBharata B Rao static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev, 4110cf632463SBharata B Rao DeviceState *dev, Error **errp) 4111cf632463SBharata B Rao { 4112ce2918cbSDavid Gibson SpaprMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev)); 4113c86c1affSDaniel Henrique Barboza MachineClass *mc = MACHINE_GET_CLASS(sms); 4114ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4115cf632463SBharata B Rao 4116cf632463SBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 4117cf632463SBharata B Rao if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) { 4118cf632463SBharata B Rao spapr_memory_unplug_request(hotplug_dev, dev, errp); 4119cf632463SBharata B Rao } else { 4120cf632463SBharata B Rao /* NOTE: this means there is a window after guest reset, prior to 4121cf632463SBharata B Rao * CAS negotiation, where unplug requests will fail due to the 4122cf632463SBharata B Rao * capability not being detected yet. This is a bit different than 4123cf632463SBharata B Rao * the case with PCI unplug, where the events will be queued and 4124cf632463SBharata B Rao * eventually handled by the guest after boot 4125cf632463SBharata B Rao */ 4126cf632463SBharata B Rao error_setg(errp, "Memory hot unplug not supported for this guest"); 4127cf632463SBharata B Rao } 41286f4b5c3eSBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4129c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 41306f4b5c3eSBharata B Rao error_setg(errp, "CPU hot unplug not supported on this machine"); 41316f4b5c3eSBharata B Rao return; 41326f4b5c3eSBharata B Rao } 4133115debf2SIgor Mammedov spapr_core_unplug_request(hotplug_dev, dev, errp); 4134bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4135bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) { 4136bb2bdd81SGreg Kurz error_setg(errp, "PHB hot unplug not supported on this machine"); 4137bb2bdd81SGreg Kurz return; 4138bb2bdd81SGreg Kurz } 4139bb2bdd81SGreg Kurz spapr_phb_unplug_request(hotplug_dev, dev, errp); 41400fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 41410fb6bd07SMichael Roth spapr_tpm_proxy_unplug(hotplug_dev, dev); 4142c20d332aSBharata B Rao } 4143c20d332aSBharata B Rao } 4144c20d332aSBharata B Rao 414594a94e4cSBharata B Rao static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, 414694a94e4cSBharata B Rao DeviceState *dev, Error **errp) 414794a94e4cSBharata B Rao { 4148c871bc70SLaurent Vivier if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 4149c871bc70SLaurent Vivier spapr_memory_pre_plug(hotplug_dev, dev, errp); 4150c871bc70SLaurent Vivier } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 415194a94e4cSBharata B Rao spapr_core_pre_plug(hotplug_dev, dev, errp); 4152bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4153bb2bdd81SGreg Kurz spapr_phb_pre_plug(hotplug_dev, dev, errp); 415494a94e4cSBharata B Rao } 415594a94e4cSBharata B Rao } 415694a94e4cSBharata B Rao 41577ebaf795SBharata B Rao static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine, 4158c20d332aSBharata B Rao DeviceState *dev) 4159c20d332aSBharata B Rao { 416094a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || 4161bb2bdd81SGreg Kurz object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE) || 41620fb6bd07SMichael Roth object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE) || 41630fb6bd07SMichael Roth object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 4164c20d332aSBharata B Rao return HOTPLUG_HANDLER(machine); 4165c20d332aSBharata B Rao } 4166cb600087SDavid Gibson if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { 4167cb600087SDavid Gibson PCIDevice *pcidev = PCI_DEVICE(dev); 4168cb600087SDavid Gibson PCIBus *root = pci_device_root_bus(pcidev); 4169cb600087SDavid Gibson SpaprPhbState *phb = 4170cb600087SDavid Gibson (SpaprPhbState *)object_dynamic_cast(OBJECT(BUS(root)->parent), 4171cb600087SDavid Gibson TYPE_SPAPR_PCI_HOST_BRIDGE); 4172cb600087SDavid Gibson 4173cb600087SDavid Gibson if (phb) { 4174cb600087SDavid Gibson return HOTPLUG_HANDLER(phb); 4175cb600087SDavid Gibson } 4176cb600087SDavid Gibson } 4177c20d332aSBharata B Rao return NULL; 4178c20d332aSBharata B Rao } 4179c20d332aSBharata B Rao 4180ea089eebSIgor Mammedov static CpuInstanceProperties 4181ea089eebSIgor Mammedov spapr_cpu_index_to_props(MachineState *machine, unsigned cpu_index) 418220bb648dSDavid Gibson { 4183ea089eebSIgor Mammedov CPUArchId *core_slot; 4184ea089eebSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 4185ea089eebSIgor Mammedov 4186ea089eebSIgor Mammedov /* make sure possible_cpu are intialized */ 4187ea089eebSIgor Mammedov mc->possible_cpu_arch_ids(machine); 4188ea089eebSIgor Mammedov /* get CPU core slot containing thread that matches cpu_index */ 4189ea089eebSIgor Mammedov core_slot = spapr_find_cpu_slot(machine, cpu_index, NULL); 4190ea089eebSIgor Mammedov assert(core_slot); 4191ea089eebSIgor Mammedov return core_slot->props; 419220bb648dSDavid Gibson } 419320bb648dSDavid Gibson 419479e07936SIgor Mammedov static int64_t spapr_get_default_cpu_node_id(const MachineState *ms, int idx) 419579e07936SIgor Mammedov { 4196aa570207STao Xu return idx / ms->smp.cores % ms->numa_state->num_nodes; 419779e07936SIgor Mammedov } 419879e07936SIgor Mammedov 4199535455fdSIgor Mammedov static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine) 4200535455fdSIgor Mammedov { 4201535455fdSIgor Mammedov int i; 4202fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 4203fe6b6346SLike Xu unsigned int smp_cpus = machine->smp.cpus; 4204d342eb76SIgor Mammedov const char *core_type; 4205fe6b6346SLike Xu int spapr_max_cores = machine->smp.max_cpus / smp_threads; 4206535455fdSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 4207535455fdSIgor Mammedov 4208c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 4209535455fdSIgor Mammedov spapr_max_cores = QEMU_ALIGN_UP(smp_cpus, smp_threads) / smp_threads; 4210535455fdSIgor Mammedov } 4211535455fdSIgor Mammedov if (machine->possible_cpus) { 4212535455fdSIgor Mammedov assert(machine->possible_cpus->len == spapr_max_cores); 4213535455fdSIgor Mammedov return machine->possible_cpus; 4214535455fdSIgor Mammedov } 4215535455fdSIgor Mammedov 4216d342eb76SIgor Mammedov core_type = spapr_get_cpu_core_type(machine->cpu_type); 4217d342eb76SIgor Mammedov if (!core_type) { 4218d342eb76SIgor Mammedov error_report("Unable to find sPAPR CPU Core definition"); 4219d342eb76SIgor Mammedov exit(1); 4220d342eb76SIgor Mammedov } 4221d342eb76SIgor Mammedov 4222535455fdSIgor Mammedov machine->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + 4223535455fdSIgor Mammedov sizeof(CPUArchId) * spapr_max_cores); 4224535455fdSIgor Mammedov machine->possible_cpus->len = spapr_max_cores; 4225535455fdSIgor Mammedov for (i = 0; i < machine->possible_cpus->len; i++) { 4226535455fdSIgor Mammedov int core_id = i * smp_threads; 4227535455fdSIgor Mammedov 4228d342eb76SIgor Mammedov machine->possible_cpus->cpus[i].type = core_type; 4229f2d672c2SIgor Mammedov machine->possible_cpus->cpus[i].vcpus_count = smp_threads; 4230535455fdSIgor Mammedov machine->possible_cpus->cpus[i].arch_id = core_id; 4231535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.has_core_id = true; 4232535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.core_id = core_id; 4233535455fdSIgor Mammedov } 4234535455fdSIgor Mammedov return machine->possible_cpus; 4235535455fdSIgor Mammedov } 4236535455fdSIgor Mammedov 4237ce2918cbSDavid Gibson static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index, 4238daa23699SDavid Gibson uint64_t *buid, hwaddr *pio, 4239daa23699SDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 4240ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4241ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 42426737d9adSDavid Gibson { 4243357d1e3bSDavid Gibson /* 4244357d1e3bSDavid Gibson * New-style PHB window placement. 4245357d1e3bSDavid Gibson * 4246357d1e3bSDavid Gibson * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window 4247357d1e3bSDavid Gibson * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO 4248357d1e3bSDavid Gibson * windows. 4249357d1e3bSDavid Gibson * 4250357d1e3bSDavid Gibson * Some guest kernels can't work with MMIO windows above 1<<46 4251357d1e3bSDavid Gibson * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB 4252357d1e3bSDavid Gibson * 4253357d1e3bSDavid Gibson * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each 4254357d1e3bSDavid Gibson * PHB stacked together. (32TiB+2GiB)..(32TiB+64GiB) contains the 4255357d1e3bSDavid Gibson * 2GiB 32-bit MMIO windows for each PHB. Then 33..64TiB has the 4256357d1e3bSDavid Gibson * 1TiB 64-bit MMIO windows for each PHB. 4257357d1e3bSDavid Gibson */ 42586737d9adSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 42596737d9adSDavid Gibson int i; 42606737d9adSDavid Gibson 4261357d1e3bSDavid Gibson /* Sanity check natural alignments */ 4262357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 4263357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 4264357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0); 4265357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0); 4266357d1e3bSDavid Gibson /* Sanity check bounds */ 426725e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_IO_WIN_SIZE) > 426825e6a118SMichael S. Tsirkin SPAPR_PCI_MEM32_WIN_SIZE); 426925e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_MEM32_WIN_SIZE) > 427025e6a118SMichael S. Tsirkin SPAPR_PCI_MEM64_WIN_SIZE); 42712efff1c0SDavid Gibson 427225e6a118SMichael S. Tsirkin if (index >= SPAPR_MAX_PHBS) { 427325e6a118SMichael S. Tsirkin error_setg(errp, "\"index\" for PAPR PHB is too large (max %llu)", 427425e6a118SMichael S. Tsirkin SPAPR_MAX_PHBS - 1); 42756737d9adSDavid Gibson return; 42766737d9adSDavid Gibson } 42776737d9adSDavid Gibson 42786737d9adSDavid Gibson *buid = base_buid + index; 42796737d9adSDavid Gibson for (i = 0; i < n_dma; ++i) { 42806737d9adSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 42816737d9adSDavid Gibson } 42826737d9adSDavid Gibson 4283357d1e3bSDavid Gibson *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE; 4284357d1e3bSDavid Gibson *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE; 4285357d1e3bSDavid Gibson *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE; 4286ec132efaSAlexey Kardashevskiy 4287ec132efaSAlexey Kardashevskiy *nv2gpa = SPAPR_PCI_NV2RAM64_WIN_BASE + index * SPAPR_PCI_NV2RAM64_WIN_SIZE; 4288ec132efaSAlexey Kardashevskiy *nv2atsd = SPAPR_PCI_NV2ATSD_WIN_BASE + index * SPAPR_PCI_NV2ATSD_WIN_SIZE; 42896737d9adSDavid Gibson } 42906737d9adSDavid Gibson 42917844e12bSCédric Le Goater static ICSState *spapr_ics_get(XICSFabric *dev, int irq) 42927844e12bSCédric Le Goater { 4293ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(dev); 42947844e12bSCédric Le Goater 42957844e12bSCédric Le Goater return ics_valid_irq(spapr->ics, irq) ? spapr->ics : NULL; 42967844e12bSCédric Le Goater } 42977844e12bSCédric Le Goater 42987844e12bSCédric Le Goater static void spapr_ics_resend(XICSFabric *dev) 42997844e12bSCédric Le Goater { 4300ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(dev); 43017844e12bSCédric Le Goater 43027844e12bSCédric Le Goater ics_resend(spapr->ics); 43037844e12bSCédric Le Goater } 43047844e12bSCédric Le Goater 430581210c20SSam Bobroff static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id) 4306b2fc59aaSCédric Le Goater { 43072e886fb3SSam Bobroff PowerPCCPU *cpu = spapr_find_cpu(vcpu_id); 4308b2fc59aaSCédric Le Goater 4309a28b9a5aSCédric Le Goater return cpu ? spapr_cpu_state(cpu)->icp : NULL; 4310b2fc59aaSCédric Le Goater } 4311b2fc59aaSCédric Le Goater 43126449da45SCédric Le Goater static void spapr_pic_print_info(InterruptStatsProvider *obj, 43136449da45SCédric Le Goater Monitor *mon) 43146449da45SCédric Le Goater { 4315ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 43166449da45SCédric Le Goater 4317328d8eb2SDavid Gibson spapr_irq_print_info(spapr, mon); 4318f041d6afSGreg Kurz monitor_printf(mon, "irqchip: %s\n", 4319f041d6afSGreg Kurz kvm_irqchip_in_kernel() ? "in-kernel" : "emulated"); 43206449da45SCédric Le Goater } 43216449da45SCédric Le Goater 4322baa45b17SCédric Le Goater /* 4323baa45b17SCédric Le Goater * This is a XIVE only operation 4324baa45b17SCédric Le Goater */ 4325932de7aeSCédric Le Goater static int spapr_match_nvt(XiveFabric *xfb, uint8_t format, 4326932de7aeSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 4327932de7aeSCédric Le Goater bool cam_ignore, uint8_t priority, 4328932de7aeSCédric Le Goater uint32_t logic_serv, XiveTCTXMatch *match) 4329932de7aeSCédric Le Goater { 4330932de7aeSCédric Le Goater SpaprMachineState *spapr = SPAPR_MACHINE(xfb); 4331baa45b17SCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(spapr->active_intc); 4332932de7aeSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 4333932de7aeSCédric Le Goater int count; 4334932de7aeSCédric Le Goater 4335932de7aeSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 4336932de7aeSCédric Le Goater priority, logic_serv, match); 4337932de7aeSCédric Le Goater if (count < 0) { 4338932de7aeSCédric Le Goater return count; 4339932de7aeSCédric Le Goater } 4340932de7aeSCédric Le Goater 4341932de7aeSCédric Le Goater /* 4342932de7aeSCédric Le Goater * When we implement the save and restore of the thread interrupt 4343932de7aeSCédric Le Goater * contexts in the enter/exit CPU handlers of the machine and the 4344932de7aeSCédric Le Goater * escalations in QEMU, we should be able to handle non dispatched 4345932de7aeSCédric Le Goater * vCPUs. 4346932de7aeSCédric Le Goater * 4347932de7aeSCédric Le Goater * Until this is done, the sPAPR machine should find at least one 4348932de7aeSCédric Le Goater * matching context always. 4349932de7aeSCédric Le Goater */ 4350932de7aeSCédric Le Goater if (count == 0) { 4351932de7aeSCédric Le Goater qemu_log_mask(LOG_GUEST_ERROR, "XIVE: NVT %x/%x is not dispatched\n", 4352932de7aeSCédric Le Goater nvt_blk, nvt_idx); 4353932de7aeSCédric Le Goater } 4354932de7aeSCédric Le Goater 4355932de7aeSCédric Le Goater return count; 4356932de7aeSCédric Le Goater } 4357932de7aeSCédric Le Goater 435814bb4486SGreg Kurz int spapr_get_vcpu_id(PowerPCCPU *cpu) 43592e886fb3SSam Bobroff { 4360b1a568c1SGreg Kurz return cpu->vcpu_id; 43612e886fb3SSam Bobroff } 43622e886fb3SSam Bobroff 4363648edb64SGreg Kurz void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp) 4364648edb64SGreg Kurz { 4365ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 4366fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 4367648edb64SGreg Kurz int vcpu_id; 4368648edb64SGreg Kurz 43695d0fb150SGreg Kurz vcpu_id = spapr_vcpu_id(spapr, cpu_index); 4370648edb64SGreg Kurz 4371648edb64SGreg Kurz if (kvm_enabled() && !kvm_vcpu_id_is_valid(vcpu_id)) { 4372648edb64SGreg Kurz error_setg(errp, "Can't create CPU with id %d in KVM", vcpu_id); 4373648edb64SGreg Kurz error_append_hint(errp, "Adjust the number of cpus to %d " 4374648edb64SGreg Kurz "or try to raise the number of threads per core\n", 4375fe6b6346SLike Xu vcpu_id * ms->smp.threads / spapr->vsmt); 4376648edb64SGreg Kurz return; 4377648edb64SGreg Kurz } 4378648edb64SGreg Kurz 4379648edb64SGreg Kurz cpu->vcpu_id = vcpu_id; 4380648edb64SGreg Kurz } 4381648edb64SGreg Kurz 43822e886fb3SSam Bobroff PowerPCCPU *spapr_find_cpu(int vcpu_id) 43832e886fb3SSam Bobroff { 43842e886fb3SSam Bobroff CPUState *cs; 43852e886fb3SSam Bobroff 43862e886fb3SSam Bobroff CPU_FOREACH(cs) { 43872e886fb3SSam Bobroff PowerPCCPU *cpu = POWERPC_CPU(cs); 43882e886fb3SSam Bobroff 438914bb4486SGreg Kurz if (spapr_get_vcpu_id(cpu) == vcpu_id) { 43902e886fb3SSam Bobroff return cpu; 43912e886fb3SSam Bobroff } 43922e886fb3SSam Bobroff } 43932e886fb3SSam Bobroff 43942e886fb3SSam Bobroff return NULL; 43952e886fb3SSam Bobroff } 43962e886fb3SSam Bobroff 439703ef074cSNicholas Piggin static void spapr_cpu_exec_enter(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) 439803ef074cSNicholas Piggin { 439903ef074cSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 440003ef074cSNicholas Piggin 440103ef074cSNicholas Piggin /* These are only called by TCG, KVM maintains dispatch state */ 440203ef074cSNicholas Piggin 44033a6e6224SNicholas Piggin spapr_cpu->prod = false; 440403ef074cSNicholas Piggin if (spapr_cpu->vpa_addr) { 440503ef074cSNicholas Piggin CPUState *cs = CPU(cpu); 440603ef074cSNicholas Piggin uint32_t dispatch; 440703ef074cSNicholas Piggin 440803ef074cSNicholas Piggin dispatch = ldl_be_phys(cs->as, 440903ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER); 441003ef074cSNicholas Piggin dispatch++; 441103ef074cSNicholas Piggin if ((dispatch & 1) != 0) { 441203ef074cSNicholas Piggin qemu_log_mask(LOG_GUEST_ERROR, 441303ef074cSNicholas Piggin "VPA: incorrect dispatch counter value for " 441403ef074cSNicholas Piggin "dispatched partition %u, correcting.\n", dispatch); 441503ef074cSNicholas Piggin dispatch++; 441603ef074cSNicholas Piggin } 441703ef074cSNicholas Piggin stl_be_phys(cs->as, 441803ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch); 441903ef074cSNicholas Piggin } 442003ef074cSNicholas Piggin } 442103ef074cSNicholas Piggin 442203ef074cSNicholas Piggin static void spapr_cpu_exec_exit(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) 442303ef074cSNicholas Piggin { 442403ef074cSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 442503ef074cSNicholas Piggin 442603ef074cSNicholas Piggin if (spapr_cpu->vpa_addr) { 442703ef074cSNicholas Piggin CPUState *cs = CPU(cpu); 442803ef074cSNicholas Piggin uint32_t dispatch; 442903ef074cSNicholas Piggin 443003ef074cSNicholas Piggin dispatch = ldl_be_phys(cs->as, 443103ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER); 443203ef074cSNicholas Piggin dispatch++; 443303ef074cSNicholas Piggin if ((dispatch & 1) != 1) { 443403ef074cSNicholas Piggin qemu_log_mask(LOG_GUEST_ERROR, 443503ef074cSNicholas Piggin "VPA: incorrect dispatch counter value for " 443603ef074cSNicholas Piggin "preempted partition %u, correcting.\n", dispatch); 443703ef074cSNicholas Piggin dispatch++; 443803ef074cSNicholas Piggin } 443903ef074cSNicholas Piggin stl_be_phys(cs->as, 444003ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch); 444103ef074cSNicholas Piggin } 444203ef074cSNicholas Piggin } 444303ef074cSNicholas Piggin 444429ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data) 444553018216SPaolo Bonzini { 444629ee3247SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 4447ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(oc); 444871461b0fSAlexey Kardashevskiy FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); 444934316482SAlexey Kardashevskiy NMIClass *nc = NMI_CLASS(oc); 4450c20d332aSBharata B Rao HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); 44511d1be34dSDavid Gibson PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc); 44527844e12bSCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 44536449da45SCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 4454932de7aeSCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 445529ee3247SAlexey Kardashevskiy 44560eb9054cSDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant)"; 4457907aac2fSMark Cave-Ayland mc->ignore_boot_device_suffixes = true; 4458fc9f38c3SDavid Gibson 4459fc9f38c3SDavid Gibson /* 4460fc9f38c3SDavid Gibson * We set up the default / latest behaviour here. The class_init 4461fc9f38c3SDavid Gibson * functions for the specific versioned machine types can override 4462fc9f38c3SDavid Gibson * these details for backwards compatibility 4463fc9f38c3SDavid Gibson */ 4464bcb5ce08SDavid Gibson mc->init = spapr_machine_init; 4465bcb5ce08SDavid Gibson mc->reset = spapr_machine_reset; 4466958db90cSMarcel Apfelbaum mc->block_default_type = IF_SCSI; 44676244bb7eSGreg Kurz mc->max_cpus = 1024; 4468958db90cSMarcel Apfelbaum mc->no_parallel = 1; 44695b2128d2SAlexander Graf mc->default_boot_order = ""; 4470d23b6caaSPhilippe Mathieu-Daudé mc->default_ram_size = 512 * MiB; 4471ab74e543SIgor Mammedov mc->default_ram_id = "ppc_spapr.ram"; 447229f9cef3SSebastian Bauer mc->default_display = "std"; 4473958db90cSMarcel Apfelbaum mc->kvm_type = spapr_kvm_type; 44747da79a16SEduardo Habkost machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SPAPR_PCI_HOST_BRIDGE); 4475e4024630SLaurent Vivier mc->pci_allow_0_address = true; 4476debbdc00SIgor Mammedov assert(!mc->get_hotplug_handler); 44777ebaf795SBharata B Rao mc->get_hotplug_handler = spapr_get_hotplug_handler; 447894a94e4cSBharata B Rao hc->pre_plug = spapr_machine_device_pre_plug; 4479c20d332aSBharata B Rao hc->plug = spapr_machine_device_plug; 4480ea089eebSIgor Mammedov mc->cpu_index_to_instance_props = spapr_cpu_index_to_props; 448179e07936SIgor Mammedov mc->get_default_cpu_node_id = spapr_get_default_cpu_node_id; 4482535455fdSIgor Mammedov mc->possible_cpu_arch_ids = spapr_possible_cpu_arch_ids; 4483cf632463SBharata B Rao hc->unplug_request = spapr_machine_device_unplug_request; 448488432f44SDavid Hildenbrand hc->unplug = spapr_machine_device_unplug; 448500b4fbe2SMarcel Apfelbaum 4486fc9f38c3SDavid Gibson smc->dr_lmb_enabled = true; 4487fea35ca4SAlexey Kardashevskiy smc->update_dt_enabled = true; 448834a6b015SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 4489c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = true; 4490ee3a71e3SShivaprasad G Bhat mc->nvdimm_supported = true; 449152b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED; 449271461b0fSAlexey Kardashevskiy fwc->get_dev_path = spapr_get_fw_dev_path; 449334316482SAlexey Kardashevskiy nc->nmi_monitor_handler = spapr_nmi; 44946737d9adSDavid Gibson smc->phb_placement = spapr_phb_placement; 44951d1be34dSDavid Gibson vhc->hypercall = emulate_spapr_hypercall; 4496e57ca75cSDavid Gibson vhc->hpt_mask = spapr_hpt_mask; 4497e57ca75cSDavid Gibson vhc->map_hptes = spapr_map_hptes; 4498e57ca75cSDavid Gibson vhc->unmap_hptes = spapr_unmap_hptes; 4499a2dd4e83SBenjamin Herrenschmidt vhc->hpte_set_c = spapr_hpte_set_c; 4500a2dd4e83SBenjamin Herrenschmidt vhc->hpte_set_r = spapr_hpte_set_r; 450179825f4dSBenjamin Herrenschmidt vhc->get_pate = spapr_get_pate; 45021ec26c75SGreg Kurz vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr; 450303ef074cSNicholas Piggin vhc->cpu_exec_enter = spapr_cpu_exec_enter; 450403ef074cSNicholas Piggin vhc->cpu_exec_exit = spapr_cpu_exec_exit; 45057844e12bSCédric Le Goater xic->ics_get = spapr_ics_get; 45067844e12bSCédric Le Goater xic->ics_resend = spapr_ics_resend; 4507b2fc59aaSCédric Le Goater xic->icp_get = spapr_icp_get; 45086449da45SCédric Le Goater ispc->print_info = spapr_pic_print_info; 450955641213SLaurent Vivier /* Force NUMA node memory size to be a multiple of 451055641213SLaurent Vivier * SPAPR_MEMORY_BLOCK_SIZE (256M) since that's the granularity 451155641213SLaurent Vivier * in which LMBs are represented and hot-added 451255641213SLaurent Vivier */ 451355641213SLaurent Vivier mc->numa_mem_align_shift = 28; 4514cd5ff833SIgor Mammedov mc->numa_mem_supported = true; 45150533ef5fSTao Xu mc->auto_enable_numa = 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; 452637965dfeSDavid Gibson smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_ON; 45278af7e1feSNicholas Piggin smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_ON; 452840c2281cSMarkus Armbruster spapr_caps_add_properties(smc); 4529bd94bc06SCédric Le Goater smc->irq = &spapr_irq_dual; 4530dae5e39aSMichael Roth smc->dr_phb_enabled = true; 45316c3829a2SAlexey Kardashevskiy smc->linux_pci_probe = true; 453229cb4187SGreg Kurz smc->smp_threads_vsmt = true; 453354255c1fSDavid Gibson smc->nr_xirqs = SPAPR_NR_XIRQS; 4534932de7aeSCédric Le Goater xfc->match_nvt = spapr_match_nvt; 453553018216SPaolo Bonzini } 453653018216SPaolo Bonzini 453729ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = { 453829ee3247SAlexey Kardashevskiy .name = TYPE_SPAPR_MACHINE, 453929ee3247SAlexey Kardashevskiy .parent = TYPE_MACHINE, 45404aee7362SDavid Gibson .abstract = true, 4541ce2918cbSDavid Gibson .instance_size = sizeof(SpaprMachineState), 4542bcb5ce08SDavid Gibson .instance_init = spapr_instance_init, 454387bbdd9cSDavid Gibson .instance_finalize = spapr_machine_finalizefn, 4544ce2918cbSDavid Gibson .class_size = sizeof(SpaprMachineClass), 454529ee3247SAlexey Kardashevskiy .class_init = spapr_machine_class_init, 454671461b0fSAlexey Kardashevskiy .interfaces = (InterfaceInfo[]) { 454771461b0fSAlexey Kardashevskiy { TYPE_FW_PATH_PROVIDER }, 454834316482SAlexey Kardashevskiy { TYPE_NMI }, 4549c20d332aSBharata B Rao { TYPE_HOTPLUG_HANDLER }, 45501d1be34dSDavid Gibson { TYPE_PPC_VIRTUAL_HYPERVISOR }, 45517844e12bSCédric Le Goater { TYPE_XICS_FABRIC }, 45526449da45SCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 4553932de7aeSCédric Le Goater { TYPE_XIVE_FABRIC }, 455471461b0fSAlexey Kardashevskiy { } 455571461b0fSAlexey Kardashevskiy }, 455629ee3247SAlexey Kardashevskiy }; 455729ee3247SAlexey Kardashevskiy 4558a7849268SMichael S. Tsirkin static void spapr_machine_latest_class_options(MachineClass *mc) 4559a7849268SMichael S. Tsirkin { 4560a7849268SMichael S. Tsirkin mc->alias = "pseries"; 4561ea0ac7f6SPhilippe Mathieu-Daudé mc->is_default = true; 4562a7849268SMichael S. Tsirkin } 4563a7849268SMichael S. Tsirkin 4564fccbc785SDavid Gibson #define DEFINE_SPAPR_MACHINE(suffix, verstr, latest) \ 45655013c547SDavid Gibson static void spapr_machine_##suffix##_class_init(ObjectClass *oc, \ 45665013c547SDavid Gibson void *data) \ 45675013c547SDavid Gibson { \ 45685013c547SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); \ 45695013c547SDavid Gibson spapr_machine_##suffix##_class_options(mc); \ 4570fccbc785SDavid Gibson if (latest) { \ 4571a7849268SMichael S. Tsirkin spapr_machine_latest_class_options(mc); \ 4572fccbc785SDavid Gibson } \ 45735013c547SDavid Gibson } \ 45745013c547SDavid Gibson static const TypeInfo spapr_machine_##suffix##_info = { \ 45755013c547SDavid Gibson .name = MACHINE_TYPE_NAME("pseries-" verstr), \ 45765013c547SDavid Gibson .parent = TYPE_SPAPR_MACHINE, \ 45775013c547SDavid Gibson .class_init = spapr_machine_##suffix##_class_init, \ 45785013c547SDavid Gibson }; \ 45795013c547SDavid Gibson static void spapr_machine_register_##suffix(void) \ 45805013c547SDavid Gibson { \ 45815013c547SDavid Gibson type_register(&spapr_machine_##suffix##_info); \ 45825013c547SDavid Gibson } \ 45830e6aac87SEduardo Habkost type_init(spapr_machine_register_##suffix) 45845013c547SDavid Gibson 45851c5f29bbSDavid Gibson /* 4586541aaa1dSCornelia Huck * pseries-5.1 45873eb74d20SCornelia Huck */ 4588541aaa1dSCornelia Huck static void spapr_machine_5_1_class_options(MachineClass *mc) 45893eb74d20SCornelia Huck { 45903eb74d20SCornelia Huck /* Defaults for the latest behaviour inherited from the base class */ 45913eb74d20SCornelia Huck } 45923eb74d20SCornelia Huck 4593541aaa1dSCornelia Huck DEFINE_SPAPR_MACHINE(5_1, "5.1", true); 4594541aaa1dSCornelia Huck 4595541aaa1dSCornelia Huck /* 4596541aaa1dSCornelia Huck * pseries-5.0 4597541aaa1dSCornelia Huck */ 4598541aaa1dSCornelia Huck static void spapr_machine_5_0_class_options(MachineClass *mc) 4599541aaa1dSCornelia Huck { 4600541aaa1dSCornelia Huck spapr_machine_5_1_class_options(mc); 4601541aaa1dSCornelia Huck compat_props_add(mc->compat_props, hw_compat_5_0, hw_compat_5_0_len); 4602541aaa1dSCornelia Huck } 4603541aaa1dSCornelia Huck 4604541aaa1dSCornelia Huck DEFINE_SPAPR_MACHINE(5_0, "5.0", false); 46053eb74d20SCornelia Huck 46063eb74d20SCornelia Huck /* 46079aec2e52SCornelia Huck * pseries-4.2 4608e2676b16SGreg Kurz */ 46099aec2e52SCornelia Huck static void spapr_machine_4_2_class_options(MachineClass *mc) 4610e2676b16SGreg Kurz { 461137965dfeSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 461237965dfeSDavid Gibson 46133eb74d20SCornelia Huck spapr_machine_5_0_class_options(mc); 46145f258577SEvgeny Yakovlev compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len); 461537965dfeSDavid Gibson smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF; 46168af7e1feSNicholas Piggin smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_OFF; 46171052ab67SDavid Gibson smc->rma_limit = 16 * GiB; 4618ee3a71e3SShivaprasad G Bhat mc->nvdimm_supported = false; 4619e2676b16SGreg Kurz } 4620e2676b16SGreg Kurz 46213eb74d20SCornelia Huck DEFINE_SPAPR_MACHINE(4_2, "4.2", false); 46229aec2e52SCornelia Huck 46239aec2e52SCornelia Huck /* 46249aec2e52SCornelia Huck * pseries-4.1 46259aec2e52SCornelia Huck */ 46269aec2e52SCornelia Huck static void spapr_machine_4_1_class_options(MachineClass *mc) 46279aec2e52SCornelia Huck { 46286c3829a2SAlexey Kardashevskiy SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4629d15d4ad6SDavid Gibson static GlobalProperty compat[] = { 4630d15d4ad6SDavid Gibson /* Only allow 4kiB and 64kiB IOMMU pagesizes */ 4631d15d4ad6SDavid Gibson { TYPE_SPAPR_PCI_HOST_BRIDGE, "pgsz", "0x11000" }, 4632d15d4ad6SDavid Gibson }; 4633d15d4ad6SDavid Gibson 46349aec2e52SCornelia Huck spapr_machine_4_2_class_options(mc); 46356c3829a2SAlexey Kardashevskiy smc->linux_pci_probe = false; 463629cb4187SGreg Kurz smc->smp_threads_vsmt = false; 46379aec2e52SCornelia Huck compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len); 4638d15d4ad6SDavid Gibson compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 46399aec2e52SCornelia Huck } 46409aec2e52SCornelia Huck 46419aec2e52SCornelia Huck DEFINE_SPAPR_MACHINE(4_1, "4.1", false); 46429bf2650bSCornelia Huck 46439bf2650bSCornelia Huck /* 46449bf2650bSCornelia Huck * pseries-4.0 46459bf2650bSCornelia Huck */ 4646eb3cba82SDavid Gibson static void phb_placement_4_0(SpaprMachineState *spapr, uint32_t index, 4647ec132efaSAlexey Kardashevskiy uint64_t *buid, hwaddr *pio, 4648ec132efaSAlexey Kardashevskiy hwaddr *mmio32, hwaddr *mmio64, 4649ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4650ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 4651ec132efaSAlexey Kardashevskiy { 4652ec132efaSAlexey Kardashevskiy spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma, liobns, 4653ec132efaSAlexey Kardashevskiy nv2gpa, nv2atsd, errp); 4654ec132efaSAlexey Kardashevskiy *nv2gpa = 0; 4655ec132efaSAlexey Kardashevskiy *nv2atsd = 0; 4656ec132efaSAlexey Kardashevskiy } 4657ec132efaSAlexey Kardashevskiy 4658eb3cba82SDavid Gibson static void spapr_machine_4_0_class_options(MachineClass *mc) 4659eb3cba82SDavid Gibson { 4660eb3cba82SDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4661eb3cba82SDavid Gibson 4662eb3cba82SDavid Gibson spapr_machine_4_1_class_options(mc); 4663eb3cba82SDavid Gibson compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); 4664eb3cba82SDavid Gibson smc->phb_placement = phb_placement_4_0; 4665bd94bc06SCédric Le Goater smc->irq = &spapr_irq_xics; 46663725ef1aSGreg Kurz smc->pre_4_1_migration = true; 4667eb3cba82SDavid Gibson } 4668eb3cba82SDavid Gibson 4669eb3cba82SDavid Gibson DEFINE_SPAPR_MACHINE(4_0, "4.0", false); 4670eb3cba82SDavid Gibson 4671eb3cba82SDavid Gibson /* 4672eb3cba82SDavid Gibson * pseries-3.1 4673eb3cba82SDavid Gibson */ 467488cbe073SMarc-André Lureau static void spapr_machine_3_1_class_options(MachineClass *mc) 467588cbe073SMarc-André Lureau { 4676ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4677fea35ca4SAlexey Kardashevskiy 467884e060bfSAlex Williamson spapr_machine_4_0_class_options(mc); 4679abd93cc7SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len); 468027461d69SPrasad J Pandit 468134a6b015SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 4682fea35ca4SAlexey Kardashevskiy smc->update_dt_enabled = false; 4683dae5e39aSMichael Roth smc->dr_phb_enabled = false; 46840a794529SDavid Gibson smc->broken_host_serial_model = true; 46852782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN; 46862782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN; 46872782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN; 4688edaa7995SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF; 468984e060bfSAlex Williamson } 469084e060bfSAlex Williamson 469184e060bfSAlex Williamson DEFINE_SPAPR_MACHINE(3_1, "3.1", false); 4692d45360d9SCédric Le Goater 4693d45360d9SCédric Le Goater /* 4694d45360d9SCédric Le Goater * pseries-3.0 4695d45360d9SCédric Le Goater */ 4696d45360d9SCédric Le Goater 4697d45360d9SCédric Le Goater static void spapr_machine_3_0_class_options(MachineClass *mc) 4698d45360d9SCédric Le Goater { 4699ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 470082cffa2eSCédric Le Goater 4701d45360d9SCédric Le Goater spapr_machine_3_1_class_options(mc); 4702ddb3235dSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len); 470382cffa2eSCédric Le Goater 470482cffa2eSCédric Le Goater smc->legacy_irq_allocation = true; 470554255c1fSDavid Gibson smc->nr_xirqs = 0x400; 4706ae837402SCédric Le Goater smc->irq = &spapr_irq_xics_legacy; 4707d45360d9SCédric Le Goater } 4708d45360d9SCédric Le Goater 4709d45360d9SCédric Le Goater DEFINE_SPAPR_MACHINE(3_0, "3.0", false); 47108a4fd427SDavid Gibson 47118a4fd427SDavid Gibson /* 47128a4fd427SDavid Gibson * pseries-2.12 47138a4fd427SDavid Gibson */ 471488cbe073SMarc-André Lureau static void spapr_machine_2_12_class_options(MachineClass *mc) 471588cbe073SMarc-André Lureau { 4716ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 471788cbe073SMarc-André Lureau static GlobalProperty compat[] = { 47186c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-3.0-migration", "on" }, 47196c36bddfSEduardo Habkost { TYPE_SPAPR_CPU_CORE, "pre-3.0-migration", "on" }, 4720fa386d98SMarc-André Lureau }; 47218a4fd427SDavid Gibson 4722d8c0c7afSPeter Maydell spapr_machine_3_0_class_options(mc); 47230d47310bSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_12, hw_compat_2_12_len); 472488cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 47252309832aSDavid Gibson 4726e8937295SGreg Kurz /* We depend on kvm_enabled() to choose a default value for the 4727e8937295SGreg Kurz * hpt-max-page-size capability. Of course we can't do it here 4728e8937295SGreg Kurz * because this is too early and the HW accelerator isn't initialzed 4729e8937295SGreg Kurz * yet. Postpone this to machine init (see default_caps_with_cpu()). 4730e8937295SGreg Kurz */ 4731e8937295SGreg Kurz smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 0; 47328a4fd427SDavid Gibson } 47338a4fd427SDavid Gibson 47348a4fd427SDavid Gibson DEFINE_SPAPR_MACHINE(2_12, "2.12", false); 47352b615412SDavid Gibson 4736813f3cf6SSuraj Jitindar Singh static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc) 4737813f3cf6SSuraj Jitindar Singh { 4738ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4739813f3cf6SSuraj Jitindar Singh 4740813f3cf6SSuraj Jitindar Singh spapr_machine_2_12_class_options(mc); 4741813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND; 4742813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND; 4743813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_FIXED_CCD; 4744813f3cf6SSuraj Jitindar Singh } 4745813f3cf6SSuraj Jitindar Singh 4746813f3cf6SSuraj Jitindar Singh DEFINE_SPAPR_MACHINE(2_12_sxxm, "2.12-sxxm", false); 4747813f3cf6SSuraj Jitindar Singh 47482b615412SDavid Gibson /* 47492b615412SDavid Gibson * pseries-2.11 47502b615412SDavid Gibson */ 47512b615412SDavid Gibson 47522b615412SDavid Gibson static void spapr_machine_2_11_class_options(MachineClass *mc) 47532b615412SDavid Gibson { 4754ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4755ee76a09fSDavid Gibson 47562b615412SDavid Gibson spapr_machine_2_12_class_options(mc); 47574e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON; 475843df70a9SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len); 47592b615412SDavid Gibson } 47602b615412SDavid Gibson 47612b615412SDavid Gibson DEFINE_SPAPR_MACHINE(2_11, "2.11", false); 4762e2676b16SGreg Kurz 4763e2676b16SGreg Kurz /* 47643fa14fbeSDavid Gibson * pseries-2.10 4765db800b21SDavid Gibson */ 4766e2676b16SGreg Kurz 47673fa14fbeSDavid Gibson static void spapr_machine_2_10_class_options(MachineClass *mc) 4768db800b21SDavid Gibson { 4769e2676b16SGreg Kurz spapr_machine_2_11_class_options(mc); 4770503224f4SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_10, hw_compat_2_10_len); 4771db800b21SDavid Gibson } 4772db800b21SDavid Gibson 4773e2676b16SGreg Kurz DEFINE_SPAPR_MACHINE(2_10, "2.10", false); 47743fa14fbeSDavid Gibson 47753fa14fbeSDavid Gibson /* 47763fa14fbeSDavid Gibson * pseries-2.9 47773fa14fbeSDavid Gibson */ 477888cbe073SMarc-André Lureau 477988cbe073SMarc-André Lureau static void spapr_machine_2_9_class_options(MachineClass *mc) 478088cbe073SMarc-André Lureau { 4781ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 478288cbe073SMarc-André Lureau static GlobalProperty compat[] = { 47836c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-2.10-migration", "on" }, 4784fa386d98SMarc-André Lureau }; 47853fa14fbeSDavid Gibson 47863fa14fbeSDavid Gibson spapr_machine_2_10_class_options(mc); 47873e803152SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len); 478888cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 47893bfe5716SLaurent Vivier mc->numa_auto_assign_ram = numa_legacy_auto_assign_ram; 479046f7afa3SGreg Kurz smc->pre_2_10_has_unused_icps = true; 479152b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED; 47923fa14fbeSDavid Gibson } 47933fa14fbeSDavid Gibson 47943fa14fbeSDavid Gibson DEFINE_SPAPR_MACHINE(2_9, "2.9", false); 4795fa325e6cSDavid Gibson 4796fa325e6cSDavid Gibson /* 4797fa325e6cSDavid Gibson * pseries-2.8 4798fa325e6cSDavid Gibson */ 479988cbe073SMarc-André Lureau 480088cbe073SMarc-André Lureau static void spapr_machine_2_8_class_options(MachineClass *mc) 480188cbe073SMarc-André Lureau { 480288cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48036c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "pcie-extended-configuration-space", "off" }, 4804fa386d98SMarc-André Lureau }; 4805fa325e6cSDavid Gibson 4806fa325e6cSDavid Gibson spapr_machine_2_9_class_options(mc); 4807edc24ccdSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len); 480888cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 480955641213SLaurent Vivier mc->numa_mem_align_shift = 23; 4810fa325e6cSDavid Gibson } 4811fa325e6cSDavid Gibson 4812fa325e6cSDavid Gibson DEFINE_SPAPR_MACHINE(2_8, "2.8", false); 4813db800b21SDavid Gibson 4814db800b21SDavid Gibson /* 48151ea1eefcSBharata B Rao * pseries-2.7 48161ea1eefcSBharata B Rao */ 4817357d1e3bSDavid Gibson 4818ce2918cbSDavid Gibson static void phb_placement_2_7(SpaprMachineState *spapr, uint32_t index, 4819357d1e3bSDavid Gibson uint64_t *buid, hwaddr *pio, 4820357d1e3bSDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 4821ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4822ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 4823357d1e3bSDavid Gibson { 4824357d1e3bSDavid Gibson /* Legacy PHB placement for pseries-2.7 and earlier machine types */ 4825357d1e3bSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 4826357d1e3bSDavid Gibson const hwaddr phb_spacing = 0x1000000000ULL; /* 64 GiB */ 4827357d1e3bSDavid Gibson const hwaddr mmio_offset = 0xa0000000; /* 2 GiB + 512 MiB */ 4828357d1e3bSDavid Gibson const hwaddr pio_offset = 0x80000000; /* 2 GiB */ 4829357d1e3bSDavid Gibson const uint32_t max_index = 255; 4830357d1e3bSDavid Gibson const hwaddr phb0_alignment = 0x10000000000ULL; /* 1 TiB */ 4831357d1e3bSDavid Gibson 4832357d1e3bSDavid Gibson uint64_t ram_top = MACHINE(spapr)->ram_size; 4833357d1e3bSDavid Gibson hwaddr phb0_base, phb_base; 4834357d1e3bSDavid Gibson int i; 4835357d1e3bSDavid Gibson 48360c9269a5SDavid Hildenbrand /* Do we have device memory? */ 4837357d1e3bSDavid Gibson if (MACHINE(spapr)->maxram_size > ram_top) { 4838357d1e3bSDavid Gibson /* Can't just use maxram_size, because there may be an 48390c9269a5SDavid Hildenbrand * alignment gap between normal and device memory regions 48400c9269a5SDavid Hildenbrand */ 4841b0c14ec4SDavid Hildenbrand ram_top = MACHINE(spapr)->device_memory->base + 4842b0c14ec4SDavid Hildenbrand memory_region_size(&MACHINE(spapr)->device_memory->mr); 4843357d1e3bSDavid Gibson } 4844357d1e3bSDavid Gibson 4845357d1e3bSDavid Gibson phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment); 4846357d1e3bSDavid Gibson 4847357d1e3bSDavid Gibson if (index > max_index) { 4848357d1e3bSDavid Gibson error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", 4849357d1e3bSDavid Gibson max_index); 4850357d1e3bSDavid Gibson return; 4851357d1e3bSDavid Gibson } 4852357d1e3bSDavid Gibson 4853357d1e3bSDavid Gibson *buid = base_buid + index; 4854357d1e3bSDavid Gibson for (i = 0; i < n_dma; ++i) { 4855357d1e3bSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 4856357d1e3bSDavid Gibson } 4857357d1e3bSDavid Gibson 4858357d1e3bSDavid Gibson phb_base = phb0_base + index * phb_spacing; 4859357d1e3bSDavid Gibson *pio = phb_base + pio_offset; 4860357d1e3bSDavid Gibson *mmio32 = phb_base + mmio_offset; 4861357d1e3bSDavid Gibson /* 4862357d1e3bSDavid Gibson * We don't set the 64-bit MMIO window, relying on the PHB's 4863357d1e3bSDavid Gibson * fallback behaviour of automatically splitting a large "32-bit" 4864357d1e3bSDavid Gibson * window into contiguous 32-bit and 64-bit windows 4865357d1e3bSDavid Gibson */ 4866ec132efaSAlexey Kardashevskiy 4867ec132efaSAlexey Kardashevskiy *nv2gpa = 0; 4868ec132efaSAlexey Kardashevskiy *nv2atsd = 0; 4869357d1e3bSDavid Gibson } 4870db800b21SDavid Gibson 48711ea1eefcSBharata B Rao static void spapr_machine_2_7_class_options(MachineClass *mc) 48721ea1eefcSBharata B Rao { 4873ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 487488cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48756c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0xf80000000", }, 48766c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem64_win_size", "0", }, 48776c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-2.8-migration", "on", }, 48786c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-2.8-migration", "on", }, 487988cbe073SMarc-André Lureau }; 48803daa4a9fSThomas Huth 4881db800b21SDavid Gibson spapr_machine_2_8_class_options(mc); 48822e9c10ebSIgor Mammedov mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power7_v2.3"); 4883a140c199SEduardo Habkost mc->default_machine_opts = "modern-hotplug-events=off"; 48845a995064SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_7, hw_compat_2_7_len); 488588cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 4886357d1e3bSDavid Gibson smc->phb_placement = phb_placement_2_7; 48871ea1eefcSBharata B Rao } 48881ea1eefcSBharata B Rao 4889db800b21SDavid Gibson DEFINE_SPAPR_MACHINE(2_7, "2.7", false); 48901ea1eefcSBharata B Rao 48911ea1eefcSBharata B Rao /* 48924b23699cSDavid Gibson * pseries-2.6 48934b23699cSDavid Gibson */ 489488cbe073SMarc-André Lureau 489588cbe073SMarc-André Lureau static void spapr_machine_2_6_class_options(MachineClass *mc) 489688cbe073SMarc-André Lureau { 489788cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48986c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "ddw", "off" }, 4899fa386d98SMarc-André Lureau }; 49001ea1eefcSBharata B Rao 49011ea1eefcSBharata B Rao spapr_machine_2_7_class_options(mc); 4902c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = false; 4903ff8f261fSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_6, hw_compat_2_6_len); 490488cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 49054b23699cSDavid Gibson } 49064b23699cSDavid Gibson 49071ea1eefcSBharata B Rao DEFINE_SPAPR_MACHINE(2_6, "2.6", false); 49084b23699cSDavid Gibson 49094b23699cSDavid Gibson /* 49101c5f29bbSDavid Gibson * pseries-2.5 49111c5f29bbSDavid Gibson */ 491288cbe073SMarc-André Lureau 491388cbe073SMarc-André Lureau static void spapr_machine_2_5_class_options(MachineClass *mc) 491488cbe073SMarc-André Lureau { 4915ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 491688cbe073SMarc-André Lureau static GlobalProperty compat[] = { 49176c36bddfSEduardo Habkost { "spapr-vlan", "use-rx-buffer-pools", "off" }, 4918fa386d98SMarc-André Lureau }; 49194b23699cSDavid Gibson 49204b23699cSDavid Gibson spapr_machine_2_6_class_options(mc); 492157040d45SThomas Huth smc->use_ohci_by_default = true; 4922fe759610SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_5, hw_compat_2_5_len); 492388cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 49241c5f29bbSDavid Gibson } 49251c5f29bbSDavid Gibson 49264b23699cSDavid Gibson DEFINE_SPAPR_MACHINE(2_5, "2.5", false); 49271c5f29bbSDavid Gibson 49281c5f29bbSDavid Gibson /* 49291c5f29bbSDavid Gibson * pseries-2.4 49301c5f29bbSDavid Gibson */ 493180fd50f9SCornelia Huck 49325013c547SDavid Gibson static void spapr_machine_2_4_class_options(MachineClass *mc) 49335013c547SDavid Gibson { 4934ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4935fc9f38c3SDavid Gibson 4936fc9f38c3SDavid Gibson spapr_machine_2_5_class_options(mc); 4937fc9f38c3SDavid Gibson smc->dr_lmb_enabled = false; 49382f99b9c2SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_4, hw_compat_2_4_len); 49391c5f29bbSDavid Gibson } 49401c5f29bbSDavid Gibson 4941fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_4, "2.4", false); 49421c5f29bbSDavid Gibson 49431c5f29bbSDavid Gibson /* 49441c5f29bbSDavid Gibson * pseries-2.3 49451c5f29bbSDavid Gibson */ 494688cbe073SMarc-André Lureau 494788cbe073SMarc-André Lureau static void spapr_machine_2_3_class_options(MachineClass *mc) 494888cbe073SMarc-André Lureau { 494988cbe073SMarc-André Lureau static GlobalProperty compat[] = { 49506c36bddfSEduardo Habkost { "spapr-pci-host-bridge", "dynamic-reconfiguration", "off" }, 4951fa386d98SMarc-André Lureau }; 4952fc9f38c3SDavid Gibson spapr_machine_2_4_class_options(mc); 49538995dd90SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_3, hw_compat_2_3_len); 495488cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 49551c5f29bbSDavid Gibson } 4956fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_3, "2.3", false); 49571c5f29bbSDavid Gibson 49581c5f29bbSDavid Gibson /* 49591c5f29bbSDavid Gibson * pseries-2.2 49601c5f29bbSDavid Gibson */ 496188cbe073SMarc-André Lureau 496288cbe073SMarc-André Lureau static void spapr_machine_2_2_class_options(MachineClass *mc) 496388cbe073SMarc-André Lureau { 496488cbe073SMarc-André Lureau static GlobalProperty compat[] = { 49656c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0x20000000" }, 4966fa386d98SMarc-André Lureau }; 4967b194df47SAlexey Kardashevskiy 4968fc9f38c3SDavid Gibson spapr_machine_2_3_class_options(mc); 49691c30044eSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_2, hw_compat_2_2_len); 497088cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 4971f6d0656bSEduardo Habkost mc->default_machine_opts = "modern-hotplug-events=off,suppress-vmdesc=on"; 49721c5f29bbSDavid Gibson } 4973fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_2, "2.2", false); 49741c5f29bbSDavid Gibson 49751c5f29bbSDavid Gibson /* 49761c5f29bbSDavid Gibson * pseries-2.1 49771c5f29bbSDavid Gibson */ 49781c5f29bbSDavid Gibson 49795013c547SDavid Gibson static void spapr_machine_2_1_class_options(MachineClass *mc) 4980b0e966d0SJason Wang { 4981fc9f38c3SDavid Gibson spapr_machine_2_2_class_options(mc); 4982c4fc5695SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_1, hw_compat_2_1_len); 49836026db45SAlexey Kardashevskiy } 4984fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_1, "2.1", false); 49856026db45SAlexey Kardashevskiy 498629ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void) 498729ee3247SAlexey Kardashevskiy { 498829ee3247SAlexey Kardashevskiy type_register_static(&spapr_machine_info); 498929ee3247SAlexey Kardashevskiy } 499029ee3247SAlexey Kardashevskiy 499129ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types) 4992