153018216SPaolo Bonzini /* 253018216SPaolo Bonzini * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator 353018216SPaolo Bonzini * 453018216SPaolo Bonzini * Copyright (c) 2004-2007 Fabrice Bellard 553018216SPaolo Bonzini * Copyright (c) 2007 Jocelyn Mayer 653018216SPaolo Bonzini * Copyright (c) 2010 David Gibson, IBM Corporation. 753018216SPaolo Bonzini * 853018216SPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy 953018216SPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal 1053018216SPaolo Bonzini * in the Software without restriction, including without limitation the rights 1153018216SPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1253018216SPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is 1353018216SPaolo Bonzini * furnished to do so, subject to the following conditions: 1453018216SPaolo Bonzini * 1553018216SPaolo Bonzini * The above copyright notice and this permission notice shall be included in 1653018216SPaolo Bonzini * all copies or substantial portions of the Software. 1753018216SPaolo Bonzini * 1853018216SPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1953018216SPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2053018216SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2153018216SPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2253018216SPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2353018216SPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 2453018216SPaolo Bonzini * THE SOFTWARE. 2553018216SPaolo Bonzini */ 26a8d25326SMarkus Armbruster 270d75590dSPeter Maydell #include "qemu/osdep.h" 28a8d25326SMarkus Armbruster #include "qemu-common.h" 29da34e65cSMarkus Armbruster #include "qapi/error.h" 30fa98fbfcSSam Bobroff #include "qapi/visitor.h" 3153018216SPaolo Bonzini #include "sysemu/sysemu.h" 32b58c5c2dSMarkus Armbruster #include "sysemu/hostmem.h" 33e35704baSEduardo Habkost #include "sysemu/numa.h" 3423ff81bdSGreg Kurz #include "sysemu/qtest.h" 3571e8a915SMarkus Armbruster #include "sysemu/reset.h" 3654d31236SMarkus Armbruster #include "sysemu/runstate.h" 3703dd024fSPaolo Bonzini #include "qemu/log.h" 3871461b0fSAlexey Kardashevskiy #include "hw/fw-path-provider.h" 3953018216SPaolo Bonzini #include "elf.h" 4053018216SPaolo Bonzini #include "net/net.h" 41ad440b4aSAndrew Jones #include "sysemu/device_tree.h" 4253018216SPaolo Bonzini #include "sysemu/cpus.h" 43b3946626SVincent Palatin #include "sysemu/hw_accel.h" 4453018216SPaolo Bonzini #include "kvm_ppc.h" 45c4b63b7cSJuan Quintela #include "migration/misc.h" 46ca77ee28SMarkus Armbruster #include "migration/qemu-file-types.h" 4784a899deSJuan Quintela #include "migration/global_state.h" 48f2a8f0a6SJuan Quintela #include "migration/register.h" 494be21d56SDavid Gibson #include "mmu-hash64.h" 50b4db5413SSuraj Jitindar Singh #include "mmu-book3s-v3.h" 517abd43baSSuraj Jitindar Singh #include "cpu-models.h" 522e5b09fdSMarkus Armbruster #include "hw/core/cpu.h" 5353018216SPaolo Bonzini 5453018216SPaolo Bonzini #include "hw/boards.h" 550d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h" 5653018216SPaolo Bonzini #include "hw/loader.h" 5753018216SPaolo Bonzini 587804c353SCédric Le Goater #include "hw/ppc/fdt.h" 590d09e41aSPaolo Bonzini #include "hw/ppc/spapr.h" 600d09e41aSPaolo Bonzini #include "hw/ppc/spapr_vio.h" 61a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 620d09e41aSPaolo Bonzini #include "hw/pci-host/spapr.h" 6353018216SPaolo Bonzini #include "hw/pci/msi.h" 6453018216SPaolo Bonzini 6553018216SPaolo Bonzini #include "hw/pci/pci.h" 6671461b0fSAlexey Kardashevskiy #include "hw/scsi/scsi.h" 6771461b0fSAlexey Kardashevskiy #include "hw/virtio/virtio-scsi.h" 68c4e13492SFelipe Franciosi #include "hw/virtio/vhost-scsi-common.h" 6953018216SPaolo Bonzini 7053018216SPaolo Bonzini #include "exec/address-spaces.h" 712309832aSDavid Gibson #include "exec/ram_addr.h" 7253018216SPaolo Bonzini #include "hw/usb.h" 7353018216SPaolo Bonzini #include "qemu/config-file.h" 74135a129aSAneesh Kumar K.V #include "qemu/error-report.h" 752a6593cbSAlexey Kardashevskiy #include "trace.h" 7634316482SAlexey Kardashevskiy #include "hw/nmi.h" 776449da45SCédric Le Goater #include "hw/intc/intc.h" 7853018216SPaolo Bonzini 79f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 8094a94e4cSBharata B Rao #include "hw/ppc/spapr_cpu_core.h" 812cc0e2e8SDavid Hildenbrand #include "hw/mem/memory-device.h" 820fb6bd07SMichael Roth #include "hw/ppc/spapr_tpm_proxy.h" 8368a27b20SMichael S. Tsirkin 84f041d6afSGreg Kurz #include "monitor/monitor.h" 85f041d6afSGreg Kurz 8653018216SPaolo Bonzini #include <libfdt.h> 8753018216SPaolo Bonzini 8853018216SPaolo Bonzini /* SLOF memory layout: 8953018216SPaolo Bonzini * 9053018216SPaolo Bonzini * SLOF raw image loaded at 0, copies its romfs right below the flat 9153018216SPaolo Bonzini * device-tree, then position SLOF itself 31M below that 9253018216SPaolo Bonzini * 9353018216SPaolo Bonzini * So we set FW_OVERHEAD to 40MB which should account for all of that 9453018216SPaolo Bonzini * and more 9553018216SPaolo Bonzini * 9653018216SPaolo Bonzini * We load our kernel at 4M, leaving space for SLOF initial image 9753018216SPaolo Bonzini */ 9838b02bd8SAlexey Kardashevskiy #define FDT_MAX_SIZE 0x100000 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 10553018216SPaolo Bonzini #define MIN_RMA_SLOF 128UL 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 21986d5771aSSam Bobroff /* Populate the "ibm,pa-features" property */ 220ce2918cbSDavid Gibson static void spapr_populate_pa_features(SpaprMachineState *spapr, 221ee76a09fSDavid Gibson PowerPCCPU *cpu, 222daa36379SDavid Gibson void *fdt, int offset) 22386d5771aSSam Bobroff { 22486d5771aSSam Bobroff uint8_t pa_features_206[] = { 6, 0, 22586d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 }; 22686d5771aSSam Bobroff uint8_t pa_features_207[] = { 24, 0, 22786d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, 22886d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 22986d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 23086d5771aSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 }; 2319fb4541fSSam Bobroff uint8_t pa_features_300[] = { 66, 0, 2329fb4541fSSam Bobroff /* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */ 2339fb4541fSSam Bobroff /* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, SSO, 5: LE|CFAR|EB|LSQ */ 23486d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, /* 0 - 5 */ 2359fb4541fSSam Bobroff /* 6: DS207 */ 23686d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */ 2379fb4541fSSam Bobroff /* 16: Vector */ 23886d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */ 2399fb4541fSSam Bobroff /* 18: Vec. Scalar, 20: Vec. XOR, 22: HTM */ 2409bf502feSDavid Gibson 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */ 2419fb4541fSSam Bobroff /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */ 2429fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */ 2439fb4541fSSam Bobroff /* 30: MMR, 32: LE atomic, 34: EBB + ext EBB */ 2449fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */ 2459fb4541fSSam Bobroff /* 36: SPR SO, 38: Copy/Paste, 40: Radix MMU */ 2469fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 36 - 41 */ 2479fb4541fSSam Bobroff /* 42: PM, 44: PC RA, 46: SC vec'd */ 2489fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */ 2499fb4541fSSam Bobroff /* 48: SIMD, 50: QP BFP, 52: String */ 2509fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */ 2519fb4541fSSam Bobroff /* 54: DecFP, 56: DecI, 58: SHA */ 2529fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */ 2539fb4541fSSam Bobroff /* 60: NM atomic, 62: RNG */ 2549fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */ 2559fb4541fSSam Bobroff }; 2567abd43baSSuraj Jitindar Singh uint8_t *pa_features = NULL; 25786d5771aSSam Bobroff size_t pa_size; 25886d5771aSSam Bobroff 2597abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06, 0, cpu->compat_pvr)) { 26086d5771aSSam Bobroff pa_features = pa_features_206; 26186d5771aSSam Bobroff pa_size = sizeof(pa_features_206); 2627abd43baSSuraj Jitindar Singh } 2637abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07, 0, cpu->compat_pvr)) { 26486d5771aSSam Bobroff pa_features = pa_features_207; 26586d5771aSSam Bobroff pa_size = sizeof(pa_features_207); 2667abd43baSSuraj Jitindar Singh } 2677abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0, cpu->compat_pvr)) { 26886d5771aSSam Bobroff pa_features = pa_features_300; 26986d5771aSSam Bobroff pa_size = sizeof(pa_features_300); 2707abd43baSSuraj Jitindar Singh } 2717abd43baSSuraj Jitindar Singh if (!pa_features) { 27286d5771aSSam Bobroff return; 27386d5771aSSam Bobroff } 27486d5771aSSam Bobroff 27526cd35b8SDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_CI_LARGEPAGE)) { 27686d5771aSSam Bobroff /* 27786d5771aSSam Bobroff * Note: we keep CI large pages off by default because a 64K capable 27886d5771aSSam Bobroff * guest provisioned with large pages might otherwise try to map a qemu 27986d5771aSSam Bobroff * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages 28086d5771aSSam Bobroff * even if that qemu runs on a 4k host. 28186d5771aSSam Bobroff * We dd this bit back here if we are confident this is not an issue 28286d5771aSSam Bobroff */ 28386d5771aSSam Bobroff pa_features[3] |= 0x20; 28486d5771aSSam Bobroff } 2854e5fe368SSuraj Jitindar Singh if ((spapr_get_cap(spapr, SPAPR_CAP_HTM) != 0) && pa_size > 24) { 28686d5771aSSam Bobroff pa_features[24] |= 0x80; /* Transactional memory support */ 28786d5771aSSam Bobroff } 288daa36379SDavid Gibson if (spapr->cas_pre_isa3_guest && pa_size > 40) { 289e957f6a9SSam Bobroff /* Workaround for broken kernels that attempt (guest) radix 290e957f6a9SSam Bobroff * mode when they can't handle it, if they see the radix bit set 291e957f6a9SSam Bobroff * in pa-features. So hide it from them. */ 292e957f6a9SSam Bobroff pa_features[40 + 2] &= ~0x80; /* Radix MMU */ 293e957f6a9SSam Bobroff } 29486d5771aSSam Bobroff 29586d5771aSSam Bobroff _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size))); 29686d5771aSSam Bobroff } 29786d5771aSSam Bobroff 298c86c1affSDaniel Henrique Barboza static hwaddr spapr_node0_size(MachineState *machine) 299b082d65aSAlexey Kardashevskiy { 300aa570207STao Xu if (machine->numa_state->num_nodes) { 301b082d65aSAlexey Kardashevskiy int i; 302aa570207STao Xu for (i = 0; i < machine->numa_state->num_nodes; ++i) { 3037e721e7bSTao Xu if (machine->numa_state->nodes[i].node_mem) { 3047e721e7bSTao Xu return MIN(pow2floor(machine->numa_state->nodes[i].node_mem), 305fb164994SDavid Gibson machine->ram_size); 306b082d65aSAlexey Kardashevskiy } 307b082d65aSAlexey Kardashevskiy } 308b082d65aSAlexey Kardashevskiy } 309fb164994SDavid Gibson return machine->ram_size; 310b082d65aSAlexey Kardashevskiy } 311b082d65aSAlexey Kardashevskiy 312a1d59c0fSAlexey Kardashevskiy static void add_str(GString *s, const gchar *s1) 313a1d59c0fSAlexey Kardashevskiy { 314a1d59c0fSAlexey Kardashevskiy g_string_append_len(s, s1, strlen(s1) + 1); 315a1d59c0fSAlexey Kardashevskiy } 31653018216SPaolo Bonzini 31703d196b7SBharata B Rao static int spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start, 31826a8c353SAlexey Kardashevskiy hwaddr size) 31926a8c353SAlexey Kardashevskiy { 32026a8c353SAlexey Kardashevskiy uint32_t associativity[] = { 32126a8c353SAlexey Kardashevskiy cpu_to_be32(0x4), /* length */ 32226a8c353SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(0x0), 323c3b4f589SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(nodeid) 32426a8c353SAlexey Kardashevskiy }; 32526a8c353SAlexey Kardashevskiy char mem_name[32]; 32626a8c353SAlexey Kardashevskiy uint64_t mem_reg_property[2]; 32726a8c353SAlexey Kardashevskiy int off; 32826a8c353SAlexey Kardashevskiy 32926a8c353SAlexey Kardashevskiy mem_reg_property[0] = cpu_to_be64(start); 33026a8c353SAlexey Kardashevskiy mem_reg_property[1] = cpu_to_be64(size); 33126a8c353SAlexey Kardashevskiy 3323a17e38fSAlexey Kardashevskiy sprintf(mem_name, "memory@%" HWADDR_PRIx, start); 33326a8c353SAlexey Kardashevskiy off = fdt_add_subnode(fdt, 0, mem_name); 33426a8c353SAlexey Kardashevskiy _FDT(off); 33526a8c353SAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 33626a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 33726a8c353SAlexey Kardashevskiy sizeof(mem_reg_property)))); 33826a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity, 33926a8c353SAlexey Kardashevskiy sizeof(associativity)))); 34003d196b7SBharata B Rao return off; 34126a8c353SAlexey Kardashevskiy } 34226a8c353SAlexey Kardashevskiy 343ce2918cbSDavid Gibson static int spapr_populate_memory(SpaprMachineState *spapr, void *fdt) 34453018216SPaolo Bonzini { 345fb164994SDavid Gibson MachineState *machine = MACHINE(spapr); 3467db8a127SAlexey Kardashevskiy hwaddr mem_start, node_size; 347aa570207STao Xu int i, nb_nodes = machine->numa_state->num_nodes; 3487e721e7bSTao Xu NodeInfo *nodes = machine->numa_state->nodes; 34953018216SPaolo Bonzini 3507db8a127SAlexey Kardashevskiy for (i = 0, mem_start = 0; i < nb_nodes; ++i) { 3517db8a127SAlexey Kardashevskiy if (!nodes[i].node_mem) { 3527db8a127SAlexey Kardashevskiy continue; 35353018216SPaolo Bonzini } 354fb164994SDavid Gibson if (mem_start >= machine->ram_size) { 3555fe269b1SPaul Mackerras node_size = 0; 3565fe269b1SPaul Mackerras } else { 3577db8a127SAlexey Kardashevskiy node_size = nodes[i].node_mem; 358fb164994SDavid Gibson if (node_size > machine->ram_size - mem_start) { 359fb164994SDavid Gibson node_size = machine->ram_size - mem_start; 3605fe269b1SPaul Mackerras } 3615fe269b1SPaul Mackerras } 3627db8a127SAlexey Kardashevskiy if (!mem_start) { 363b472b1a7SDaniel Henrique Barboza /* spapr_machine_init() checks for rma_size <= node0_size 364b472b1a7SDaniel Henrique Barboza * already */ 365e8f986fcSBharata B Rao spapr_populate_memory_node(fdt, i, 0, spapr->rma_size); 3667db8a127SAlexey Kardashevskiy mem_start += spapr->rma_size; 3677db8a127SAlexey Kardashevskiy node_size -= spapr->rma_size; 3687db8a127SAlexey Kardashevskiy } 3696010818cSAlexey Kardashevskiy for ( ; node_size; ) { 3706010818cSAlexey Kardashevskiy hwaddr sizetmp = pow2floor(node_size); 3716010818cSAlexey Kardashevskiy 3726010818cSAlexey Kardashevskiy /* mem_start != 0 here */ 3736010818cSAlexey Kardashevskiy if (ctzl(mem_start) < ctzl(sizetmp)) { 3746010818cSAlexey Kardashevskiy sizetmp = 1ULL << ctzl(mem_start); 3756010818cSAlexey Kardashevskiy } 3766010818cSAlexey Kardashevskiy 3776010818cSAlexey Kardashevskiy spapr_populate_memory_node(fdt, i, mem_start, sizetmp); 3786010818cSAlexey Kardashevskiy node_size -= sizetmp; 3796010818cSAlexey Kardashevskiy mem_start += sizetmp; 3806010818cSAlexey Kardashevskiy } 38153018216SPaolo Bonzini } 38253018216SPaolo Bonzini 38353018216SPaolo Bonzini return 0; 38453018216SPaolo Bonzini } 38553018216SPaolo Bonzini 3860da6f3feSBharata B Rao static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, 387ce2918cbSDavid Gibson SpaprMachineState *spapr) 3880da6f3feSBharata B Rao { 389fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 3900da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 3910da6f3feSBharata B Rao CPUPPCState *env = &cpu->env; 3920da6f3feSBharata B Rao PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 39314bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 3940da6f3feSBharata B Rao uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 3950da6f3feSBharata B Rao 0xffffffff, 0xffffffff}; 396afd10a0fSBharata B Rao uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() 397afd10a0fSBharata B Rao : SPAPR_TIMEBASE_FREQ; 3980da6f3feSBharata B Rao uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; 3990da6f3feSBharata B Rao uint32_t page_sizes_prop[64]; 4000da6f3feSBharata B Rao size_t page_sizes_prop_size; 401fe6b6346SLike Xu unsigned int smp_threads = ms->smp.threads; 402fe6b6346SLike Xu uint32_t vcpus_per_socket = smp_threads * ms->smp.cores; 4030da6f3feSBharata B Rao uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 404abbc1247SDavid Gibson int compat_smt = MIN(smp_threads, ppc_compat_max_vthreads(cpu)); 405ce2918cbSDavid Gibson SpaprDrc *drc; 406af81cf32SBharata B Rao int drc_index; 407c64abd1fSSam Bobroff uint32_t radix_AP_encodings[PPC_PAGE_SIZES_MAX_SZ]; 408c64abd1fSSam Bobroff int i; 409af81cf32SBharata B Rao 410fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index); 411af81cf32SBharata B Rao if (drc) { 4120b55aa91SDavid Gibson drc_index = spapr_drc_index(drc); 413af81cf32SBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index))); 414af81cf32SBharata B Rao } 4150da6f3feSBharata B Rao 4160da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); 4170da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 4180da6f3feSBharata B Rao 4190da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 4200da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 4210da6f3feSBharata B Rao env->dcache_line_size))); 4220da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 4230da6f3feSBharata B Rao env->dcache_line_size))); 4240da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 4250da6f3feSBharata B Rao env->icache_line_size))); 4260da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 4270da6f3feSBharata B Rao env->icache_line_size))); 4280da6f3feSBharata B Rao 4290da6f3feSBharata B Rao if (pcc->l1_dcache_size) { 4300da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 4310da6f3feSBharata B Rao pcc->l1_dcache_size))); 4320da6f3feSBharata B Rao } else { 4333dc6f869SAlistair Francis warn_report("Unknown L1 dcache size for cpu"); 4340da6f3feSBharata B Rao } 4350da6f3feSBharata B Rao if (pcc->l1_icache_size) { 4360da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 4370da6f3feSBharata B Rao pcc->l1_icache_size))); 4380da6f3feSBharata B Rao } else { 4393dc6f869SAlistair Francis warn_report("Unknown L1 icache size for cpu"); 4400da6f3feSBharata B Rao } 4410da6f3feSBharata B Rao 4420da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 4430da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 44467d7d66fSDavid Gibson _FDT((fdt_setprop_cell(fdt, offset, "slb-size", cpu->hash64_opts->slb_size))); 44567d7d66fSDavid Gibson _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", cpu->hash64_opts->slb_size))); 4460da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 4470da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 4480da6f3feSBharata B Rao 4490da6f3feSBharata B Rao if (env->spr_cb[SPR_PURR].oea_read) { 45083f192d3SSuraj Jitindar Singh _FDT((fdt_setprop_cell(fdt, offset, "ibm,purr", 1))); 45183f192d3SSuraj Jitindar Singh } 45283f192d3SSuraj Jitindar Singh if (env->spr_cb[SPR_SPURR].oea_read) { 45383f192d3SSuraj Jitindar Singh _FDT((fdt_setprop_cell(fdt, offset, "ibm,spurr", 1))); 4540da6f3feSBharata B Rao } 4550da6f3feSBharata B Rao 45658969eeeSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 4570da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 4580da6f3feSBharata B Rao segs, sizeof(segs)))); 4590da6f3feSBharata B Rao } 4600da6f3feSBharata B Rao 46129386642SDavid Gibson /* Advertise VSX (vector extensions) if available 4620da6f3feSBharata B Rao * 1 == VMX / Altivec available 46329386642SDavid Gibson * 2 == VSX available 46429386642SDavid Gibson * 46529386642SDavid Gibson * Only CPUs for which we create core types in spapr_cpu_core.c 46629386642SDavid Gibson * are possible, and all of those have VMX */ 4674e5fe368SSuraj Jitindar Singh if (spapr_get_cap(spapr, SPAPR_CAP_VSX) != 0) { 46829386642SDavid Gibson _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2))); 46929386642SDavid Gibson } else { 47029386642SDavid Gibson _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1))); 4710da6f3feSBharata B Rao } 4720da6f3feSBharata B Rao 4730da6f3feSBharata B Rao /* Advertise DFP (Decimal Floating Point) if available 4740da6f3feSBharata B Rao * 0 / no property == no DFP 4750da6f3feSBharata B Rao * 1 == DFP available */ 4764e5fe368SSuraj Jitindar Singh if (spapr_get_cap(spapr, SPAPR_CAP_DFP) != 0) { 4770da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 4780da6f3feSBharata B Rao } 4790da6f3feSBharata B Rao 480644a2c99SDavid Gibson page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 4810da6f3feSBharata B Rao sizeof(page_sizes_prop)); 4820da6f3feSBharata B Rao if (page_sizes_prop_size) { 4830da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 4840da6f3feSBharata B Rao page_sizes_prop, page_sizes_prop_size))); 4850da6f3feSBharata B Rao } 4860da6f3feSBharata B Rao 487daa36379SDavid Gibson spapr_populate_pa_features(spapr, cpu, fdt, offset); 48890da0d5aSBenjamin Herrenschmidt 4890da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", 49022419c2aSDavid Gibson cs->cpu_index / vcpus_per_socket))); 4910da6f3feSBharata B Rao 4920da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", 4930da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)))); 4940da6f3feSBharata B Rao 495aa570207STao Xu if (ms->numa_state->num_nodes > 1) { 49699861ecbSIgor Mammedov _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cpu)); 49799861ecbSIgor Mammedov } 4980da6f3feSBharata B Rao 49912dbeb16SDavid Gibson _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt)); 500c64abd1fSSam Bobroff 501c64abd1fSSam Bobroff if (pcc->radix_page_info) { 502c64abd1fSSam Bobroff for (i = 0; i < pcc->radix_page_info->count; i++) { 503c64abd1fSSam Bobroff radix_AP_encodings[i] = 504c64abd1fSSam Bobroff cpu_to_be32(pcc->radix_page_info->entries[i]); 505c64abd1fSSam Bobroff } 506c64abd1fSSam Bobroff _FDT((fdt_setprop(fdt, offset, "ibm,processor-radix-AP-encodings", 507c64abd1fSSam Bobroff radix_AP_encodings, 508c64abd1fSSam Bobroff pcc->radix_page_info->count * 509c64abd1fSSam Bobroff sizeof(radix_AP_encodings[0])))); 510c64abd1fSSam Bobroff } 511a8dafa52SSuraj Jitindar Singh 512a8dafa52SSuraj Jitindar Singh /* 513a8dafa52SSuraj Jitindar Singh * We set this property to let the guest know that it can use the large 514a8dafa52SSuraj Jitindar Singh * decrementer and its width in bits. 515a8dafa52SSuraj Jitindar Singh */ 516a8dafa52SSuraj Jitindar Singh if (spapr_get_cap(spapr, SPAPR_CAP_LARGE_DECREMENTER) != SPAPR_CAP_OFF) 517a8dafa52SSuraj Jitindar Singh _FDT((fdt_setprop_u32(fdt, offset, "ibm,dec-bits", 518a8dafa52SSuraj Jitindar Singh pcc->lrg_decr_bits))); 5190da6f3feSBharata B Rao } 5200da6f3feSBharata B Rao 521ce2918cbSDavid Gibson static void spapr_populate_cpus_dt_node(void *fdt, SpaprMachineState *spapr) 5220da6f3feSBharata B Rao { 52304d595b3SEmilio G. Cota CPUState **rev; 5240da6f3feSBharata B Rao CPUState *cs; 52504d595b3SEmilio G. Cota int n_cpus; 5260da6f3feSBharata B Rao int cpus_offset; 5270da6f3feSBharata B Rao char *nodename; 52804d595b3SEmilio G. Cota int i; 5290da6f3feSBharata B Rao 5300da6f3feSBharata B Rao cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 5310da6f3feSBharata B Rao _FDT(cpus_offset); 5320da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 5330da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 5340da6f3feSBharata B Rao 5350da6f3feSBharata B Rao /* 5360da6f3feSBharata B Rao * We walk the CPUs in reverse order to ensure that CPU DT nodes 5370da6f3feSBharata B Rao * created by fdt_add_subnode() end up in the right order in FDT 5380da6f3feSBharata B Rao * for the guest kernel the enumerate the CPUs correctly. 53904d595b3SEmilio G. Cota * 54004d595b3SEmilio G. Cota * The CPU list cannot be traversed in reverse order, so we need 54104d595b3SEmilio G. Cota * to do extra work. 5420da6f3feSBharata B Rao */ 54304d595b3SEmilio G. Cota n_cpus = 0; 54404d595b3SEmilio G. Cota rev = NULL; 54504d595b3SEmilio G. Cota CPU_FOREACH(cs) { 54604d595b3SEmilio G. Cota rev = g_renew(CPUState *, rev, n_cpus + 1); 54704d595b3SEmilio G. Cota rev[n_cpus++] = cs; 54804d595b3SEmilio G. Cota } 54904d595b3SEmilio G. Cota 55004d595b3SEmilio G. Cota for (i = n_cpus - 1; i >= 0; i--) { 55104d595b3SEmilio G. Cota CPUState *cs = rev[i]; 5520da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 55314bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 5540da6f3feSBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 5550da6f3feSBharata B Rao int offset; 5560da6f3feSBharata B Rao 5575d0fb150SGreg Kurz if (!spapr_is_thread0_in_vcore(spapr, cpu)) { 5580da6f3feSBharata B Rao continue; 5590da6f3feSBharata B Rao } 5600da6f3feSBharata B Rao 5610da6f3feSBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, index); 5620da6f3feSBharata B Rao offset = fdt_add_subnode(fdt, cpus_offset, nodename); 5630da6f3feSBharata B Rao g_free(nodename); 5640da6f3feSBharata B Rao _FDT(offset); 5650da6f3feSBharata B Rao spapr_populate_cpu_dt(cs, fdt, offset, spapr); 5660da6f3feSBharata B Rao } 5670da6f3feSBharata B Rao 568eceba347SEmilio G. Cota g_free(rev); 5690da6f3feSBharata B Rao } 5700da6f3feSBharata B Rao 5710e947a89SThomas Huth static int spapr_rng_populate_dt(void *fdt) 5720e947a89SThomas Huth { 5730e947a89SThomas Huth int node; 5740e947a89SThomas Huth int ret; 5750e947a89SThomas Huth 5760e947a89SThomas Huth node = qemu_fdt_add_subnode(fdt, "/ibm,platform-facilities"); 5770e947a89SThomas Huth if (node <= 0) { 5780e947a89SThomas Huth return -1; 5790e947a89SThomas Huth } 5800e947a89SThomas Huth ret = fdt_setprop_string(fdt, node, "device_type", 5810e947a89SThomas Huth "ibm,platform-facilities"); 5820e947a89SThomas Huth ret |= fdt_setprop_cell(fdt, node, "#address-cells", 0x1); 5830e947a89SThomas Huth ret |= fdt_setprop_cell(fdt, node, "#size-cells", 0x0); 5840e947a89SThomas Huth 5850e947a89SThomas Huth node = fdt_add_subnode(fdt, node, "ibm,random-v1"); 5860e947a89SThomas Huth if (node <= 0) { 5870e947a89SThomas Huth return -1; 5880e947a89SThomas Huth } 5890e947a89SThomas Huth ret |= fdt_setprop_string(fdt, node, "compatible", "ibm,random"); 5900e947a89SThomas Huth 5910e947a89SThomas Huth return ret ? -1 : 0; 5920e947a89SThomas Huth } 5930e947a89SThomas Huth 594f47bd1c8SIgor Mammedov static uint32_t spapr_pc_dimm_node(MemoryDeviceInfoList *list, ram_addr_t addr) 595f47bd1c8SIgor Mammedov { 596f47bd1c8SIgor Mammedov MemoryDeviceInfoList *info; 597f47bd1c8SIgor Mammedov 598f47bd1c8SIgor Mammedov for (info = list; info; info = info->next) { 599f47bd1c8SIgor Mammedov MemoryDeviceInfo *value = info->value; 600f47bd1c8SIgor Mammedov 601f47bd1c8SIgor Mammedov if (value && value->type == MEMORY_DEVICE_INFO_KIND_DIMM) { 602f47bd1c8SIgor Mammedov PCDIMMDeviceInfo *pcdimm_info = value->u.dimm.data; 603f47bd1c8SIgor Mammedov 604ccc2cef8SDavid Gibson if (addr >= pcdimm_info->addr && 605f47bd1c8SIgor Mammedov addr < (pcdimm_info->addr + pcdimm_info->size)) { 606f47bd1c8SIgor Mammedov return pcdimm_info->node; 607f47bd1c8SIgor Mammedov } 608f47bd1c8SIgor Mammedov } 609f47bd1c8SIgor Mammedov } 610f47bd1c8SIgor Mammedov 611f47bd1c8SIgor Mammedov return -1; 612f47bd1c8SIgor Mammedov } 613f47bd1c8SIgor Mammedov 614a324d6f1SBharata B Rao struct sPAPRDrconfCellV2 { 615a324d6f1SBharata B Rao uint32_t seq_lmbs; 616a324d6f1SBharata B Rao uint64_t base_addr; 617a324d6f1SBharata B Rao uint32_t drc_index; 618a324d6f1SBharata B Rao uint32_t aa_index; 619a324d6f1SBharata B Rao uint32_t flags; 620a324d6f1SBharata B Rao } QEMU_PACKED; 621a324d6f1SBharata B Rao 622a324d6f1SBharata B Rao typedef struct DrconfCellQueue { 623a324d6f1SBharata B Rao struct sPAPRDrconfCellV2 cell; 624a324d6f1SBharata B Rao QSIMPLEQ_ENTRY(DrconfCellQueue) entry; 625a324d6f1SBharata B Rao } DrconfCellQueue; 626a324d6f1SBharata B Rao 627a324d6f1SBharata B Rao static DrconfCellQueue * 628a324d6f1SBharata B Rao spapr_get_drconf_cell(uint32_t seq_lmbs, uint64_t base_addr, 629a324d6f1SBharata B Rao uint32_t drc_index, uint32_t aa_index, 630a324d6f1SBharata B Rao uint32_t flags) 63103d196b7SBharata B Rao { 632a324d6f1SBharata B Rao DrconfCellQueue *elem; 633a324d6f1SBharata B Rao 634a324d6f1SBharata B Rao elem = g_malloc0(sizeof(*elem)); 635a324d6f1SBharata B Rao elem->cell.seq_lmbs = cpu_to_be32(seq_lmbs); 636a324d6f1SBharata B Rao elem->cell.base_addr = cpu_to_be64(base_addr); 637a324d6f1SBharata B Rao elem->cell.drc_index = cpu_to_be32(drc_index); 638a324d6f1SBharata B Rao elem->cell.aa_index = cpu_to_be32(aa_index); 639a324d6f1SBharata B Rao elem->cell.flags = cpu_to_be32(flags); 640a324d6f1SBharata B Rao 641a324d6f1SBharata B Rao return elem; 642a324d6f1SBharata B Rao } 643a324d6f1SBharata B Rao 644a324d6f1SBharata B Rao /* ibm,dynamic-memory-v2 */ 645ce2918cbSDavid Gibson static int spapr_populate_drmem_v2(SpaprMachineState *spapr, void *fdt, 646a324d6f1SBharata B Rao int offset, MemoryDeviceInfoList *dimms) 647a324d6f1SBharata B Rao { 648b0c14ec4SDavid Hildenbrand MachineState *machine = MACHINE(spapr); 649cc941111SFabiano Rosas uint8_t *int_buf, *cur_index; 650a324d6f1SBharata B Rao int ret; 65103d196b7SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 652a324d6f1SBharata B Rao uint64_t addr, cur_addr, size; 653b0c14ec4SDavid Hildenbrand uint32_t nr_boot_lmbs = (machine->device_memory->base / lmb_size); 654b0c14ec4SDavid Hildenbrand uint64_t mem_end = machine->device_memory->base + 655b0c14ec4SDavid Hildenbrand memory_region_size(&machine->device_memory->mr); 656cc941111SFabiano Rosas uint32_t node, buf_len, nr_entries = 0; 657ce2918cbSDavid Gibson SpaprDrc *drc; 658a324d6f1SBharata B Rao DrconfCellQueue *elem, *next; 659a324d6f1SBharata B Rao MemoryDeviceInfoList *info; 660a324d6f1SBharata B Rao QSIMPLEQ_HEAD(, DrconfCellQueue) drconf_queue 661a324d6f1SBharata B Rao = QSIMPLEQ_HEAD_INITIALIZER(drconf_queue); 662a324d6f1SBharata B Rao 663a324d6f1SBharata B Rao /* Entry to cover RAM and the gap area */ 664a324d6f1SBharata B Rao elem = spapr_get_drconf_cell(nr_boot_lmbs, 0, 0, -1, 665a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_RESERVED | 666a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 667a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 668a324d6f1SBharata B Rao nr_entries++; 669a324d6f1SBharata B Rao 670b0c14ec4SDavid Hildenbrand cur_addr = machine->device_memory->base; 671a324d6f1SBharata B Rao for (info = dimms; info; info = info->next) { 672a324d6f1SBharata B Rao PCDIMMDeviceInfo *di = info->value->u.dimm.data; 673a324d6f1SBharata B Rao 674a324d6f1SBharata B Rao addr = di->addr; 675a324d6f1SBharata B Rao size = di->size; 676a324d6f1SBharata B Rao node = di->node; 677a324d6f1SBharata B Rao 678a324d6f1SBharata B Rao /* Entry for hot-pluggable area */ 679a324d6f1SBharata B Rao if (cur_addr < addr) { 680a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size); 681a324d6f1SBharata B Rao g_assert(drc); 682a324d6f1SBharata B Rao elem = spapr_get_drconf_cell((addr - cur_addr) / lmb_size, 683a324d6f1SBharata B Rao cur_addr, spapr_drc_index(drc), -1, 0); 684a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 685a324d6f1SBharata B Rao nr_entries++; 686a324d6f1SBharata B Rao } 687a324d6f1SBharata B Rao 688a324d6f1SBharata B Rao /* Entry for DIMM */ 689a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr / lmb_size); 690a324d6f1SBharata B Rao g_assert(drc); 691a324d6f1SBharata B Rao elem = spapr_get_drconf_cell(size / lmb_size, addr, 692a324d6f1SBharata B Rao spapr_drc_index(drc), node, 693a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_ASSIGNED); 694a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 695a324d6f1SBharata B Rao nr_entries++; 696a324d6f1SBharata B Rao cur_addr = addr + size; 697a324d6f1SBharata B Rao } 698a324d6f1SBharata B Rao 699a324d6f1SBharata B Rao /* Entry for remaining hotpluggable area */ 700a324d6f1SBharata B Rao if (cur_addr < mem_end) { 701a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size); 702a324d6f1SBharata B Rao g_assert(drc); 703a324d6f1SBharata B Rao elem = spapr_get_drconf_cell((mem_end - cur_addr) / lmb_size, 704a324d6f1SBharata B Rao cur_addr, spapr_drc_index(drc), -1, 0); 705a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 706a324d6f1SBharata B Rao nr_entries++; 707a324d6f1SBharata B Rao } 708a324d6f1SBharata B Rao 709a324d6f1SBharata B Rao buf_len = nr_entries * sizeof(struct sPAPRDrconfCellV2) + sizeof(uint32_t); 710a324d6f1SBharata B Rao int_buf = cur_index = g_malloc0(buf_len); 711a324d6f1SBharata B Rao *(uint32_t *)int_buf = cpu_to_be32(nr_entries); 712a324d6f1SBharata B Rao cur_index += sizeof(nr_entries); 713a324d6f1SBharata B Rao 714a324d6f1SBharata B Rao QSIMPLEQ_FOREACH_SAFE(elem, &drconf_queue, entry, next) { 715a324d6f1SBharata B Rao memcpy(cur_index, &elem->cell, sizeof(elem->cell)); 716a324d6f1SBharata B Rao cur_index += sizeof(elem->cell); 717a324d6f1SBharata B Rao QSIMPLEQ_REMOVE(&drconf_queue, elem, DrconfCellQueue, entry); 718a324d6f1SBharata B Rao g_free(elem); 719a324d6f1SBharata B Rao } 720a324d6f1SBharata B Rao 721a324d6f1SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory-v2", int_buf, buf_len); 722a324d6f1SBharata B Rao g_free(int_buf); 723a324d6f1SBharata B Rao if (ret < 0) { 724a324d6f1SBharata B Rao return -1; 725a324d6f1SBharata B Rao } 726a324d6f1SBharata B Rao return 0; 727a324d6f1SBharata B Rao } 728a324d6f1SBharata B Rao 729a324d6f1SBharata B Rao /* ibm,dynamic-memory */ 730ce2918cbSDavid Gibson static int spapr_populate_drmem_v1(SpaprMachineState *spapr, void *fdt, 731a324d6f1SBharata B Rao int offset, MemoryDeviceInfoList *dimms) 732a324d6f1SBharata B Rao { 733b0c14ec4SDavid Hildenbrand MachineState *machine = MACHINE(spapr); 734a324d6f1SBharata B Rao int i, ret; 735a324d6f1SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 7360c9269a5SDavid Hildenbrand uint32_t device_lmb_start = machine->device_memory->base / lmb_size; 737b0c14ec4SDavid Hildenbrand uint32_t nr_lmbs = (machine->device_memory->base + 738b0c14ec4SDavid Hildenbrand memory_region_size(&machine->device_memory->mr)) / 739d0e5a8f2SBharata B Rao lmb_size; 74003d196b7SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 74116c25aefSBharata B Rao 74216c25aefSBharata B Rao /* 743ef001f06SThomas Huth * Allocate enough buffer size to fit in ibm,dynamic-memory 744ef001f06SThomas Huth */ 745a324d6f1SBharata B Rao buf_len = (nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1) * sizeof(uint32_t); 74603d196b7SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 74703d196b7SBharata B Rao int_buf[0] = cpu_to_be32(nr_lmbs); 74803d196b7SBharata B Rao cur_index++; 74903d196b7SBharata B Rao for (i = 0; i < nr_lmbs; i++) { 750d0e5a8f2SBharata B Rao uint64_t addr = i * lmb_size; 75103d196b7SBharata B Rao uint32_t *dynamic_memory = cur_index; 75203d196b7SBharata B Rao 7530c9269a5SDavid Hildenbrand if (i >= device_lmb_start) { 754ce2918cbSDavid Gibson SpaprDrc *drc; 755d0e5a8f2SBharata B Rao 756fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, i); 75703d196b7SBharata B Rao g_assert(drc); 75803d196b7SBharata B Rao 75903d196b7SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 76003d196b7SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 7610b55aa91SDavid Gibson dynamic_memory[2] = cpu_to_be32(spapr_drc_index(drc)); 76203d196b7SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 763f47bd1c8SIgor Mammedov dynamic_memory[4] = cpu_to_be32(spapr_pc_dimm_node(dimms, addr)); 764d0e5a8f2SBharata B Rao if (memory_region_present(get_system_memory(), addr)) { 76503d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); 76603d196b7SBharata B Rao } else { 76703d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(0); 76803d196b7SBharata B Rao } 769d0e5a8f2SBharata B Rao } else { 770d0e5a8f2SBharata B Rao /* 771d0e5a8f2SBharata B Rao * LMB information for RMA, boot time RAM and gap b/n RAM and 7720c9269a5SDavid Hildenbrand * device memory region -- all these are marked as reserved 773d0e5a8f2SBharata B Rao * and as having no valid DRC. 774d0e5a8f2SBharata B Rao */ 775d0e5a8f2SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 776d0e5a8f2SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 777d0e5a8f2SBharata B Rao dynamic_memory[2] = cpu_to_be32(0); 778d0e5a8f2SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 779d0e5a8f2SBharata B Rao dynamic_memory[4] = cpu_to_be32(-1); 780d0e5a8f2SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED | 781d0e5a8f2SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 782d0e5a8f2SBharata B Rao } 78303d196b7SBharata B Rao 78403d196b7SBharata B Rao cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; 78503d196b7SBharata B Rao } 78603d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len); 787a324d6f1SBharata B Rao g_free(int_buf); 78803d196b7SBharata B Rao if (ret < 0) { 789a324d6f1SBharata B Rao return -1; 790a324d6f1SBharata B Rao } 791a324d6f1SBharata B Rao return 0; 792a324d6f1SBharata B Rao } 793a324d6f1SBharata B Rao 794a324d6f1SBharata B Rao /* 795a324d6f1SBharata B Rao * Adds ibm,dynamic-reconfiguration-memory node. 796a324d6f1SBharata B Rao * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation 797a324d6f1SBharata B Rao * of this device tree node. 798a324d6f1SBharata B Rao */ 799ce2918cbSDavid Gibson static int spapr_populate_drconf_memory(SpaprMachineState *spapr, void *fdt) 800a324d6f1SBharata B Rao { 801a324d6f1SBharata B Rao MachineState *machine = MACHINE(spapr); 802aa570207STao Xu int nb_numa_nodes = machine->numa_state->num_nodes; 803a324d6f1SBharata B Rao int ret, i, offset; 804a324d6f1SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 805a324d6f1SBharata B Rao uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; 806a324d6f1SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 807a324d6f1SBharata B Rao int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; 808a324d6f1SBharata B Rao MemoryDeviceInfoList *dimms = NULL; 809a324d6f1SBharata B Rao 810a324d6f1SBharata B Rao /* 8110c9269a5SDavid Hildenbrand * Don't create the node if there is no device memory 812a324d6f1SBharata B Rao */ 813a324d6f1SBharata B Rao if (machine->ram_size == machine->maxram_size) { 814a324d6f1SBharata B Rao return 0; 815a324d6f1SBharata B Rao } 816a324d6f1SBharata B Rao 817a324d6f1SBharata B Rao offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory"); 818a324d6f1SBharata B Rao 819a324d6f1SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size, 820a324d6f1SBharata B Rao sizeof(prop_lmb_size)); 821a324d6f1SBharata B Rao if (ret < 0) { 822a324d6f1SBharata B Rao return ret; 823a324d6f1SBharata B Rao } 824a324d6f1SBharata B Rao 825a324d6f1SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff); 826a324d6f1SBharata B Rao if (ret < 0) { 827a324d6f1SBharata B Rao return ret; 828a324d6f1SBharata B Rao } 829a324d6f1SBharata B Rao 830a324d6f1SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0); 831a324d6f1SBharata B Rao if (ret < 0) { 832a324d6f1SBharata B Rao return ret; 833a324d6f1SBharata B Rao } 834a324d6f1SBharata B Rao 835a324d6f1SBharata B Rao /* ibm,dynamic-memory or ibm,dynamic-memory-v2 */ 8362cc0e2e8SDavid Hildenbrand dimms = qmp_memory_device_list(); 837a324d6f1SBharata B Rao if (spapr_ovec_test(spapr->ov5_cas, OV5_DRMEM_V2)) { 838a324d6f1SBharata B Rao ret = spapr_populate_drmem_v2(spapr, fdt, offset, dimms); 839a324d6f1SBharata B Rao } else { 840a324d6f1SBharata B Rao ret = spapr_populate_drmem_v1(spapr, fdt, offset, dimms); 841a324d6f1SBharata B Rao } 842a324d6f1SBharata B Rao qapi_free_MemoryDeviceInfoList(dimms); 843a324d6f1SBharata B Rao 844a324d6f1SBharata B Rao if (ret < 0) { 845a324d6f1SBharata B Rao return ret; 84603d196b7SBharata B Rao } 84703d196b7SBharata B Rao 84803d196b7SBharata B Rao /* ibm,associativity-lookup-arrays */ 849a324d6f1SBharata B Rao buf_len = (nr_nodes * 4 + 2) * sizeof(uint32_t); 850a324d6f1SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 8516663864eSBharata B Rao int_buf[0] = cpu_to_be32(nr_nodes); 85203d196b7SBharata B Rao int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */ 85303d196b7SBharata B Rao cur_index += 2; 8546663864eSBharata B Rao for (i = 0; i < nr_nodes; i++) { 85503d196b7SBharata B Rao uint32_t associativity[] = { 85603d196b7SBharata B Rao cpu_to_be32(0x0), 85703d196b7SBharata B Rao cpu_to_be32(0x0), 85803d196b7SBharata B Rao cpu_to_be32(0x0), 85903d196b7SBharata B Rao cpu_to_be32(i) 86003d196b7SBharata B Rao }; 86103d196b7SBharata B Rao memcpy(cur_index, associativity, sizeof(associativity)); 86203d196b7SBharata B Rao cur_index += 4; 86303d196b7SBharata B Rao } 86403d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf, 86503d196b7SBharata B Rao (cur_index - int_buf) * sizeof(uint32_t)); 86603d196b7SBharata B Rao g_free(int_buf); 867a324d6f1SBharata B Rao 86803d196b7SBharata B Rao return ret; 86903d196b7SBharata B Rao } 87003d196b7SBharata B Rao 871ce2918cbSDavid Gibson static int spapr_dt_cas_updates(SpaprMachineState *spapr, void *fdt, 872ce2918cbSDavid Gibson SpaprOptionVector *ov5_updates) 8736787d27bSMichael Roth { 874ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 875417ece33SMichael Roth int ret = 0, offset; 8766787d27bSMichael Roth 8776787d27bSMichael Roth /* Generate ibm,dynamic-reconfiguration-memory node if required */ 8786787d27bSMichael Roth if (spapr_ovec_test(ov5_updates, OV5_DRCONF_MEMORY)) { 8796787d27bSMichael Roth g_assert(smc->dr_lmb_enabled); 8806787d27bSMichael Roth ret = spapr_populate_drconf_memory(spapr, fdt); 881417ece33SMichael Roth if (ret) { 882417ece33SMichael Roth goto out; 883417ece33SMichael Roth } 8846787d27bSMichael Roth } 8856787d27bSMichael Roth 886417ece33SMichael Roth offset = fdt_path_offset(fdt, "/chosen"); 887417ece33SMichael Roth if (offset < 0) { 888417ece33SMichael Roth offset = fdt_add_subnode(fdt, 0, "chosen"); 889417ece33SMichael Roth if (offset < 0) { 890417ece33SMichael Roth return offset; 891417ece33SMichael Roth } 892417ece33SMichael Roth } 893417ece33SMichael Roth ret = spapr_ovec_populate_dt(fdt, offset, spapr->ov5_cas, 894417ece33SMichael Roth "ibm,architecture-vec-5"); 895417ece33SMichael Roth 896417ece33SMichael Roth out: 8976787d27bSMichael Roth return ret; 8986787d27bSMichael Roth } 8996787d27bSMichael Roth 90010f12e64SDaniel Henrique Barboza static bool spapr_hotplugged_dev_before_cas(void) 90110f12e64SDaniel Henrique Barboza { 90210f12e64SDaniel Henrique Barboza Object *drc_container, *obj; 90310f12e64SDaniel Henrique Barboza ObjectProperty *prop; 90410f12e64SDaniel Henrique Barboza ObjectPropertyIterator iter; 90510f12e64SDaniel Henrique Barboza 90610f12e64SDaniel Henrique Barboza drc_container = container_get(object_get_root(), "/dr-connector"); 90710f12e64SDaniel Henrique Barboza object_property_iter_init(&iter, drc_container); 90810f12e64SDaniel Henrique Barboza while ((prop = object_property_iter_next(&iter))) { 90910f12e64SDaniel Henrique Barboza if (!strstart(prop->type, "link<", NULL)) { 91010f12e64SDaniel Henrique Barboza continue; 91110f12e64SDaniel Henrique Barboza } 91210f12e64SDaniel Henrique Barboza obj = object_property_get_link(drc_container, prop->name, NULL); 91310f12e64SDaniel Henrique Barboza if (spapr_drc_needed(obj)) { 91410f12e64SDaniel Henrique Barboza return true; 91510f12e64SDaniel Henrique Barboza } 91610f12e64SDaniel Henrique Barboza } 91710f12e64SDaniel Henrique Barboza return false; 91810f12e64SDaniel Henrique Barboza } 91910f12e64SDaniel Henrique Barboza 920e68cd0cbSAlexey Kardashevskiy static void *spapr_build_fdt(SpaprMachineState *spapr); 921e68cd0cbSAlexey Kardashevskiy 922ce2918cbSDavid Gibson int spapr_h_cas_compose_response(SpaprMachineState *spapr, 92303d196b7SBharata B Rao target_ulong addr, target_ulong size, 924ce2918cbSDavid Gibson SpaprOptionVector *ov5_updates) 92503d196b7SBharata B Rao { 926e68cd0cbSAlexey Kardashevskiy void *fdt; 927ce2918cbSDavid Gibson SpaprDeviceTreeUpdateHeader hdr = { .version_id = 1 }; 92803d196b7SBharata B Rao 92910f12e64SDaniel Henrique Barboza if (spapr_hotplugged_dev_before_cas()) { 93010f12e64SDaniel Henrique Barboza return 1; 93110f12e64SDaniel Henrique Barboza } 93210f12e64SDaniel Henrique Barboza 933827b17c4SGreg Kurz if (size < sizeof(hdr) || size > FW_MAX_SIZE) { 934827b17c4SGreg Kurz error_report("SLOF provided an unexpected CAS buffer size " 935827b17c4SGreg Kurz TARGET_FMT_lu " (min: %zu, max: %u)", 936827b17c4SGreg Kurz size, sizeof(hdr), FW_MAX_SIZE); 937827b17c4SGreg Kurz exit(EXIT_FAILURE); 938827b17c4SGreg Kurz } 939827b17c4SGreg Kurz 94003d196b7SBharata B Rao size -= sizeof(hdr); 94103d196b7SBharata B Rao 942e68cd0cbSAlexey Kardashevskiy fdt = spapr_build_fdt(spapr); 94303d196b7SBharata B Rao _FDT((fdt_pack(fdt))); 94403d196b7SBharata B Rao 94503d196b7SBharata B Rao if (fdt_totalsize(fdt) + sizeof(hdr) > size) { 946f767b1acSAlexey Kardashevskiy g_free(fdt); 94703d196b7SBharata B Rao trace_spapr_cas_failed(size); 94803d196b7SBharata B Rao return -1; 94903d196b7SBharata B Rao } 95003d196b7SBharata B Rao 95103d196b7SBharata B Rao cpu_physical_memory_write(addr, &hdr, sizeof(hdr)); 95203d196b7SBharata B Rao cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt)); 95303d196b7SBharata B Rao trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr)); 954e68cd0cbSAlexey Kardashevskiy 955e68cd0cbSAlexey Kardashevskiy g_free(spapr->fdt_blob); 956e68cd0cbSAlexey Kardashevskiy spapr->fdt_size = fdt_totalsize(fdt); 957e68cd0cbSAlexey Kardashevskiy spapr->fdt_initial_size = spapr->fdt_size; 958e68cd0cbSAlexey Kardashevskiy spapr->fdt_blob = fdt; 95903d196b7SBharata B Rao 96003d196b7SBharata B Rao return 0; 96103d196b7SBharata B Rao } 96203d196b7SBharata B Rao 963ce2918cbSDavid Gibson static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt) 9643f5dabceSDavid Gibson { 965fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 9663f5dabceSDavid Gibson int rtas; 9673f5dabceSDavid Gibson GString *hypertas = g_string_sized_new(256); 9683f5dabceSDavid Gibson GString *qemu_hypertas = g_string_sized_new(256); 9693f5dabceSDavid Gibson uint32_t refpoints[] = { cpu_to_be32(0x4), cpu_to_be32(0x4) }; 9700c9269a5SDavid Hildenbrand uint64_t max_device_addr = MACHINE(spapr)->device_memory->base + 971b0c14ec4SDavid Hildenbrand memory_region_size(&MACHINE(spapr)->device_memory->mr); 9723f5dabceSDavid Gibson uint32_t lrdr_capacity[] = { 9730c9269a5SDavid Hildenbrand cpu_to_be32(max_device_addr >> 32), 9740c9269a5SDavid Hildenbrand cpu_to_be32(max_device_addr & 0xffffffff), 9753f5dabceSDavid Gibson 0, cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE), 976fe6b6346SLike Xu cpu_to_be32(ms->smp.max_cpus / ms->smp.threads), 9773f5dabceSDavid Gibson }; 978ec132efaSAlexey Kardashevskiy uint32_t maxdomain = cpu_to_be32(spapr->gpu_numa_id > 1 ? 1 : 0); 979da9f80fbSSerhii Popovych uint32_t maxdomains[] = { 980da9f80fbSSerhii Popovych cpu_to_be32(4), 981ec132efaSAlexey Kardashevskiy maxdomain, 982ec132efaSAlexey Kardashevskiy maxdomain, 983ec132efaSAlexey Kardashevskiy maxdomain, 984ec132efaSAlexey Kardashevskiy cpu_to_be32(spapr->gpu_numa_id), 985da9f80fbSSerhii Popovych }; 9863f5dabceSDavid Gibson 9873f5dabceSDavid Gibson _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas")); 9883f5dabceSDavid Gibson 9893f5dabceSDavid Gibson /* hypertas */ 9903f5dabceSDavid Gibson add_str(hypertas, "hcall-pft"); 9913f5dabceSDavid Gibson add_str(hypertas, "hcall-term"); 9923f5dabceSDavid Gibson add_str(hypertas, "hcall-dabr"); 9933f5dabceSDavid Gibson add_str(hypertas, "hcall-interrupt"); 9943f5dabceSDavid Gibson add_str(hypertas, "hcall-tce"); 9953f5dabceSDavid Gibson add_str(hypertas, "hcall-vio"); 9963f5dabceSDavid Gibson add_str(hypertas, "hcall-splpar"); 99710741314SNicholas Piggin add_str(hypertas, "hcall-join"); 9983f5dabceSDavid Gibson add_str(hypertas, "hcall-bulk"); 9993f5dabceSDavid Gibson add_str(hypertas, "hcall-set-mode"); 10003f5dabceSDavid Gibson add_str(hypertas, "hcall-sprg0"); 10013f5dabceSDavid Gibson add_str(hypertas, "hcall-copy"); 10023f5dabceSDavid Gibson add_str(hypertas, "hcall-debug"); 1003c24ba3d0SLaurent Vivier add_str(hypertas, "hcall-vphn"); 10043f5dabceSDavid Gibson add_str(qemu_hypertas, "hcall-memop1"); 10053f5dabceSDavid Gibson 10063f5dabceSDavid Gibson if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { 10073f5dabceSDavid Gibson add_str(hypertas, "hcall-multi-tce"); 10083f5dabceSDavid Gibson } 100930f4b05bSDavid Gibson 101030f4b05bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { 101130f4b05bSDavid Gibson add_str(hypertas, "hcall-hpt-resize"); 101230f4b05bSDavid Gibson } 101330f4b05bSDavid Gibson 10143f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions", 10153f5dabceSDavid Gibson hypertas->str, hypertas->len)); 10163f5dabceSDavid Gibson g_string_free(hypertas, TRUE); 10173f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "qemu,hypertas-functions", 10183f5dabceSDavid Gibson qemu_hypertas->str, qemu_hypertas->len)); 10193f5dabceSDavid Gibson g_string_free(qemu_hypertas, TRUE); 10203f5dabceSDavid Gibson 10213f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,associativity-reference-points", 10223f5dabceSDavid Gibson refpoints, sizeof(refpoints))); 10233f5dabceSDavid Gibson 1024da9f80fbSSerhii Popovych _FDT(fdt_setprop(fdt, rtas, "ibm,max-associativity-domains", 1025da9f80fbSSerhii Popovych maxdomains, sizeof(maxdomains))); 1026da9f80fbSSerhii Popovych 10273f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-error-log-max", 10283f5dabceSDavid Gibson RTAS_ERROR_LOG_MAX)); 10293f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-event-scan-rate", 10303f5dabceSDavid Gibson RTAS_EVENT_SCAN_RATE)); 10313f5dabceSDavid Gibson 10324f441474SDavid Gibson g_assert(msi_nonbroken); 10333f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,change-msix-capable", NULL, 0)); 10343f5dabceSDavid Gibson 10353f5dabceSDavid Gibson /* 10363f5dabceSDavid Gibson * According to PAPR, rtas ibm,os-term does not guarantee a return 10373f5dabceSDavid Gibson * back to the guest cpu. 10383f5dabceSDavid Gibson * 10393f5dabceSDavid Gibson * While an additional ibm,extended-os-term property indicates 10403f5dabceSDavid Gibson * that rtas call return will always occur. Set this property. 10413f5dabceSDavid Gibson */ 10423f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,extended-os-term", NULL, 0)); 10433f5dabceSDavid Gibson 10443f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,lrdr-capacity", 10453f5dabceSDavid Gibson lrdr_capacity, sizeof(lrdr_capacity))); 10463f5dabceSDavid Gibson 10473f5dabceSDavid Gibson spapr_dt_rtas_tokens(fdt, rtas); 10483f5dabceSDavid Gibson } 10493f5dabceSDavid Gibson 1050db592b5bSCédric Le Goater /* 1051db592b5bSCédric Le Goater * Prepare ibm,arch-vec-5-platform-support, which indicates the MMU 1052db592b5bSCédric Le Goater * and the XIVE features that the guest may request and thus the valid 1053db592b5bSCédric Le Goater * values for bytes 23..26 of option vector 5: 1054db592b5bSCédric Le Goater */ 1055ce2918cbSDavid Gibson static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt, 1056db592b5bSCédric Le Goater int chosen) 10579fb4541fSSam Bobroff { 1058545d6e2bSSuraj Jitindar Singh PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); 1059545d6e2bSSuraj Jitindar Singh 1060f2b14e3aSCédric Le Goater char val[2 * 4] = { 1061ca62823bSDavid Gibson 23, 0x00, /* XICS / XIVE mode */ 10629fb4541fSSam Bobroff 24, 0x00, /* Hash/Radix, filled in below. */ 10639fb4541fSSam Bobroff 25, 0x00, /* Hash options: Segment Tables == no, GTSE == no. */ 10649fb4541fSSam Bobroff 26, 0x40, /* Radix options: GTSE == yes. */ 10659fb4541fSSam Bobroff }; 10669fb4541fSSam Bobroff 1067ca62823bSDavid Gibson if (spapr->irq->xics && spapr->irq->xive) { 1068ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_BOTH; 1069ca62823bSDavid Gibson } else if (spapr->irq->xive) { 1070ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_EXPLOIT; 1071ca62823bSDavid Gibson } else { 1072ca62823bSDavid Gibson assert(spapr->irq->xics); 1073ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_LEGACY; 1074ca62823bSDavid Gibson } 1075ca62823bSDavid Gibson 10767abd43baSSuraj Jitindar Singh if (!ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0, 10777abd43baSSuraj Jitindar Singh first_ppc_cpu->compat_pvr)) { 1078db592b5bSCédric Le Goater /* 1079db592b5bSCédric Le Goater * If we're in a pre POWER9 compat mode then the guest should 1080db592b5bSCédric Le Goater * do hash and use the legacy interrupt mode 1081db592b5bSCédric Le Goater */ 1082ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_LEGACY; /* XICS */ 10837abd43baSSuraj Jitindar Singh val[3] = 0x00; /* Hash */ 10847abd43baSSuraj Jitindar Singh } else if (kvm_enabled()) { 10859fb4541fSSam Bobroff if (kvmppc_has_cap_mmu_radix() && kvmppc_has_cap_mmu_hash_v3()) { 1086f2b14e3aSCédric Le Goater val[3] = 0x80; /* OV5_MMU_BOTH */ 10879fb4541fSSam Bobroff } else if (kvmppc_has_cap_mmu_radix()) { 1088f2b14e3aSCédric Le Goater val[3] = 0x40; /* OV5_MMU_RADIX_300 */ 10899fb4541fSSam Bobroff } else { 1090f2b14e3aSCédric Le Goater val[3] = 0x00; /* Hash */ 10919fb4541fSSam Bobroff } 10929fb4541fSSam Bobroff } else { 10937abd43baSSuraj Jitindar Singh /* V3 MMU supports both hash and radix in tcg (with dynamic switching) */ 1094f2b14e3aSCédric Le Goater val[3] = 0xC0; 1095545d6e2bSSuraj Jitindar Singh } 10969fb4541fSSam Bobroff _FDT(fdt_setprop(fdt, chosen, "ibm,arch-vec-5-platform-support", 10979fb4541fSSam Bobroff val, sizeof(val))); 10989fb4541fSSam Bobroff } 10999fb4541fSSam Bobroff 1100ce2918cbSDavid Gibson static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt) 11017c866c6aSDavid Gibson { 11027c866c6aSDavid Gibson MachineState *machine = MACHINE(spapr); 11036c3829a2SAlexey Kardashevskiy SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 11047c866c6aSDavid Gibson int chosen; 11057c866c6aSDavid Gibson const char *boot_device = machine->boot_order; 11067c866c6aSDavid Gibson char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus); 11077c866c6aSDavid Gibson size_t cb = 0; 1108907aac2fSMark Cave-Ayland char *bootlist = get_boot_devices_list(&cb); 11097c866c6aSDavid Gibson 11107c866c6aSDavid Gibson _FDT(chosen = fdt_add_subnode(fdt, 0, "chosen")); 11117c866c6aSDavid Gibson 11125ced7895SAlexey Kardashevskiy if (machine->kernel_cmdline && machine->kernel_cmdline[0]) { 11135ced7895SAlexey Kardashevskiy _FDT(fdt_setprop_string(fdt, chosen, "bootargs", 11145ced7895SAlexey Kardashevskiy machine->kernel_cmdline)); 11155ced7895SAlexey Kardashevskiy } 11165ced7895SAlexey Kardashevskiy if (spapr->initrd_size) { 11177c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-start", 11187c866c6aSDavid Gibson spapr->initrd_base)); 11197c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-end", 11207c866c6aSDavid Gibson spapr->initrd_base + spapr->initrd_size)); 11215ced7895SAlexey Kardashevskiy } 11227c866c6aSDavid Gibson 11237c866c6aSDavid Gibson if (spapr->kernel_size) { 11247c866c6aSDavid Gibson uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR), 11257c866c6aSDavid Gibson cpu_to_be64(spapr->kernel_size) }; 11267c866c6aSDavid Gibson 11277c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel", 11287c866c6aSDavid Gibson &kprop, sizeof(kprop))); 11297c866c6aSDavid Gibson if (spapr->kernel_le) { 11307c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel-le", NULL, 0)); 11317c866c6aSDavid Gibson } 11327c866c6aSDavid Gibson } 11337c866c6aSDavid Gibson if (boot_menu) { 11347c866c6aSDavid Gibson _FDT((fdt_setprop_cell(fdt, chosen, "qemu,boot-menu", boot_menu))); 11357c866c6aSDavid Gibson } 11367c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-width", graphic_width)); 11377c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-height", graphic_height)); 11387c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-depth", graphic_depth)); 11397c866c6aSDavid Gibson 11407c866c6aSDavid Gibson if (cb && bootlist) { 11417c866c6aSDavid Gibson int i; 11427c866c6aSDavid Gibson 11437c866c6aSDavid Gibson for (i = 0; i < cb; i++) { 11447c866c6aSDavid Gibson if (bootlist[i] == '\n') { 11457c866c6aSDavid Gibson bootlist[i] = ' '; 11467c866c6aSDavid Gibson } 11477c866c6aSDavid Gibson } 11487c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-list", bootlist)); 11497c866c6aSDavid Gibson } 11507c866c6aSDavid Gibson 11517c866c6aSDavid Gibson if (boot_device && strlen(boot_device)) { 11527c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-device", boot_device)); 11537c866c6aSDavid Gibson } 11547c866c6aSDavid Gibson 11557c866c6aSDavid Gibson if (!spapr->has_graphics && stdout_path) { 115690ee4e01SNikunj A Dadhania /* 115790ee4e01SNikunj A Dadhania * "linux,stdout-path" and "stdout" properties are deprecated by linux 115890ee4e01SNikunj A Dadhania * kernel. New platforms should only use the "stdout-path" property. Set 115990ee4e01SNikunj A Dadhania * the new property and continue using older property to remain 116090ee4e01SNikunj A Dadhania * compatible with the existing firmware. 116190ee4e01SNikunj A Dadhania */ 11627c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "linux,stdout-path", stdout_path)); 116390ee4e01SNikunj A Dadhania _FDT(fdt_setprop_string(fdt, chosen, "stdout-path", stdout_path)); 11647c866c6aSDavid Gibson } 11657c866c6aSDavid Gibson 11666c3829a2SAlexey Kardashevskiy /* We can deal with BAR reallocation just fine, advertise it to the guest */ 11676c3829a2SAlexey Kardashevskiy if (smc->linux_pci_probe) { 11686c3829a2SAlexey Kardashevskiy _FDT(fdt_setprop_cell(fdt, chosen, "linux,pci-probe-only", 0)); 11696c3829a2SAlexey Kardashevskiy } 11706c3829a2SAlexey Kardashevskiy 1171db592b5bSCédric Le Goater spapr_dt_ov5_platform_support(spapr, fdt, chosen); 11729fb4541fSSam Bobroff 11737c866c6aSDavid Gibson g_free(stdout_path); 11747c866c6aSDavid Gibson g_free(bootlist); 11757c866c6aSDavid Gibson } 11767c866c6aSDavid Gibson 1177ce2918cbSDavid Gibson static void spapr_dt_hypervisor(SpaprMachineState *spapr, void *fdt) 1178fca5f2dcSDavid Gibson { 1179fca5f2dcSDavid Gibson /* The /hypervisor node isn't in PAPR - this is a hack to allow PR 1180fca5f2dcSDavid Gibson * KVM to work under pHyp with some guest co-operation */ 1181fca5f2dcSDavid Gibson int hypervisor; 1182fca5f2dcSDavid Gibson uint8_t hypercall[16]; 1183fca5f2dcSDavid Gibson 1184fca5f2dcSDavid Gibson _FDT(hypervisor = fdt_add_subnode(fdt, 0, "hypervisor")); 1185fca5f2dcSDavid Gibson /* indicate KVM hypercall interface */ 1186fca5f2dcSDavid Gibson _FDT(fdt_setprop_string(fdt, hypervisor, "compatible", "linux,kvm")); 1187fca5f2dcSDavid Gibson if (kvmppc_has_cap_fixup_hcalls()) { 1188fca5f2dcSDavid Gibson /* 1189fca5f2dcSDavid Gibson * Older KVM versions with older guest kernels were broken 1190fca5f2dcSDavid Gibson * with the magic page, don't allow the guest to map it. 1191fca5f2dcSDavid Gibson */ 1192fca5f2dcSDavid Gibson if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall, 1193fca5f2dcSDavid Gibson sizeof(hypercall))) { 1194fca5f2dcSDavid Gibson _FDT(fdt_setprop(fdt, hypervisor, "hcall-instructions", 1195fca5f2dcSDavid Gibson hypercall, sizeof(hypercall))); 1196fca5f2dcSDavid Gibson } 1197fca5f2dcSDavid Gibson } 1198fca5f2dcSDavid Gibson } 1199fca5f2dcSDavid Gibson 1200ce2918cbSDavid Gibson static void *spapr_build_fdt(SpaprMachineState *spapr) 120153018216SPaolo Bonzini { 1202c86c1affSDaniel Henrique Barboza MachineState *machine = MACHINE(spapr); 12033c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 1204ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 12057c866c6aSDavid Gibson int ret; 120653018216SPaolo Bonzini void *fdt; 1207ce2918cbSDavid Gibson SpaprPhbState *phb; 1208398a0bd5SDavid Gibson char *buf; 120953018216SPaolo Bonzini 1210398a0bd5SDavid Gibson fdt = g_malloc0(FDT_MAX_SIZE); 1211398a0bd5SDavid Gibson _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 121253018216SPaolo Bonzini 1213398a0bd5SDavid Gibson /* Root node */ 1214398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "device_type", "chrp")); 1215398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "model", "IBM pSeries (emulated by qemu)")); 1216398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "compatible", "qemu,pseries")); 1217398a0bd5SDavid Gibson 12180a794529SDavid Gibson /* Guest UUID & Name*/ 1219398a0bd5SDavid Gibson buf = qemu_uuid_unparse_strdup(&qemu_uuid); 1220398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "vm,uuid", buf)); 1221398a0bd5SDavid Gibson if (qemu_uuid_set) { 1222398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "system-id", buf)); 1223398a0bd5SDavid Gibson } 1224398a0bd5SDavid Gibson g_free(buf); 1225398a0bd5SDavid Gibson 1226398a0bd5SDavid Gibson if (qemu_get_vm_name()) { 1227398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "ibm,partition-name", 1228398a0bd5SDavid Gibson qemu_get_vm_name())); 1229398a0bd5SDavid Gibson } 1230398a0bd5SDavid Gibson 12310a794529SDavid Gibson /* Host Model & Serial Number */ 12320a794529SDavid Gibson if (spapr->host_model) { 12330a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model)); 12340a794529SDavid Gibson } else if (smc->broken_host_serial_model && kvmppc_get_host_model(&buf)) { 12350a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-model", buf)); 12360a794529SDavid Gibson g_free(buf); 12370a794529SDavid Gibson } 12380a794529SDavid Gibson 12390a794529SDavid Gibson if (spapr->host_serial) { 12400a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial)); 12410a794529SDavid Gibson } else if (smc->broken_host_serial_model && kvmppc_get_host_serial(&buf)) { 12420a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf)); 12430a794529SDavid Gibson g_free(buf); 12440a794529SDavid Gibson } 12450a794529SDavid Gibson 1246398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#address-cells", 2)); 1247398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2)); 124853018216SPaolo Bonzini 1249fc7e0765SDavid Gibson /* /interrupt controller */ 12503ba3d0bcSCédric Le Goater spapr->irq->dt_populate(spapr, spapr_max_server_number(spapr), fdt, 12515c7adcf4SGreg Kurz PHANDLE_INTC); 1252fc7e0765SDavid Gibson 1253e8f986fcSBharata B Rao ret = spapr_populate_memory(spapr, fdt); 1254e8f986fcSBharata B Rao if (ret < 0) { 1255ce9863b7SCédric Le Goater error_report("couldn't setup memory nodes in fdt"); 1256e8f986fcSBharata B Rao exit(1); 125753018216SPaolo Bonzini } 125853018216SPaolo Bonzini 1259bf5a6696SDavid Gibson /* /vdevice */ 1260bf5a6696SDavid Gibson spapr_dt_vdevice(spapr->vio_bus, fdt); 126153018216SPaolo Bonzini 12624d9392beSThomas Huth if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) { 12634d9392beSThomas Huth ret = spapr_rng_populate_dt(fdt); 12644d9392beSThomas Huth if (ret < 0) { 1265ce9863b7SCédric Le Goater error_report("could not set up rng device in the fdt"); 12664d9392beSThomas Huth exit(1); 12674d9392beSThomas Huth } 12684d9392beSThomas Huth } 12694d9392beSThomas Huth 127053018216SPaolo Bonzini QLIST_FOREACH(phb, &spapr->phbs, list) { 1271466e8831SDavid Gibson ret = spapr_dt_phb(phb, PHANDLE_INTC, fdt, spapr->irq->nr_msis, NULL); 127253018216SPaolo Bonzini if (ret < 0) { 1273da34fed7SThomas Huth error_report("couldn't setup PCI devices in fdt"); 127453018216SPaolo Bonzini exit(1); 127553018216SPaolo Bonzini } 1276da34fed7SThomas Huth } 127753018216SPaolo Bonzini 12780da6f3feSBharata B Rao /* cpus */ 12790da6f3feSBharata B Rao spapr_populate_cpus_dt_node(fdt, spapr); 128053018216SPaolo Bonzini 1281c20d332aSBharata B Rao if (smc->dr_lmb_enabled) { 12829e7d38e8SDavid Gibson _FDT(spapr_dt_drc(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB)); 1283c20d332aSBharata B Rao } 1284c20d332aSBharata B Rao 1285c5514d0eSIgor Mammedov if (mc->has_hotpluggable_cpus) { 1286af81cf32SBharata B Rao int offset = fdt_path_offset(fdt, "/cpus"); 12879e7d38e8SDavid Gibson ret = spapr_dt_drc(fdt, offset, NULL, SPAPR_DR_CONNECTOR_TYPE_CPU); 1288af81cf32SBharata B Rao if (ret < 0) { 1289af81cf32SBharata B Rao error_report("Couldn't set up CPU DR device tree properties"); 1290af81cf32SBharata B Rao exit(1); 1291af81cf32SBharata B Rao } 1292af81cf32SBharata B Rao } 1293af81cf32SBharata B Rao 1294ffb1e275SDavid Gibson /* /event-sources */ 1295ffbb1705SMichael Roth spapr_dt_events(spapr, fdt); 1296ffb1e275SDavid Gibson 12973f5dabceSDavid Gibson /* /rtas */ 12983f5dabceSDavid Gibson spapr_dt_rtas(spapr, fdt); 12993f5dabceSDavid Gibson 13007c866c6aSDavid Gibson /* /chosen */ 13017c866c6aSDavid Gibson spapr_dt_chosen(spapr, fdt); 1302cf6e5223SDavid Gibson 1303fca5f2dcSDavid Gibson /* /hypervisor */ 1304fca5f2dcSDavid Gibson if (kvm_enabled()) { 1305fca5f2dcSDavid Gibson spapr_dt_hypervisor(spapr, fdt); 1306fca5f2dcSDavid Gibson } 1307fca5f2dcSDavid Gibson 1308cf6e5223SDavid Gibson /* Build memory reserve map */ 1309cf6e5223SDavid Gibson if (spapr->kernel_size) { 1310cf6e5223SDavid Gibson _FDT((fdt_add_mem_rsv(fdt, KERNEL_LOAD_ADDR, spapr->kernel_size))); 1311cf6e5223SDavid Gibson } 1312cf6e5223SDavid Gibson if (spapr->initrd_size) { 1313cf6e5223SDavid Gibson _FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base, spapr->initrd_size))); 1314cf6e5223SDavid Gibson } 1315cf6e5223SDavid Gibson 13166787d27bSMichael Roth /* ibm,client-architecture-support updates */ 13176787d27bSMichael Roth ret = spapr_dt_cas_updates(spapr, fdt, spapr->ov5_cas); 13186787d27bSMichael Roth if (ret < 0) { 13196787d27bSMichael Roth error_report("couldn't setup CAS properties fdt"); 13206787d27bSMichael Roth exit(1); 13216787d27bSMichael Roth } 13226787d27bSMichael Roth 13233998ccd0SNathan Fontenot if (smc->dr_phb_enabled) { 13249e7d38e8SDavid Gibson ret = spapr_dt_drc(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_PHB); 13253998ccd0SNathan Fontenot if (ret < 0) { 13263998ccd0SNathan Fontenot error_report("Couldn't set up PHB DR device tree properties"); 13273998ccd0SNathan Fontenot exit(1); 13283998ccd0SNathan Fontenot } 13293998ccd0SNathan Fontenot } 13303998ccd0SNathan Fontenot 1331997b6cfcSDavid Gibson return fdt; 133253018216SPaolo Bonzini } 133353018216SPaolo Bonzini 133453018216SPaolo Bonzini static uint64_t translate_kernel_address(void *opaque, uint64_t addr) 133553018216SPaolo Bonzini { 133653018216SPaolo Bonzini return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR; 133753018216SPaolo Bonzini } 133853018216SPaolo Bonzini 13391d1be34dSDavid Gibson static void emulate_spapr_hypercall(PPCVirtualHypervisor *vhyp, 13401d1be34dSDavid Gibson PowerPCCPU *cpu) 134153018216SPaolo Bonzini { 134253018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 134353018216SPaolo Bonzini 13448d04fb55SJan Kiszka /* The TCG path should also be holding the BQL at this point */ 13458d04fb55SJan Kiszka g_assert(qemu_mutex_iothread_locked()); 13468d04fb55SJan Kiszka 134753018216SPaolo Bonzini if (msr_pr) { 134853018216SPaolo Bonzini hcall_dprintf("Hypercall made with MSR[PR]=1\n"); 134953018216SPaolo Bonzini env->gpr[3] = H_PRIVILEGE; 135053018216SPaolo Bonzini } else { 135153018216SPaolo Bonzini env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]); 135253018216SPaolo Bonzini } 135353018216SPaolo Bonzini } 135453018216SPaolo Bonzini 135500fd075eSBenjamin Herrenschmidt struct LPCRSyncState { 135600fd075eSBenjamin Herrenschmidt target_ulong value; 135700fd075eSBenjamin Herrenschmidt target_ulong mask; 135800fd075eSBenjamin Herrenschmidt }; 135900fd075eSBenjamin Herrenschmidt 136000fd075eSBenjamin Herrenschmidt static void do_lpcr_sync(CPUState *cs, run_on_cpu_data arg) 136100fd075eSBenjamin Herrenschmidt { 136200fd075eSBenjamin Herrenschmidt struct LPCRSyncState *s = arg.host_ptr; 136300fd075eSBenjamin Herrenschmidt PowerPCCPU *cpu = POWERPC_CPU(cs); 136400fd075eSBenjamin Herrenschmidt CPUPPCState *env = &cpu->env; 136500fd075eSBenjamin Herrenschmidt target_ulong lpcr; 136600fd075eSBenjamin Herrenschmidt 136700fd075eSBenjamin Herrenschmidt cpu_synchronize_state(cs); 136800fd075eSBenjamin Herrenschmidt lpcr = env->spr[SPR_LPCR]; 136900fd075eSBenjamin Herrenschmidt lpcr &= ~s->mask; 137000fd075eSBenjamin Herrenschmidt lpcr |= s->value; 137100fd075eSBenjamin Herrenschmidt ppc_store_lpcr(cpu, lpcr); 137200fd075eSBenjamin Herrenschmidt } 137300fd075eSBenjamin Herrenschmidt 137400fd075eSBenjamin Herrenschmidt void spapr_set_all_lpcrs(target_ulong value, target_ulong mask) 137500fd075eSBenjamin Herrenschmidt { 137600fd075eSBenjamin Herrenschmidt CPUState *cs; 137700fd075eSBenjamin Herrenschmidt struct LPCRSyncState s = { 137800fd075eSBenjamin Herrenschmidt .value = value, 137900fd075eSBenjamin Herrenschmidt .mask = mask 138000fd075eSBenjamin Herrenschmidt }; 138100fd075eSBenjamin Herrenschmidt CPU_FOREACH(cs) { 138200fd075eSBenjamin Herrenschmidt run_on_cpu(cs, do_lpcr_sync, RUN_ON_CPU_HOST_PTR(&s)); 138300fd075eSBenjamin Herrenschmidt } 138400fd075eSBenjamin Herrenschmidt } 138500fd075eSBenjamin Herrenschmidt 138679825f4dSBenjamin Herrenschmidt static void spapr_get_pate(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry) 13879861bb3eSSuraj Jitindar Singh { 1388ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 13899861bb3eSSuraj Jitindar Singh 139079825f4dSBenjamin Herrenschmidt /* Copy PATE1:GR into PATE0:HR */ 139179825f4dSBenjamin Herrenschmidt entry->dw0 = spapr->patb_entry & PATE0_HR; 139279825f4dSBenjamin Herrenschmidt entry->dw1 = spapr->patb_entry; 13939861bb3eSSuraj Jitindar Singh } 13949861bb3eSSuraj Jitindar Singh 1395e6b8fd24SSamuel Mendoza-Jonas #define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2)) 1396e6b8fd24SSamuel Mendoza-Jonas #define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID) 1397e6b8fd24SSamuel Mendoza-Jonas #define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY) 1398e6b8fd24SSamuel Mendoza-Jonas #define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY)) 1399e6b8fd24SSamuel Mendoza-Jonas #define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY)) 1400e6b8fd24SSamuel Mendoza-Jonas 1401715c5407SDavid Gibson /* 1402715c5407SDavid Gibson * Get the fd to access the kernel htab, re-opening it if necessary 1403715c5407SDavid Gibson */ 1404ce2918cbSDavid Gibson static int get_htab_fd(SpaprMachineState *spapr) 1405715c5407SDavid Gibson { 140614b0d748SGreg Kurz Error *local_err = NULL; 140714b0d748SGreg Kurz 1408715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1409715c5407SDavid Gibson return spapr->htab_fd; 1410715c5407SDavid Gibson } 1411715c5407SDavid Gibson 141214b0d748SGreg Kurz spapr->htab_fd = kvmppc_get_htab_fd(false, 0, &local_err); 1413715c5407SDavid Gibson if (spapr->htab_fd < 0) { 141414b0d748SGreg Kurz error_report_err(local_err); 1415715c5407SDavid Gibson } 1416715c5407SDavid Gibson 1417715c5407SDavid Gibson return spapr->htab_fd; 1418715c5407SDavid Gibson } 1419715c5407SDavid Gibson 1420ce2918cbSDavid Gibson void close_htab_fd(SpaprMachineState *spapr) 1421715c5407SDavid Gibson { 1422715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1423715c5407SDavid Gibson close(spapr->htab_fd); 1424715c5407SDavid Gibson } 1425715c5407SDavid Gibson spapr->htab_fd = -1; 1426715c5407SDavid Gibson } 1427715c5407SDavid Gibson 1428e57ca75cSDavid Gibson static hwaddr spapr_hpt_mask(PPCVirtualHypervisor *vhyp) 1429e57ca75cSDavid Gibson { 1430ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1431e57ca75cSDavid Gibson 1432e57ca75cSDavid Gibson return HTAB_SIZE(spapr) / HASH_PTEG_SIZE_64 - 1; 1433e57ca75cSDavid Gibson } 1434e57ca75cSDavid Gibson 14351ec26c75SGreg Kurz static target_ulong spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp) 14361ec26c75SGreg Kurz { 1437ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 14381ec26c75SGreg Kurz 14391ec26c75SGreg Kurz assert(kvm_enabled()); 14401ec26c75SGreg Kurz 14411ec26c75SGreg Kurz if (!spapr->htab) { 14421ec26c75SGreg Kurz return 0; 14431ec26c75SGreg Kurz } 14441ec26c75SGreg Kurz 14451ec26c75SGreg Kurz return (target_ulong)(uintptr_t)spapr->htab | (spapr->htab_shift - 18); 14461ec26c75SGreg Kurz } 14471ec26c75SGreg Kurz 1448e57ca75cSDavid Gibson static const ppc_hash_pte64_t *spapr_map_hptes(PPCVirtualHypervisor *vhyp, 1449e57ca75cSDavid Gibson hwaddr ptex, int n) 1450e57ca75cSDavid Gibson { 1451ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1452e57ca75cSDavid Gibson hwaddr pte_offset = ptex * HASH_PTE_SIZE_64; 1453e57ca75cSDavid Gibson 1454e57ca75cSDavid Gibson if (!spapr->htab) { 1455e57ca75cSDavid Gibson /* 1456e57ca75cSDavid Gibson * HTAB is controlled by KVM. Fetch into temporary buffer 1457e57ca75cSDavid Gibson */ 1458e57ca75cSDavid Gibson ppc_hash_pte64_t *hptes = g_malloc(n * HASH_PTE_SIZE_64); 1459e57ca75cSDavid Gibson kvmppc_read_hptes(hptes, ptex, n); 1460e57ca75cSDavid Gibson return hptes; 1461e57ca75cSDavid Gibson } 1462e57ca75cSDavid Gibson 1463e57ca75cSDavid Gibson /* 1464e57ca75cSDavid Gibson * HTAB is controlled by QEMU. Just point to the internally 1465e57ca75cSDavid Gibson * accessible PTEG. 1466e57ca75cSDavid Gibson */ 1467e57ca75cSDavid Gibson return (const ppc_hash_pte64_t *)(spapr->htab + pte_offset); 1468e57ca75cSDavid Gibson } 1469e57ca75cSDavid Gibson 1470e57ca75cSDavid Gibson static void spapr_unmap_hptes(PPCVirtualHypervisor *vhyp, 1471e57ca75cSDavid Gibson const ppc_hash_pte64_t *hptes, 1472e57ca75cSDavid Gibson hwaddr ptex, int n) 1473e57ca75cSDavid Gibson { 1474ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1475e57ca75cSDavid Gibson 1476e57ca75cSDavid Gibson if (!spapr->htab) { 1477e57ca75cSDavid Gibson g_free((void *)hptes); 1478e57ca75cSDavid Gibson } 1479e57ca75cSDavid Gibson 1480e57ca75cSDavid Gibson /* Nothing to do for qemu managed HPT */ 1481e57ca75cSDavid Gibson } 1482e57ca75cSDavid Gibson 1483a2dd4e83SBenjamin Herrenschmidt void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex, 1484e57ca75cSDavid Gibson uint64_t pte0, uint64_t pte1) 1485e57ca75cSDavid Gibson { 1486a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(cpu->vhyp); 1487e57ca75cSDavid Gibson hwaddr offset = ptex * HASH_PTE_SIZE_64; 1488e57ca75cSDavid Gibson 1489e57ca75cSDavid Gibson if (!spapr->htab) { 1490e57ca75cSDavid Gibson kvmppc_write_hpte(ptex, pte0, pte1); 1491e57ca75cSDavid Gibson } else { 14923054b0caSBenjamin Herrenschmidt if (pte0 & HPTE64_V_VALID) { 1493e57ca75cSDavid Gibson stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); 14943054b0caSBenjamin Herrenschmidt /* 14953054b0caSBenjamin Herrenschmidt * When setting valid, we write PTE1 first. This ensures 14963054b0caSBenjamin Herrenschmidt * proper synchronization with the reading code in 14973054b0caSBenjamin Herrenschmidt * ppc_hash64_pteg_search() 14983054b0caSBenjamin Herrenschmidt */ 14993054b0caSBenjamin Herrenschmidt smp_wmb(); 15003054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset, pte0); 15013054b0caSBenjamin Herrenschmidt } else { 15023054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset, pte0); 15033054b0caSBenjamin Herrenschmidt /* 15043054b0caSBenjamin Herrenschmidt * When clearing it we set PTE0 first. This ensures proper 15053054b0caSBenjamin Herrenschmidt * synchronization with the reading code in 15063054b0caSBenjamin Herrenschmidt * ppc_hash64_pteg_search() 15073054b0caSBenjamin Herrenschmidt */ 15083054b0caSBenjamin Herrenschmidt smp_wmb(); 15093054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); 15103054b0caSBenjamin Herrenschmidt } 1511e57ca75cSDavid Gibson } 1512e57ca75cSDavid Gibson } 1513e57ca75cSDavid Gibson 1514a2dd4e83SBenjamin Herrenschmidt static void spapr_hpte_set_c(PPCVirtualHypervisor *vhyp, hwaddr ptex, 1515a2dd4e83SBenjamin Herrenschmidt uint64_t pte1) 1516a2dd4e83SBenjamin Herrenschmidt { 1517a2dd4e83SBenjamin Herrenschmidt hwaddr offset = ptex * HASH_PTE_SIZE_64 + 15; 1518a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1519a2dd4e83SBenjamin Herrenschmidt 1520a2dd4e83SBenjamin Herrenschmidt if (!spapr->htab) { 1521a2dd4e83SBenjamin Herrenschmidt /* There should always be a hash table when this is called */ 1522a2dd4e83SBenjamin Herrenschmidt error_report("spapr_hpte_set_c called with no hash table !"); 1523a2dd4e83SBenjamin Herrenschmidt return; 1524a2dd4e83SBenjamin Herrenschmidt } 1525a2dd4e83SBenjamin Herrenschmidt 1526a2dd4e83SBenjamin Herrenschmidt /* The HW performs a non-atomic byte update */ 1527a2dd4e83SBenjamin Herrenschmidt stb_p(spapr->htab + offset, (pte1 & 0xff) | 0x80); 1528a2dd4e83SBenjamin Herrenschmidt } 1529a2dd4e83SBenjamin Herrenschmidt 1530a2dd4e83SBenjamin Herrenschmidt static void spapr_hpte_set_r(PPCVirtualHypervisor *vhyp, hwaddr ptex, 1531a2dd4e83SBenjamin Herrenschmidt uint64_t pte1) 1532a2dd4e83SBenjamin Herrenschmidt { 1533a2dd4e83SBenjamin Herrenschmidt hwaddr offset = ptex * HASH_PTE_SIZE_64 + 14; 1534a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1535a2dd4e83SBenjamin Herrenschmidt 1536a2dd4e83SBenjamin Herrenschmidt if (!spapr->htab) { 1537a2dd4e83SBenjamin Herrenschmidt /* There should always be a hash table when this is called */ 1538a2dd4e83SBenjamin Herrenschmidt error_report("spapr_hpte_set_r called with no hash table !"); 1539a2dd4e83SBenjamin Herrenschmidt return; 1540a2dd4e83SBenjamin Herrenschmidt } 1541a2dd4e83SBenjamin Herrenschmidt 1542a2dd4e83SBenjamin Herrenschmidt /* The HW performs a non-atomic byte update */ 1543a2dd4e83SBenjamin Herrenschmidt stb_p(spapr->htab + offset, ((pte1 >> 8) & 0xff) | 0x01); 1544a2dd4e83SBenjamin Herrenschmidt } 1545a2dd4e83SBenjamin Herrenschmidt 15460b0b8310SDavid Gibson int spapr_hpt_shift_for_ramsize(uint64_t ramsize) 15478dfe8e7fSDavid Gibson { 15488dfe8e7fSDavid Gibson int shift; 15498dfe8e7fSDavid Gibson 15508dfe8e7fSDavid Gibson /* We aim for a hash table of size 1/128 the size of RAM (rounded 15518dfe8e7fSDavid Gibson * up). The PAPR recommendation is actually 1/64 of RAM size, but 15528dfe8e7fSDavid Gibson * that's much more than is needed for Linux guests */ 15538dfe8e7fSDavid Gibson shift = ctz64(pow2ceil(ramsize)) - 7; 15548dfe8e7fSDavid Gibson shift = MAX(shift, 18); /* Minimum architected size */ 15558dfe8e7fSDavid Gibson shift = MIN(shift, 46); /* Maximum architected size */ 15568dfe8e7fSDavid Gibson return shift; 15578dfe8e7fSDavid Gibson } 15588dfe8e7fSDavid Gibson 1559ce2918cbSDavid Gibson void spapr_free_hpt(SpaprMachineState *spapr) 156006ec79e8SBharata B Rao { 156106ec79e8SBharata B Rao g_free(spapr->htab); 156206ec79e8SBharata B Rao spapr->htab = NULL; 156306ec79e8SBharata B Rao spapr->htab_shift = 0; 156406ec79e8SBharata B Rao close_htab_fd(spapr); 156506ec79e8SBharata B Rao } 156606ec79e8SBharata B Rao 1567ce2918cbSDavid Gibson void spapr_reallocate_hpt(SpaprMachineState *spapr, int shift, 1568c5f54f3eSDavid Gibson Error **errp) 156953018216SPaolo Bonzini { 1570c5f54f3eSDavid Gibson long rc; 157153018216SPaolo Bonzini 1572c5f54f3eSDavid Gibson /* Clean up any HPT info from a previous boot */ 157306ec79e8SBharata B Rao spapr_free_hpt(spapr); 157453018216SPaolo Bonzini 1575c5f54f3eSDavid Gibson rc = kvmppc_reset_htab(shift); 1576c5f54f3eSDavid Gibson if (rc < 0) { 1577c5f54f3eSDavid Gibson /* kernel-side HPT needed, but couldn't allocate one */ 1578c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1579c5f54f3eSDavid Gibson "Failed to allocate KVM HPT of order %d (try smaller maxmem?)", 1580c5f54f3eSDavid Gibson shift); 1581c5f54f3eSDavid Gibson /* This is almost certainly fatal, but if the caller really 1582c5f54f3eSDavid Gibson * wants to carry on with shift == 0, it's welcome to try */ 1583c5f54f3eSDavid Gibson } else if (rc > 0) { 1584c5f54f3eSDavid Gibson /* kernel-side HPT allocated */ 1585c5f54f3eSDavid Gibson if (rc != shift) { 1586c5f54f3eSDavid Gibson error_setg(errp, 1587c5f54f3eSDavid Gibson "Requested order %d HPT, but kernel allocated order %ld (try smaller maxmem?)", 1588c5f54f3eSDavid Gibson shift, rc); 15897735fedaSBharata B Rao } 15907735fedaSBharata B Rao 159153018216SPaolo Bonzini spapr->htab_shift = shift; 1592c18ad9a5SDavid Gibson spapr->htab = NULL; 1593b817772aSBharata B Rao } else { 1594c5f54f3eSDavid Gibson /* kernel-side HPT not needed, allocate in userspace instead */ 1595c5f54f3eSDavid Gibson size_t size = 1ULL << shift; 1596c5f54f3eSDavid Gibson int i; 159701a57972SSamuel Mendoza-Jonas 1598c5f54f3eSDavid Gibson spapr->htab = qemu_memalign(size, size); 1599c5f54f3eSDavid Gibson if (!spapr->htab) { 1600c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1601c5f54f3eSDavid Gibson "Could not allocate HPT of order %d", shift); 1602c5f54f3eSDavid Gibson return; 1603b817772aSBharata B Rao } 1604b817772aSBharata B Rao 1605c5f54f3eSDavid Gibson memset(spapr->htab, 0, size); 1606c5f54f3eSDavid Gibson spapr->htab_shift = shift; 1607b817772aSBharata B Rao 1608c5f54f3eSDavid Gibson for (i = 0; i < size / HASH_PTE_SIZE_64; i++) { 1609c5f54f3eSDavid Gibson DIRTY_HPTE(HPTE(spapr->htab, i)); 16107735fedaSBharata B Rao } 161153018216SPaolo Bonzini } 1612ee4d9eccSSuraj Jitindar Singh /* We're setting up a hash table, so that means we're not radix */ 1613176dcceeSSuraj Jitindar Singh spapr->patb_entry = 0; 161400fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(0, LPCR_HR | LPCR_UPRT); 161553018216SPaolo Bonzini } 161653018216SPaolo Bonzini 1617ce2918cbSDavid Gibson void spapr_setup_hpt_and_vrma(SpaprMachineState *spapr) 1618b4db5413SSuraj Jitindar Singh { 16192772cf6bSDavid Gibson int hpt_shift; 16202772cf6bSDavid Gibson 16212772cf6bSDavid Gibson if ((spapr->resize_hpt == SPAPR_RESIZE_HPT_DISABLED) 16222772cf6bSDavid Gibson || (spapr->cas_reboot 16232772cf6bSDavid Gibson && !spapr_ovec_test(spapr->ov5_cas, OV5_HPT_RESIZE))) { 16242772cf6bSDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(MACHINE(spapr)->maxram_size); 16252772cf6bSDavid Gibson } else { 1626768a20f3SDavid Gibson uint64_t current_ram_size; 1627768a20f3SDavid Gibson 1628768a20f3SDavid Gibson current_ram_size = MACHINE(spapr)->ram_size + get_plugged_memory_size(); 1629768a20f3SDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(current_ram_size); 16302772cf6bSDavid Gibson } 16312772cf6bSDavid Gibson spapr_reallocate_hpt(spapr, hpt_shift, &error_fatal); 16322772cf6bSDavid Gibson 1633b4db5413SSuraj Jitindar Singh if (spapr->vrma_adjust) { 1634c86c1affSDaniel Henrique Barboza spapr->rma_size = kvmppc_rma_size(spapr_node0_size(MACHINE(spapr)), 1635b4db5413SSuraj Jitindar Singh spapr->htab_shift); 1636b4db5413SSuraj Jitindar Singh } 1637b4db5413SSuraj Jitindar Singh } 1638b4db5413SSuraj Jitindar Singh 163982512483SGreg Kurz static int spapr_reset_drcs(Object *child, void *opaque) 164082512483SGreg Kurz { 1641ce2918cbSDavid Gibson SpaprDrc *drc = 1642ce2918cbSDavid Gibson (SpaprDrc *) object_dynamic_cast(child, 164382512483SGreg Kurz TYPE_SPAPR_DR_CONNECTOR); 164482512483SGreg Kurz 164582512483SGreg Kurz if (drc) { 164682512483SGreg Kurz spapr_drc_reset(drc); 164782512483SGreg Kurz } 164882512483SGreg Kurz 164982512483SGreg Kurz return 0; 165082512483SGreg Kurz } 165182512483SGreg Kurz 1652a0628599SLike Xu static void spapr_machine_reset(MachineState *machine) 165353018216SPaolo Bonzini { 1654ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(machine); 1655182735efSAndreas Färber PowerPCCPU *first_ppc_cpu; 1656744a928cSAlexey Kardashevskiy hwaddr fdt_addr; 1657997b6cfcSDavid Gibson void *fdt; 1658997b6cfcSDavid Gibson int rc; 1659259186a7SAndreas Färber 16609f6edd06SDavid Gibson spapr_caps_apply(spapr); 166133face6bSDavid Gibson 16621481fe5fSLaurent Vivier first_ppc_cpu = POWERPC_CPU(first_cpu); 16631481fe5fSLaurent Vivier if (kvm_enabled() && kvmppc_has_cap_mmu_radix() && 1664ad99d04cSDavid Gibson ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, 16651481fe5fSLaurent Vivier spapr->max_compat_pvr)) { 166679825f4dSBenjamin Herrenschmidt /* 166779825f4dSBenjamin Herrenschmidt * If using KVM with radix mode available, VCPUs can be started 1668b4db5413SSuraj Jitindar Singh * without a HPT because KVM will start them in radix mode. 166979825f4dSBenjamin Herrenschmidt * Set the GR bit in PATE so that we know there is no HPT. 167079825f4dSBenjamin Herrenschmidt */ 167179825f4dSBenjamin Herrenschmidt spapr->patb_entry = PATE1_GR; 167200fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(LPCR_HR | LPCR_UPRT, LPCR_HR | LPCR_UPRT); 1673b4db5413SSuraj Jitindar Singh } else { 1674b4db5413SSuraj Jitindar Singh spapr_setup_hpt_and_vrma(spapr); 1675c5f54f3eSDavid Gibson } 167653018216SPaolo Bonzini 167725c9780dSDavid Gibson qemu_devices_reset(); 167825c9780dSDavid Gibson 167925c9780dSDavid Gibson /* 168079825f4dSBenjamin Herrenschmidt * If this reset wasn't generated by CAS, we should reset our 168179825f4dSBenjamin Herrenschmidt * negotiated options and start from scratch 168279825f4dSBenjamin Herrenschmidt */ 16839012a53fSGreg Kurz if (!spapr->cas_reboot) { 16849012a53fSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas); 16859012a53fSGreg Kurz spapr->ov5_cas = spapr_ovec_new(); 16869012a53fSGreg Kurz 1687ce03a193SLaurent Vivier ppc_set_compat_all(spapr->max_compat_pvr, &error_fatal); 16889012a53fSGreg Kurz } 16899012a53fSGreg Kurz 1690ec132efaSAlexey Kardashevskiy /* 1691b2e22477SCédric Le Goater * This is fixing some of the default configuration of the XIVE 1692b2e22477SCédric Le Goater * devices. To be called after the reset of the machine devices. 1693b2e22477SCédric Le Goater */ 1694b2e22477SCédric Le Goater spapr_irq_reset(spapr, &error_fatal); 1695b2e22477SCédric Le Goater 169623ff81bdSGreg Kurz /* 169723ff81bdSGreg Kurz * There is no CAS under qtest. Simulate one to please the code that 169823ff81bdSGreg Kurz * depends on spapr->ov5_cas. This is especially needed to test device 169923ff81bdSGreg Kurz * unplug, so we do that before resetting the DRCs. 170023ff81bdSGreg Kurz */ 170123ff81bdSGreg Kurz if (qtest_enabled()) { 170223ff81bdSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas); 170323ff81bdSGreg Kurz spapr->ov5_cas = spapr_ovec_clone(spapr->ov5); 170423ff81bdSGreg Kurz } 170523ff81bdSGreg Kurz 170682512483SGreg Kurz /* DRC reset may cause a device to be unplugged. This will cause troubles 170782512483SGreg Kurz * if this device is used by another device (eg, a running vhost backend 170882512483SGreg Kurz * will crash QEMU if the DIMM holding the vring goes away). To avoid such 170982512483SGreg Kurz * situations, we reset DRCs after all devices have been reset. 171082512483SGreg Kurz */ 171182512483SGreg Kurz object_child_foreach_recursive(object_get_root(), spapr_reset_drcs, NULL); 171282512483SGreg Kurz 171356258174SDaniel Henrique Barboza spapr_clear_pending_events(spapr); 171453018216SPaolo Bonzini 1715b7d1f77aSBenjamin Herrenschmidt /* 1716b7d1f77aSBenjamin Herrenschmidt * We place the device tree and RTAS just below either the top of the RMA, 1717df269271SAlexey Kardashevskiy * or just below 2GB, whichever is lower, so that it can be 1718b7d1f77aSBenjamin Herrenschmidt * processed with 32-bit real mode code if necessary 1719b7d1f77aSBenjamin Herrenschmidt */ 1720744a928cSAlexey Kardashevskiy fdt_addr = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FDT_MAX_SIZE; 1721b7d1f77aSBenjamin Herrenschmidt 1722df269271SAlexey Kardashevskiy fdt = spapr_build_fdt(spapr); 172353018216SPaolo Bonzini 1724997b6cfcSDavid Gibson rc = fdt_pack(fdt); 1725997b6cfcSDavid Gibson 1726997b6cfcSDavid Gibson /* Should only fail if we've built a corrupted tree */ 1727997b6cfcSDavid Gibson assert(rc == 0); 1728997b6cfcSDavid Gibson 1729997b6cfcSDavid Gibson if (fdt_totalsize(fdt) > FDT_MAX_SIZE) { 1730997b6cfcSDavid Gibson error_report("FDT too big ! 0x%x bytes (max is 0x%x)", 1731997b6cfcSDavid Gibson fdt_totalsize(fdt), FDT_MAX_SIZE); 1732997b6cfcSDavid Gibson exit(1); 1733997b6cfcSDavid Gibson } 1734997b6cfcSDavid Gibson 1735997b6cfcSDavid Gibson /* Load the fdt */ 1736997b6cfcSDavid Gibson qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 1737cae172abSDavid Gibson cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); 1738fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob); 1739fea35ca4SAlexey Kardashevskiy spapr->fdt_size = fdt_totalsize(fdt); 1740fea35ca4SAlexey Kardashevskiy spapr->fdt_initial_size = spapr->fdt_size; 1741fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = fdt; 1742997b6cfcSDavid Gibson 174353018216SPaolo Bonzini /* Set up the entry state */ 174484369f63SDavid Gibson spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT, fdt_addr); 1745182735efSAndreas Färber first_ppc_cpu->env.gpr[5] = 0; 174653018216SPaolo Bonzini 17476787d27bSMichael Roth spapr->cas_reboot = false; 174853018216SPaolo Bonzini } 174953018216SPaolo Bonzini 1750ce2918cbSDavid Gibson static void spapr_create_nvram(SpaprMachineState *spapr) 175153018216SPaolo Bonzini { 17522ff3de68SMarkus Armbruster DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); 17533978b863SPaolo Bonzini DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); 175453018216SPaolo Bonzini 17553978b863SPaolo Bonzini if (dinfo) { 17566231a6daSMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo), 17576231a6daSMarkus Armbruster &error_fatal); 175853018216SPaolo Bonzini } 175953018216SPaolo Bonzini 176053018216SPaolo Bonzini qdev_init_nofail(dev); 176153018216SPaolo Bonzini 1762ce2918cbSDavid Gibson spapr->nvram = (struct SpaprNvram *)dev; 176353018216SPaolo Bonzini } 176453018216SPaolo Bonzini 1765ce2918cbSDavid Gibson static void spapr_rtc_create(SpaprMachineState *spapr) 176628df36a1SDavid Gibson { 1767f6d4dca8SThomas Huth object_initialize_child(OBJECT(spapr), "rtc", 1768f6d4dca8SThomas Huth &spapr->rtc, sizeof(spapr->rtc), TYPE_SPAPR_RTC, 1769f6d4dca8SThomas Huth &error_fatal, NULL); 1770147ff807SCédric Le Goater object_property_set_bool(OBJECT(&spapr->rtc), true, "realized", 1771147ff807SCédric Le Goater &error_fatal); 1772147ff807SCédric Le Goater object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc), 1773147ff807SCédric Le Goater "date", &error_fatal); 177428df36a1SDavid Gibson } 177528df36a1SDavid Gibson 177653018216SPaolo Bonzini /* Returns whether we want to use VGA or not */ 177714c6a894SDavid Gibson static bool spapr_vga_init(PCIBus *pci_bus, Error **errp) 177853018216SPaolo Bonzini { 177953018216SPaolo Bonzini switch (vga_interface_type) { 178053018216SPaolo Bonzini case VGA_NONE: 17817effdaa3SMark Wu return false; 17827effdaa3SMark Wu case VGA_DEVICE: 17837effdaa3SMark Wu return true; 178453018216SPaolo Bonzini case VGA_STD: 1785b798c190SBenjamin Herrenschmidt case VGA_VIRTIO: 17866e66d0c6SThomas Huth case VGA_CIRRUS: 178753018216SPaolo Bonzini return pci_vga_init(pci_bus) != NULL; 178853018216SPaolo Bonzini default: 178914c6a894SDavid Gibson error_setg(errp, 179014c6a894SDavid Gibson "Unsupported VGA mode, only -vga std or -vga virtio is supported"); 179114c6a894SDavid Gibson return false; 179253018216SPaolo Bonzini } 179353018216SPaolo Bonzini } 179453018216SPaolo Bonzini 17954e5fe368SSuraj Jitindar Singh static int spapr_pre_load(void *opaque) 17964e5fe368SSuraj Jitindar Singh { 17974e5fe368SSuraj Jitindar Singh int rc; 17984e5fe368SSuraj Jitindar Singh 17994e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_load(opaque); 18004e5fe368SSuraj Jitindar Singh if (rc) { 18014e5fe368SSuraj Jitindar Singh return rc; 18024e5fe368SSuraj Jitindar Singh } 18034e5fe368SSuraj Jitindar Singh 18044e5fe368SSuraj Jitindar Singh return 0; 18054e5fe368SSuraj Jitindar Singh } 18064e5fe368SSuraj Jitindar Singh 1807880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id) 1808880ae7deSDavid Gibson { 1809ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 1810880ae7deSDavid Gibson int err = 0; 1811880ae7deSDavid Gibson 1812be85537dSDavid Gibson err = spapr_caps_post_migration(spapr); 1813be85537dSDavid Gibson if (err) { 1814be85537dSDavid Gibson return err; 1815be85537dSDavid Gibson } 1816be85537dSDavid Gibson 1817e502202cSCédric Le Goater /* 1818e502202cSCédric Le Goater * In earlier versions, there was no separate qdev for the PAPR 1819880ae7deSDavid Gibson * RTC, so the RTC offset was stored directly in sPAPREnvironment. 1820880ae7deSDavid Gibson * So when migrating from those versions, poke the incoming offset 1821e502202cSCédric Le Goater * value into the RTC device 1822e502202cSCédric Le Goater */ 1823880ae7deSDavid Gibson if (version_id < 3) { 1824147ff807SCédric Le Goater err = spapr_rtc_import_offset(&spapr->rtc, spapr->rtc_offset); 1825e502202cSCédric Le Goater if (err) { 1826e502202cSCédric Le Goater return err; 1827e502202cSCédric Le Goater } 1828880ae7deSDavid Gibson } 1829880ae7deSDavid Gibson 18300c86b2dfSLaurent Vivier if (kvm_enabled() && spapr->patb_entry) { 1831d39c90f5SBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(first_cpu); 183279825f4dSBenjamin Herrenschmidt bool radix = !!(spapr->patb_entry & PATE1_GR); 1833d39c90f5SBharata B Rao bool gtse = !!(cpu->env.spr[SPR_LPCR] & LPCR_GTSE); 1834d39c90f5SBharata B Rao 183500fd075eSBenjamin Herrenschmidt /* 183600fd075eSBenjamin Herrenschmidt * Update LPCR:HR and UPRT as they may not be set properly in 183700fd075eSBenjamin Herrenschmidt * the stream 183800fd075eSBenjamin Herrenschmidt */ 183900fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(radix ? (LPCR_HR | LPCR_UPRT) : 0, 184000fd075eSBenjamin Herrenschmidt LPCR_HR | LPCR_UPRT); 184100fd075eSBenjamin Herrenschmidt 1842d39c90f5SBharata B Rao err = kvmppc_configure_v3_mmu(cpu, radix, gtse, spapr->patb_entry); 1843d39c90f5SBharata B Rao if (err) { 1844d39c90f5SBharata B Rao error_report("Process table config unsupported by the host"); 1845d39c90f5SBharata B Rao return -EINVAL; 1846d39c90f5SBharata B Rao } 1847d39c90f5SBharata B Rao } 1848d39c90f5SBharata B Rao 18491c53b06cSCédric Le Goater err = spapr_irq_post_load(spapr, version_id); 18501c53b06cSCédric Le Goater if (err) { 18511c53b06cSCédric Le Goater return err; 18521c53b06cSCédric Le Goater } 18531c53b06cSCédric Le Goater 1854880ae7deSDavid Gibson return err; 1855880ae7deSDavid Gibson } 1856880ae7deSDavid Gibson 18574e5fe368SSuraj Jitindar Singh static int spapr_pre_save(void *opaque) 18584e5fe368SSuraj Jitindar Singh { 18594e5fe368SSuraj Jitindar Singh int rc; 18604e5fe368SSuraj Jitindar Singh 18614e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_save(opaque); 18624e5fe368SSuraj Jitindar Singh if (rc) { 18634e5fe368SSuraj Jitindar Singh return rc; 18644e5fe368SSuraj Jitindar Singh } 18654e5fe368SSuraj Jitindar Singh 18664e5fe368SSuraj Jitindar Singh return 0; 18674e5fe368SSuraj Jitindar Singh } 18684e5fe368SSuraj Jitindar Singh 1869880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id) 1870880ae7deSDavid Gibson { 1871880ae7deSDavid Gibson return version_id < 3; 1872880ae7deSDavid Gibson } 1873880ae7deSDavid Gibson 1874fd38804bSDaniel Henrique Barboza static bool spapr_pending_events_needed(void *opaque) 1875fd38804bSDaniel Henrique Barboza { 1876ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 1877fd38804bSDaniel Henrique Barboza return !QTAILQ_EMPTY(&spapr->pending_events); 1878fd38804bSDaniel Henrique Barboza } 1879fd38804bSDaniel Henrique Barboza 1880fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_event_entry = { 1881fd38804bSDaniel Henrique Barboza .name = "spapr_event_log_entry", 1882fd38804bSDaniel Henrique Barboza .version_id = 1, 1883fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1884fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 1885ce2918cbSDavid Gibson VMSTATE_UINT32(summary, SpaprEventLogEntry), 1886ce2918cbSDavid Gibson VMSTATE_UINT32(extended_length, SpaprEventLogEntry), 1887ce2918cbSDavid Gibson VMSTATE_VBUFFER_ALLOC_UINT32(extended_log, SpaprEventLogEntry, 0, 18885341258eSDavid Gibson NULL, extended_length), 1889fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1890fd38804bSDaniel Henrique Barboza }, 1891fd38804bSDaniel Henrique Barboza }; 1892fd38804bSDaniel Henrique Barboza 1893fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_pending_events = { 1894fd38804bSDaniel Henrique Barboza .name = "spapr_pending_events", 1895fd38804bSDaniel Henrique Barboza .version_id = 1, 1896fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1897fd38804bSDaniel Henrique Barboza .needed = spapr_pending_events_needed, 1898fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 1899ce2918cbSDavid Gibson VMSTATE_QTAILQ_V(pending_events, SpaprMachineState, 1, 1900ce2918cbSDavid Gibson vmstate_spapr_event_entry, SpaprEventLogEntry, next), 1901fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1902fd38804bSDaniel Henrique Barboza }, 1903fd38804bSDaniel Henrique Barboza }; 1904fd38804bSDaniel Henrique Barboza 190562ef3760SMichael Roth static bool spapr_ov5_cas_needed(void *opaque) 190662ef3760SMichael Roth { 1907ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 1908ce2918cbSDavid Gibson SpaprOptionVector *ov5_mask = spapr_ovec_new(); 1909ce2918cbSDavid Gibson SpaprOptionVector *ov5_legacy = spapr_ovec_new(); 1910ce2918cbSDavid Gibson SpaprOptionVector *ov5_removed = spapr_ovec_new(); 191162ef3760SMichael Roth bool cas_needed; 191262ef3760SMichael Roth 1913ce2918cbSDavid Gibson /* Prior to the introduction of SpaprOptionVector, we had two option 191462ef3760SMichael Roth * vectors we dealt with: OV5_FORM1_AFFINITY, and OV5_DRCONF_MEMORY. 191562ef3760SMichael Roth * Both of these options encode machine topology into the device-tree 191662ef3760SMichael Roth * in such a way that the now-booted OS should still be able to interact 191762ef3760SMichael Roth * appropriately with QEMU regardless of what options were actually 191862ef3760SMichael Roth * negotiatied on the source side. 191962ef3760SMichael Roth * 192062ef3760SMichael Roth * As such, we can avoid migrating the CAS-negotiated options if these 192162ef3760SMichael Roth * are the only options available on the current machine/platform. 192262ef3760SMichael Roth * Since these are the only options available for pseries-2.7 and 192362ef3760SMichael Roth * earlier, this allows us to maintain old->new/new->old migration 192462ef3760SMichael Roth * compatibility. 192562ef3760SMichael Roth * 192662ef3760SMichael Roth * For QEMU 2.8+, there are additional CAS-negotiatable options available 192762ef3760SMichael Roth * via default pseries-2.8 machines and explicit command-line parameters. 192862ef3760SMichael Roth * Some of these options, like OV5_HP_EVT, *do* require QEMU to be aware 192962ef3760SMichael Roth * of the actual CAS-negotiated values to continue working properly. For 193062ef3760SMichael Roth * example, availability of memory unplug depends on knowing whether 193162ef3760SMichael Roth * OV5_HP_EVT was negotiated via CAS. 193262ef3760SMichael Roth * 193362ef3760SMichael Roth * Thus, for any cases where the set of available CAS-negotiatable 193462ef3760SMichael Roth * options extends beyond OV5_FORM1_AFFINITY and OV5_DRCONF_MEMORY, we 1935aef19c04SGreg Kurz * include the CAS-negotiated options in the migration stream, unless 1936aef19c04SGreg Kurz * if they affect boot time behaviour only. 193762ef3760SMichael Roth */ 193862ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_FORM1_AFFINITY); 193962ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_DRCONF_MEMORY); 1940aef19c04SGreg Kurz spapr_ovec_set(ov5_mask, OV5_DRMEM_V2); 194162ef3760SMichael Roth 194262ef3760SMichael Roth /* spapr_ovec_diff returns true if bits were removed. we avoid using 194362ef3760SMichael Roth * the mask itself since in the future it's possible "legacy" bits may be 194462ef3760SMichael Roth * removed via machine options, which could generate a false positive 194562ef3760SMichael Roth * that breaks migration. 194662ef3760SMichael Roth */ 194762ef3760SMichael Roth spapr_ovec_intersect(ov5_legacy, spapr->ov5, ov5_mask); 194862ef3760SMichael Roth cas_needed = spapr_ovec_diff(ov5_removed, spapr->ov5, ov5_legacy); 194962ef3760SMichael Roth 195062ef3760SMichael Roth spapr_ovec_cleanup(ov5_mask); 195162ef3760SMichael Roth spapr_ovec_cleanup(ov5_legacy); 195262ef3760SMichael Roth spapr_ovec_cleanup(ov5_removed); 195362ef3760SMichael Roth 195462ef3760SMichael Roth return cas_needed; 195562ef3760SMichael Roth } 195662ef3760SMichael Roth 195762ef3760SMichael Roth static const VMStateDescription vmstate_spapr_ov5_cas = { 195862ef3760SMichael Roth .name = "spapr_option_vector_ov5_cas", 195962ef3760SMichael Roth .version_id = 1, 196062ef3760SMichael Roth .minimum_version_id = 1, 196162ef3760SMichael Roth .needed = spapr_ov5_cas_needed, 196262ef3760SMichael Roth .fields = (VMStateField[]) { 1963ce2918cbSDavid Gibson VMSTATE_STRUCT_POINTER_V(ov5_cas, SpaprMachineState, 1, 1964ce2918cbSDavid Gibson vmstate_spapr_ovec, SpaprOptionVector), 196562ef3760SMichael Roth VMSTATE_END_OF_LIST() 196662ef3760SMichael Roth }, 196762ef3760SMichael Roth }; 196862ef3760SMichael Roth 19699861bb3eSSuraj Jitindar Singh static bool spapr_patb_entry_needed(void *opaque) 19709861bb3eSSuraj Jitindar Singh { 1971ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 19729861bb3eSSuraj Jitindar Singh 19739861bb3eSSuraj Jitindar Singh return !!spapr->patb_entry; 19749861bb3eSSuraj Jitindar Singh } 19759861bb3eSSuraj Jitindar Singh 19769861bb3eSSuraj Jitindar Singh static const VMStateDescription vmstate_spapr_patb_entry = { 19779861bb3eSSuraj Jitindar Singh .name = "spapr_patb_entry", 19789861bb3eSSuraj Jitindar Singh .version_id = 1, 19799861bb3eSSuraj Jitindar Singh .minimum_version_id = 1, 19809861bb3eSSuraj Jitindar Singh .needed = spapr_patb_entry_needed, 19819861bb3eSSuraj Jitindar Singh .fields = (VMStateField[]) { 1982ce2918cbSDavid Gibson VMSTATE_UINT64(patb_entry, SpaprMachineState), 19839861bb3eSSuraj Jitindar Singh VMSTATE_END_OF_LIST() 19849861bb3eSSuraj Jitindar Singh }, 19859861bb3eSSuraj Jitindar Singh }; 19869861bb3eSSuraj Jitindar Singh 198782cffa2eSCédric Le Goater static bool spapr_irq_map_needed(void *opaque) 198882cffa2eSCédric Le Goater { 1989ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 199082cffa2eSCédric Le Goater 199182cffa2eSCédric Le Goater return spapr->irq_map && !bitmap_empty(spapr->irq_map, spapr->irq_map_nr); 199282cffa2eSCédric Le Goater } 199382cffa2eSCédric Le Goater 199482cffa2eSCédric Le Goater static const VMStateDescription vmstate_spapr_irq_map = { 199582cffa2eSCédric Le Goater .name = "spapr_irq_map", 199682cffa2eSCédric Le Goater .version_id = 1, 199782cffa2eSCédric Le Goater .minimum_version_id = 1, 199882cffa2eSCédric Le Goater .needed = spapr_irq_map_needed, 199982cffa2eSCédric Le Goater .fields = (VMStateField[]) { 2000ce2918cbSDavid Gibson VMSTATE_BITMAP(irq_map, SpaprMachineState, 0, irq_map_nr), 200182cffa2eSCédric Le Goater VMSTATE_END_OF_LIST() 200282cffa2eSCédric Le Goater }, 200382cffa2eSCédric Le Goater }; 200482cffa2eSCédric Le Goater 2005fea35ca4SAlexey Kardashevskiy static bool spapr_dtb_needed(void *opaque) 2006fea35ca4SAlexey Kardashevskiy { 2007ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(opaque); 2008fea35ca4SAlexey Kardashevskiy 2009fea35ca4SAlexey Kardashevskiy return smc->update_dt_enabled; 2010fea35ca4SAlexey Kardashevskiy } 2011fea35ca4SAlexey Kardashevskiy 2012fea35ca4SAlexey Kardashevskiy static int spapr_dtb_pre_load(void *opaque) 2013fea35ca4SAlexey Kardashevskiy { 2014ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 2015fea35ca4SAlexey Kardashevskiy 2016fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob); 2017fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = NULL; 2018fea35ca4SAlexey Kardashevskiy spapr->fdt_size = 0; 2019fea35ca4SAlexey Kardashevskiy 2020fea35ca4SAlexey Kardashevskiy return 0; 2021fea35ca4SAlexey Kardashevskiy } 2022fea35ca4SAlexey Kardashevskiy 2023fea35ca4SAlexey Kardashevskiy static const VMStateDescription vmstate_spapr_dtb = { 2024fea35ca4SAlexey Kardashevskiy .name = "spapr_dtb", 2025fea35ca4SAlexey Kardashevskiy .version_id = 1, 2026fea35ca4SAlexey Kardashevskiy .minimum_version_id = 1, 2027fea35ca4SAlexey Kardashevskiy .needed = spapr_dtb_needed, 2028fea35ca4SAlexey Kardashevskiy .pre_load = spapr_dtb_pre_load, 2029fea35ca4SAlexey Kardashevskiy .fields = (VMStateField[]) { 2030ce2918cbSDavid Gibson VMSTATE_UINT32(fdt_initial_size, SpaprMachineState), 2031ce2918cbSDavid Gibson VMSTATE_UINT32(fdt_size, SpaprMachineState), 2032ce2918cbSDavid Gibson VMSTATE_VBUFFER_ALLOC_UINT32(fdt_blob, SpaprMachineState, 0, NULL, 2033fea35ca4SAlexey Kardashevskiy fdt_size), 2034fea35ca4SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 2035fea35ca4SAlexey Kardashevskiy }, 2036fea35ca4SAlexey Kardashevskiy }; 2037fea35ca4SAlexey Kardashevskiy 20384be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = { 20394be21d56SDavid Gibson .name = "spapr", 2040880ae7deSDavid Gibson .version_id = 3, 20414be21d56SDavid Gibson .minimum_version_id = 1, 20424e5fe368SSuraj Jitindar Singh .pre_load = spapr_pre_load, 2043880ae7deSDavid Gibson .post_load = spapr_post_load, 20444e5fe368SSuraj Jitindar Singh .pre_save = spapr_pre_save, 20454be21d56SDavid Gibson .fields = (VMStateField[]) { 2046880ae7deSDavid Gibson /* used to be @next_irq */ 2047880ae7deSDavid Gibson VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4), 20484be21d56SDavid Gibson 20494be21d56SDavid Gibson /* RTC offset */ 2050ce2918cbSDavid Gibson VMSTATE_UINT64_TEST(rtc_offset, SpaprMachineState, version_before_3), 2051880ae7deSDavid Gibson 2052ce2918cbSDavid Gibson VMSTATE_PPC_TIMEBASE_V(tb, SpaprMachineState, 2), 20534be21d56SDavid Gibson VMSTATE_END_OF_LIST() 20544be21d56SDavid Gibson }, 205562ef3760SMichael Roth .subsections = (const VMStateDescription*[]) { 205662ef3760SMichael Roth &vmstate_spapr_ov5_cas, 20579861bb3eSSuraj Jitindar Singh &vmstate_spapr_patb_entry, 2058fd38804bSDaniel Henrique Barboza &vmstate_spapr_pending_events, 20594e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_htm, 20604e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_vsx, 20614e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_dfp, 20628f38eaf8SSuraj Jitindar Singh &vmstate_spapr_cap_cfpc, 206309114fd8SSuraj Jitindar Singh &vmstate_spapr_cap_sbbc, 20644be8d4e7SSuraj Jitindar Singh &vmstate_spapr_cap_ibs, 206564d4a534SDavid Gibson &vmstate_spapr_cap_hpt_maxpagesize, 206682cffa2eSCédric Le Goater &vmstate_spapr_irq_map, 2067b9a477b7SSuraj Jitindar Singh &vmstate_spapr_cap_nested_kvm_hv, 2068fea35ca4SAlexey Kardashevskiy &vmstate_spapr_dtb, 2069c982f5cfSSuraj Jitindar Singh &vmstate_spapr_cap_large_decr, 20708ff43ee4SSuraj Jitindar Singh &vmstate_spapr_cap_ccf_assist, 207162ef3760SMichael Roth NULL 207262ef3760SMichael Roth } 20734be21d56SDavid Gibson }; 20744be21d56SDavid Gibson 20754be21d56SDavid Gibson static int htab_save_setup(QEMUFile *f, void *opaque) 20764be21d56SDavid Gibson { 2077ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 20784be21d56SDavid Gibson 20794be21d56SDavid Gibson /* "Iteration" header */ 20803a384297SBharata B Rao if (!spapr->htab_shift) { 20813a384297SBharata B Rao qemu_put_be32(f, -1); 20823a384297SBharata B Rao } else { 20834be21d56SDavid Gibson qemu_put_be32(f, spapr->htab_shift); 20843a384297SBharata B Rao } 20854be21d56SDavid Gibson 2086e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 2087e68cb8b4SAlexey Kardashevskiy spapr->htab_save_index = 0; 2088e68cb8b4SAlexey Kardashevskiy spapr->htab_first_pass = true; 2089e68cb8b4SAlexey Kardashevskiy } else { 20903a384297SBharata B Rao if (spapr->htab_shift) { 2091e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 20924be21d56SDavid Gibson } 20933a384297SBharata B Rao } 20944be21d56SDavid Gibson 2095e68cb8b4SAlexey Kardashevskiy 2096e68cb8b4SAlexey Kardashevskiy return 0; 2097e68cb8b4SAlexey Kardashevskiy } 20984be21d56SDavid Gibson 2099ce2918cbSDavid Gibson static void htab_save_chunk(QEMUFile *f, SpaprMachineState *spapr, 2100332f7721SGreg Kurz int chunkstart, int n_valid, int n_invalid) 2101332f7721SGreg Kurz { 2102332f7721SGreg Kurz qemu_put_be32(f, chunkstart); 2103332f7721SGreg Kurz qemu_put_be16(f, n_valid); 2104332f7721SGreg Kurz qemu_put_be16(f, n_invalid); 2105332f7721SGreg Kurz qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 2106332f7721SGreg Kurz HASH_PTE_SIZE_64 * n_valid); 2107332f7721SGreg Kurz } 2108332f7721SGreg Kurz 2109332f7721SGreg Kurz static void htab_save_end_marker(QEMUFile *f) 2110332f7721SGreg Kurz { 2111332f7721SGreg Kurz qemu_put_be32(f, 0); 2112332f7721SGreg Kurz qemu_put_be16(f, 0); 2113332f7721SGreg Kurz qemu_put_be16(f, 0); 2114332f7721SGreg Kurz } 2115332f7721SGreg Kurz 2116ce2918cbSDavid Gibson static void htab_save_first_pass(QEMUFile *f, SpaprMachineState *spapr, 21174be21d56SDavid Gibson int64_t max_ns) 21184be21d56SDavid Gibson { 2119378bc217SDavid Gibson bool has_timeout = max_ns != -1; 21204be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 21214be21d56SDavid Gibson int index = spapr->htab_save_index; 2122bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 21234be21d56SDavid Gibson 21244be21d56SDavid Gibson assert(spapr->htab_first_pass); 21254be21d56SDavid Gibson 21264be21d56SDavid Gibson do { 21274be21d56SDavid Gibson int chunkstart; 21284be21d56SDavid Gibson 21294be21d56SDavid Gibson /* Consume invalid HPTEs */ 21304be21d56SDavid Gibson while ((index < htabslots) 21314be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 21324be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 213324ec2863SMarc-André Lureau index++; 21344be21d56SDavid Gibson } 21354be21d56SDavid Gibson 21364be21d56SDavid Gibson /* Consume valid HPTEs */ 21374be21d56SDavid Gibson chunkstart = index; 2138338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 21394be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 21404be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 214124ec2863SMarc-André Lureau index++; 21424be21d56SDavid Gibson } 21434be21d56SDavid Gibson 21444be21d56SDavid Gibson if (index > chunkstart) { 21454be21d56SDavid Gibson int n_valid = index - chunkstart; 21464be21d56SDavid Gibson 2147332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, 0); 21484be21d56SDavid Gibson 2149378bc217SDavid Gibson if (has_timeout && 2150378bc217SDavid Gibson (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 21514be21d56SDavid Gibson break; 21524be21d56SDavid Gibson } 21534be21d56SDavid Gibson } 21544be21d56SDavid Gibson } while ((index < htabslots) && !qemu_file_rate_limit(f)); 21554be21d56SDavid Gibson 21564be21d56SDavid Gibson if (index >= htabslots) { 21574be21d56SDavid Gibson assert(index == htabslots); 21584be21d56SDavid Gibson index = 0; 21594be21d56SDavid Gibson spapr->htab_first_pass = false; 21604be21d56SDavid Gibson } 21614be21d56SDavid Gibson spapr->htab_save_index = index; 21624be21d56SDavid Gibson } 21634be21d56SDavid Gibson 2164ce2918cbSDavid Gibson static int htab_save_later_pass(QEMUFile *f, SpaprMachineState *spapr, 21654be21d56SDavid Gibson int64_t max_ns) 21664be21d56SDavid Gibson { 21674be21d56SDavid Gibson bool final = max_ns < 0; 21684be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 21694be21d56SDavid Gibson int examined = 0, sent = 0; 21704be21d56SDavid Gibson int index = spapr->htab_save_index; 2171bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 21724be21d56SDavid Gibson 21734be21d56SDavid Gibson assert(!spapr->htab_first_pass); 21744be21d56SDavid Gibson 21754be21d56SDavid Gibson do { 21764be21d56SDavid Gibson int chunkstart, invalidstart; 21774be21d56SDavid Gibson 21784be21d56SDavid Gibson /* Consume non-dirty HPTEs */ 21794be21d56SDavid Gibson while ((index < htabslots) 21804be21d56SDavid Gibson && !HPTE_DIRTY(HPTE(spapr->htab, index))) { 21814be21d56SDavid Gibson index++; 21824be21d56SDavid Gibson examined++; 21834be21d56SDavid Gibson } 21844be21d56SDavid Gibson 21854be21d56SDavid Gibson chunkstart = index; 21864be21d56SDavid Gibson /* Consume valid dirty HPTEs */ 2187338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 21884be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 21894be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 21904be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 21914be21d56SDavid Gibson index++; 21924be21d56SDavid Gibson examined++; 21934be21d56SDavid Gibson } 21944be21d56SDavid Gibson 21954be21d56SDavid Gibson invalidstart = index; 21964be21d56SDavid Gibson /* Consume invalid dirty HPTEs */ 2197338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - invalidstart < USHRT_MAX) 21984be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 21994be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 22004be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 22014be21d56SDavid Gibson index++; 22024be21d56SDavid Gibson examined++; 22034be21d56SDavid Gibson } 22044be21d56SDavid Gibson 22054be21d56SDavid Gibson if (index > chunkstart) { 22064be21d56SDavid Gibson int n_valid = invalidstart - chunkstart; 22074be21d56SDavid Gibson int n_invalid = index - invalidstart; 22084be21d56SDavid Gibson 2209332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, n_invalid); 22104be21d56SDavid Gibson sent += index - chunkstart; 22114be21d56SDavid Gibson 2212bc72ad67SAlex Bligh if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 22134be21d56SDavid Gibson break; 22144be21d56SDavid Gibson } 22154be21d56SDavid Gibson } 22164be21d56SDavid Gibson 22174be21d56SDavid Gibson if (examined >= htabslots) { 22184be21d56SDavid Gibson break; 22194be21d56SDavid Gibson } 22204be21d56SDavid Gibson 22214be21d56SDavid Gibson if (index >= htabslots) { 22224be21d56SDavid Gibson assert(index == htabslots); 22234be21d56SDavid Gibson index = 0; 22244be21d56SDavid Gibson } 22254be21d56SDavid Gibson } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final)); 22264be21d56SDavid Gibson 22274be21d56SDavid Gibson if (index >= htabslots) { 22284be21d56SDavid Gibson assert(index == htabslots); 22294be21d56SDavid Gibson index = 0; 22304be21d56SDavid Gibson } 22314be21d56SDavid Gibson 22324be21d56SDavid Gibson spapr->htab_save_index = index; 22334be21d56SDavid Gibson 2234e68cb8b4SAlexey Kardashevskiy return (examined >= htabslots) && (sent == 0) ? 1 : 0; 22354be21d56SDavid Gibson } 22364be21d56SDavid Gibson 2237e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS 5000000 /* 5 ms */ 2238e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE 2048 2239e68cb8b4SAlexey Kardashevskiy 22404be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque) 22414be21d56SDavid Gibson { 2242ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2243715c5407SDavid Gibson int fd; 2244e68cb8b4SAlexey Kardashevskiy int rc = 0; 22454be21d56SDavid Gibson 22464be21d56SDavid Gibson /* Iteration header */ 22473a384297SBharata B Rao if (!spapr->htab_shift) { 22483a384297SBharata B Rao qemu_put_be32(f, -1); 2249e8cd4247SLaurent Vivier return 1; 22503a384297SBharata B Rao } else { 22514be21d56SDavid Gibson qemu_put_be32(f, 0); 22523a384297SBharata B Rao } 22534be21d56SDavid Gibson 2254e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2255e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2256e68cb8b4SAlexey Kardashevskiy 2257715c5407SDavid Gibson fd = get_htab_fd(spapr); 2258715c5407SDavid Gibson if (fd < 0) { 2259715c5407SDavid Gibson return fd; 226001a57972SSamuel Mendoza-Jonas } 226101a57972SSamuel Mendoza-Jonas 2262715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); 2263e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2264e68cb8b4SAlexey Kardashevskiy return rc; 2265e68cb8b4SAlexey Kardashevskiy } 2266e68cb8b4SAlexey Kardashevskiy } else if (spapr->htab_first_pass) { 22674be21d56SDavid Gibson htab_save_first_pass(f, spapr, MAX_ITERATION_NS); 22684be21d56SDavid Gibson } else { 2269e68cb8b4SAlexey Kardashevskiy rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS); 22704be21d56SDavid Gibson } 22714be21d56SDavid Gibson 2272332f7721SGreg Kurz htab_save_end_marker(f); 22734be21d56SDavid Gibson 2274e68cb8b4SAlexey Kardashevskiy return rc; 22754be21d56SDavid Gibson } 22764be21d56SDavid Gibson 22774be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque) 22784be21d56SDavid Gibson { 2279ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2280715c5407SDavid Gibson int fd; 22814be21d56SDavid Gibson 22824be21d56SDavid Gibson /* Iteration header */ 22833a384297SBharata B Rao if (!spapr->htab_shift) { 22843a384297SBharata B Rao qemu_put_be32(f, -1); 22853a384297SBharata B Rao return 0; 22863a384297SBharata B Rao } else { 22874be21d56SDavid Gibson qemu_put_be32(f, 0); 22883a384297SBharata B Rao } 22894be21d56SDavid Gibson 2290e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2291e68cb8b4SAlexey Kardashevskiy int rc; 2292e68cb8b4SAlexey Kardashevskiy 2293e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2294e68cb8b4SAlexey Kardashevskiy 2295715c5407SDavid Gibson fd = get_htab_fd(spapr); 2296715c5407SDavid Gibson if (fd < 0) { 2297715c5407SDavid Gibson return fd; 229801a57972SSamuel Mendoza-Jonas } 229901a57972SSamuel Mendoza-Jonas 2300715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1); 2301e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2302e68cb8b4SAlexey Kardashevskiy return rc; 2303e68cb8b4SAlexey Kardashevskiy } 2304e68cb8b4SAlexey Kardashevskiy } else { 2305378bc217SDavid Gibson if (spapr->htab_first_pass) { 2306378bc217SDavid Gibson htab_save_first_pass(f, spapr, -1); 2307378bc217SDavid Gibson } 23084be21d56SDavid Gibson htab_save_later_pass(f, spapr, -1); 2309e68cb8b4SAlexey Kardashevskiy } 23104be21d56SDavid Gibson 23114be21d56SDavid Gibson /* End marker */ 2312332f7721SGreg Kurz htab_save_end_marker(f); 23134be21d56SDavid Gibson 23144be21d56SDavid Gibson return 0; 23154be21d56SDavid Gibson } 23164be21d56SDavid Gibson 23174be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id) 23184be21d56SDavid Gibson { 2319ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 23204be21d56SDavid Gibson uint32_t section_hdr; 2321e68cb8b4SAlexey Kardashevskiy int fd = -1; 232214b0d748SGreg Kurz Error *local_err = NULL; 23234be21d56SDavid Gibson 23244be21d56SDavid Gibson if (version_id < 1 || version_id > 1) { 232598a5d100SDavid Gibson error_report("htab_load() bad version"); 23264be21d56SDavid Gibson return -EINVAL; 23274be21d56SDavid Gibson } 23284be21d56SDavid Gibson 23294be21d56SDavid Gibson section_hdr = qemu_get_be32(f); 23304be21d56SDavid Gibson 23313a384297SBharata B Rao if (section_hdr == -1) { 23323a384297SBharata B Rao spapr_free_hpt(spapr); 23333a384297SBharata B Rao return 0; 23343a384297SBharata B Rao } 23353a384297SBharata B Rao 23364be21d56SDavid Gibson if (section_hdr) { 2337c5f54f3eSDavid Gibson /* First section gives the htab size */ 2338c5f54f3eSDavid Gibson spapr_reallocate_hpt(spapr, section_hdr, &local_err); 2339c5f54f3eSDavid Gibson if (local_err) { 2340c5f54f3eSDavid Gibson error_report_err(local_err); 23414be21d56SDavid Gibson return -EINVAL; 23424be21d56SDavid Gibson } 23434be21d56SDavid Gibson return 0; 23444be21d56SDavid Gibson } 23454be21d56SDavid Gibson 2346e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2347e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2348e68cb8b4SAlexey Kardashevskiy 234914b0d748SGreg Kurz fd = kvmppc_get_htab_fd(true, 0, &local_err); 2350e68cb8b4SAlexey Kardashevskiy if (fd < 0) { 235114b0d748SGreg Kurz error_report_err(local_err); 235282be8e73SGreg Kurz return fd; 2353e68cb8b4SAlexey Kardashevskiy } 2354e68cb8b4SAlexey Kardashevskiy } 2355e68cb8b4SAlexey Kardashevskiy 23564be21d56SDavid Gibson while (true) { 23574be21d56SDavid Gibson uint32_t index; 23584be21d56SDavid Gibson uint16_t n_valid, n_invalid; 23594be21d56SDavid Gibson 23604be21d56SDavid Gibson index = qemu_get_be32(f); 23614be21d56SDavid Gibson n_valid = qemu_get_be16(f); 23624be21d56SDavid Gibson n_invalid = qemu_get_be16(f); 23634be21d56SDavid Gibson 23644be21d56SDavid Gibson if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) { 23654be21d56SDavid Gibson /* End of Stream */ 23664be21d56SDavid Gibson break; 23674be21d56SDavid Gibson } 23684be21d56SDavid Gibson 2369e68cb8b4SAlexey Kardashevskiy if ((index + n_valid + n_invalid) > 23704be21d56SDavid Gibson (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) { 23714be21d56SDavid Gibson /* Bad index in stream */ 237298a5d100SDavid Gibson error_report( 237398a5d100SDavid Gibson "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)", 237498a5d100SDavid Gibson index, n_valid, n_invalid, spapr->htab_shift); 23754be21d56SDavid Gibson return -EINVAL; 23764be21d56SDavid Gibson } 23774be21d56SDavid Gibson 2378e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 23794be21d56SDavid Gibson if (n_valid) { 23804be21d56SDavid Gibson qemu_get_buffer(f, HPTE(spapr->htab, index), 23814be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 23824be21d56SDavid Gibson } 23834be21d56SDavid Gibson if (n_invalid) { 23844be21d56SDavid Gibson memset(HPTE(spapr->htab, index + n_valid), 0, 23854be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_invalid); 23864be21d56SDavid Gibson } 2387e68cb8b4SAlexey Kardashevskiy } else { 2388e68cb8b4SAlexey Kardashevskiy int rc; 2389e68cb8b4SAlexey Kardashevskiy 2390e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2391e68cb8b4SAlexey Kardashevskiy 2392e68cb8b4SAlexey Kardashevskiy rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid); 2393e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2394e68cb8b4SAlexey Kardashevskiy return rc; 2395e68cb8b4SAlexey Kardashevskiy } 2396e68cb8b4SAlexey Kardashevskiy } 2397e68cb8b4SAlexey Kardashevskiy } 2398e68cb8b4SAlexey Kardashevskiy 2399e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2400e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2401e68cb8b4SAlexey Kardashevskiy close(fd); 24024be21d56SDavid Gibson } 24034be21d56SDavid Gibson 24044be21d56SDavid Gibson return 0; 24054be21d56SDavid Gibson } 24064be21d56SDavid Gibson 240770f794fcSJuan Quintela static void htab_save_cleanup(void *opaque) 2408c573fc03SThomas Huth { 2409ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2410c573fc03SThomas Huth 2411c573fc03SThomas Huth close_htab_fd(spapr); 2412c573fc03SThomas Huth } 2413c573fc03SThomas Huth 24144be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = { 24159907e842SJuan Quintela .save_setup = htab_save_setup, 24164be21d56SDavid Gibson .save_live_iterate = htab_save_iterate, 2417a3e06c3dSDr. David Alan Gilbert .save_live_complete_precopy = htab_save_complete, 241870f794fcSJuan Quintela .save_cleanup = htab_save_cleanup, 24194be21d56SDavid Gibson .load_state = htab_load, 24204be21d56SDavid Gibson }; 24214be21d56SDavid Gibson 24225b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device, 24235b2128d2SAlexander Graf Error **errp) 24245b2128d2SAlexander Graf { 2425c86c1affSDaniel Henrique Barboza MachineState *machine = MACHINE(opaque); 24265b2128d2SAlexander Graf machine->boot_order = g_strdup(boot_device); 24275b2128d2SAlexander Graf } 24285b2128d2SAlexander Graf 2429ce2918cbSDavid Gibson static void spapr_create_lmb_dr_connectors(SpaprMachineState *spapr) 2430224245bfSDavid Gibson { 2431224245bfSDavid Gibson MachineState *machine = MACHINE(spapr); 2432224245bfSDavid Gibson uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 2433e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 2434224245bfSDavid Gibson int i; 2435224245bfSDavid Gibson 2436224245bfSDavid Gibson for (i = 0; i < nr_lmbs; i++) { 2437224245bfSDavid Gibson uint64_t addr; 2438224245bfSDavid Gibson 2439b0c14ec4SDavid Hildenbrand addr = i * lmb_size + machine->device_memory->base; 24406caf3ac6SDavid Gibson spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_LMB, 2441224245bfSDavid Gibson addr / lmb_size); 2442224245bfSDavid Gibson } 2443224245bfSDavid Gibson } 2444224245bfSDavid Gibson 2445224245bfSDavid Gibson /* 2446224245bfSDavid Gibson * If RAM size, maxmem size and individual node mem sizes aren't aligned 2447224245bfSDavid Gibson * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest 2448224245bfSDavid Gibson * since we can't support such unaligned sizes with DRCONF_MEMORY. 2449224245bfSDavid Gibson */ 24507c150d6fSDavid Gibson static void spapr_validate_node_memory(MachineState *machine, Error **errp) 2451224245bfSDavid Gibson { 2452224245bfSDavid Gibson int i; 2453224245bfSDavid Gibson 24547c150d6fSDavid Gibson if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) { 24557c150d6fSDavid Gibson error_setg(errp, "Memory size 0x" RAM_ADDR_FMT 2456ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 24577c150d6fSDavid Gibson machine->ram_size, 2458d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 24597c150d6fSDavid Gibson return; 24607c150d6fSDavid Gibson } 24617c150d6fSDavid Gibson 24627c150d6fSDavid Gibson if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) { 24637c150d6fSDavid Gibson error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT 2464ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 24657c150d6fSDavid Gibson machine->ram_size, 2466d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 24677c150d6fSDavid Gibson return; 2468224245bfSDavid Gibson } 2469224245bfSDavid Gibson 2470aa570207STao Xu for (i = 0; i < machine->numa_state->num_nodes; i++) { 24717e721e7bSTao Xu if (machine->numa_state->nodes[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) { 24727c150d6fSDavid Gibson error_setg(errp, 24737c150d6fSDavid Gibson "Node %d memory size 0x%" PRIx64 2474ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 24757e721e7bSTao Xu i, machine->numa_state->nodes[i].node_mem, 2476d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 24777c150d6fSDavid Gibson return; 2478224245bfSDavid Gibson } 2479224245bfSDavid Gibson } 2480224245bfSDavid Gibson } 2481224245bfSDavid Gibson 2482535455fdSIgor Mammedov /* find cpu slot in machine->possible_cpus by core_id */ 2483535455fdSIgor Mammedov static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx) 2484535455fdSIgor Mammedov { 2485fe6b6346SLike Xu int index = id / ms->smp.threads; 2486535455fdSIgor Mammedov 2487535455fdSIgor Mammedov if (index >= ms->possible_cpus->len) { 2488535455fdSIgor Mammedov return NULL; 2489535455fdSIgor Mammedov } 2490535455fdSIgor Mammedov if (idx) { 2491535455fdSIgor Mammedov *idx = index; 2492535455fdSIgor Mammedov } 2493535455fdSIgor Mammedov return &ms->possible_cpus->cpus[index]; 2494535455fdSIgor Mammedov } 2495535455fdSIgor Mammedov 2496ce2918cbSDavid Gibson static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp) 2497fa98fbfcSSam Bobroff { 2498fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 2499*29cb4187SGreg Kurz SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 2500fa98fbfcSSam Bobroff Error *local_err = NULL; 2501fa98fbfcSSam Bobroff bool vsmt_user = !!spapr->vsmt; 2502fa98fbfcSSam Bobroff int kvm_smt = kvmppc_smt_threads(); 2503fa98fbfcSSam Bobroff int ret; 2504fe6b6346SLike Xu unsigned int smp_threads = ms->smp.threads; 2505fa98fbfcSSam Bobroff 2506fa98fbfcSSam Bobroff if (!kvm_enabled() && (smp_threads > 1)) { 2507fa98fbfcSSam Bobroff error_setg(&local_err, "TCG cannot support more than 1 thread/core " 2508fa98fbfcSSam Bobroff "on a pseries machine"); 2509fa98fbfcSSam Bobroff goto out; 2510fa98fbfcSSam Bobroff } 2511fa98fbfcSSam Bobroff if (!is_power_of_2(smp_threads)) { 2512fa98fbfcSSam Bobroff error_setg(&local_err, "Cannot support %d threads/core on a pseries " 2513fa98fbfcSSam Bobroff "machine because it must be a power of 2", smp_threads); 2514fa98fbfcSSam Bobroff goto out; 2515fa98fbfcSSam Bobroff } 2516fa98fbfcSSam Bobroff 2517fa98fbfcSSam Bobroff /* Detemine the VSMT mode to use: */ 2518fa98fbfcSSam Bobroff if (vsmt_user) { 2519fa98fbfcSSam Bobroff if (spapr->vsmt < smp_threads) { 2520fa98fbfcSSam Bobroff error_setg(&local_err, "Cannot support VSMT mode %d" 2521fa98fbfcSSam Bobroff " because it must be >= threads/core (%d)", 2522fa98fbfcSSam Bobroff spapr->vsmt, smp_threads); 2523fa98fbfcSSam Bobroff goto out; 2524fa98fbfcSSam Bobroff } 2525fa98fbfcSSam Bobroff /* In this case, spapr->vsmt has been set by the command line */ 2526*29cb4187SGreg Kurz } else if (!smc->smp_threads_vsmt) { 25278904e5a7SDavid Gibson /* 25288904e5a7SDavid Gibson * Default VSMT value is tricky, because we need it to be as 25298904e5a7SDavid Gibson * consistent as possible (for migration), but this requires 25308904e5a7SDavid Gibson * changing it for at least some existing cases. We pick 8 as 25318904e5a7SDavid Gibson * the value that we'd get with KVM on POWER8, the 25328904e5a7SDavid Gibson * overwhelmingly common case in production systems. 25338904e5a7SDavid Gibson */ 25344ad64cbdSLaurent Vivier spapr->vsmt = MAX(8, smp_threads); 2535*29cb4187SGreg Kurz } else { 2536*29cb4187SGreg Kurz spapr->vsmt = smp_threads; 2537fa98fbfcSSam Bobroff } 2538fa98fbfcSSam Bobroff 2539fa98fbfcSSam Bobroff /* KVM: If necessary, set the SMT mode: */ 2540fa98fbfcSSam Bobroff if (kvm_enabled() && (spapr->vsmt != kvm_smt)) { 2541fa98fbfcSSam Bobroff ret = kvmppc_set_smt_threads(spapr->vsmt); 2542fa98fbfcSSam Bobroff if (ret) { 25431f20f2e0SDavid Gibson /* Looks like KVM isn't able to change VSMT mode */ 2544fa98fbfcSSam Bobroff error_setg(&local_err, 2545fa98fbfcSSam Bobroff "Failed to set KVM's VSMT mode to %d (errno %d)", 2546fa98fbfcSSam Bobroff spapr->vsmt, ret); 25471f20f2e0SDavid Gibson /* We can live with that if the default one is big enough 25481f20f2e0SDavid Gibson * for the number of threads, and a submultiple of the one 25491f20f2e0SDavid Gibson * we want. In this case we'll waste some vcpu ids, but 25501f20f2e0SDavid Gibson * behaviour will be correct */ 25511f20f2e0SDavid Gibson if ((kvm_smt >= smp_threads) && ((spapr->vsmt % kvm_smt) == 0)) { 25521f20f2e0SDavid Gibson warn_report_err(local_err); 25531f20f2e0SDavid Gibson local_err = NULL; 25541f20f2e0SDavid Gibson goto out; 25551f20f2e0SDavid Gibson } else { 2556fa98fbfcSSam Bobroff if (!vsmt_user) { 25571f20f2e0SDavid Gibson error_append_hint(&local_err, 25581f20f2e0SDavid Gibson "On PPC, a VM with %d threads/core" 25591f20f2e0SDavid Gibson " on a host with %d threads/core" 25601f20f2e0SDavid Gibson " requires the use of VSMT mode %d.\n", 2561fa98fbfcSSam Bobroff smp_threads, kvm_smt, spapr->vsmt); 2562fa98fbfcSSam Bobroff } 2563fa98fbfcSSam Bobroff kvmppc_hint_smt_possible(&local_err); 2564fa98fbfcSSam Bobroff goto out; 2565fa98fbfcSSam Bobroff } 2566fa98fbfcSSam Bobroff } 25671f20f2e0SDavid Gibson } 2568fa98fbfcSSam Bobroff /* else TCG: nothing to do currently */ 2569fa98fbfcSSam Bobroff out: 2570fa98fbfcSSam Bobroff error_propagate(errp, local_err); 2571fa98fbfcSSam Bobroff } 2572fa98fbfcSSam Bobroff 2573ce2918cbSDavid Gibson static void spapr_init_cpus(SpaprMachineState *spapr) 25741a5008fcSGreg Kurz { 25751a5008fcSGreg Kurz MachineState *machine = MACHINE(spapr); 25761a5008fcSGreg Kurz MachineClass *mc = MACHINE_GET_CLASS(machine); 2577ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 25781a5008fcSGreg Kurz const char *type = spapr_get_cpu_core_type(machine->cpu_type); 25791a5008fcSGreg Kurz const CPUArchIdList *possible_cpus; 2580fe6b6346SLike Xu unsigned int smp_cpus = machine->smp.cpus; 2581fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 2582fe6b6346SLike Xu unsigned int max_cpus = machine->smp.max_cpus; 25831a5008fcSGreg Kurz int boot_cores_nr = smp_cpus / smp_threads; 25841a5008fcSGreg Kurz int i; 25851a5008fcSGreg Kurz 25861a5008fcSGreg Kurz possible_cpus = mc->possible_cpu_arch_ids(machine); 25871a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 25881a5008fcSGreg Kurz if (smp_cpus % smp_threads) { 25891a5008fcSGreg Kurz error_report("smp_cpus (%u) must be multiple of threads (%u)", 25901a5008fcSGreg Kurz smp_cpus, smp_threads); 25911a5008fcSGreg Kurz exit(1); 25921a5008fcSGreg Kurz } 25931a5008fcSGreg Kurz if (max_cpus % smp_threads) { 25941a5008fcSGreg Kurz error_report("max_cpus (%u) must be multiple of threads (%u)", 25951a5008fcSGreg Kurz max_cpus, smp_threads); 25961a5008fcSGreg Kurz exit(1); 25971a5008fcSGreg Kurz } 25981a5008fcSGreg Kurz } else { 25991a5008fcSGreg Kurz if (max_cpus != smp_cpus) { 26001a5008fcSGreg Kurz error_report("This machine version does not support CPU hotplug"); 26011a5008fcSGreg Kurz exit(1); 26021a5008fcSGreg Kurz } 26031a5008fcSGreg Kurz boot_cores_nr = possible_cpus->len; 26041a5008fcSGreg Kurz } 26051a5008fcSGreg Kurz 26061a5008fcSGreg Kurz if (smc->pre_2_10_has_unused_icps) { 26071a5008fcSGreg Kurz int i; 26081a5008fcSGreg Kurz 26091a518e76SCédric Le Goater for (i = 0; i < spapr_max_server_number(spapr); i++) { 26101a5008fcSGreg Kurz /* Dummy entries get deregistered when real ICPState objects 26111a5008fcSGreg Kurz * are registered during CPU core hotplug. 26121a5008fcSGreg Kurz */ 26131a5008fcSGreg Kurz pre_2_10_vmstate_register_dummy_icp(i); 26141a5008fcSGreg Kurz } 26151a5008fcSGreg Kurz } 26161a5008fcSGreg Kurz 26171a5008fcSGreg Kurz for (i = 0; i < possible_cpus->len; i++) { 26181a5008fcSGreg Kurz int core_id = i * smp_threads; 26191a5008fcSGreg Kurz 26201a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 26211a5008fcSGreg Kurz spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU, 26221a5008fcSGreg Kurz spapr_vcpu_id(spapr, core_id)); 26231a5008fcSGreg Kurz } 26241a5008fcSGreg Kurz 26251a5008fcSGreg Kurz if (i < boot_cores_nr) { 26261a5008fcSGreg Kurz Object *core = object_new(type); 26271a5008fcSGreg Kurz int nr_threads = smp_threads; 26281a5008fcSGreg Kurz 26291a5008fcSGreg Kurz /* Handle the partially filled core for older machine types */ 26301a5008fcSGreg Kurz if ((i + 1) * smp_threads >= smp_cpus) { 26311a5008fcSGreg Kurz nr_threads = smp_cpus - i * smp_threads; 26321a5008fcSGreg Kurz } 26331a5008fcSGreg Kurz 26341a5008fcSGreg Kurz object_property_set_int(core, nr_threads, "nr-threads", 26351a5008fcSGreg Kurz &error_fatal); 26361a5008fcSGreg Kurz object_property_set_int(core, core_id, CPU_CORE_PROP_CORE_ID, 26371a5008fcSGreg Kurz &error_fatal); 26381a5008fcSGreg Kurz object_property_set_bool(core, true, "realized", &error_fatal); 2639ecda255eSSam Bobroff 2640ecda255eSSam Bobroff object_unref(core); 26411a5008fcSGreg Kurz } 26421a5008fcSGreg Kurz } 26431a5008fcSGreg Kurz } 26441a5008fcSGreg Kurz 2645999c9cafSGreg Kurz static PCIHostState *spapr_create_default_phb(void) 2646999c9cafSGreg Kurz { 2647999c9cafSGreg Kurz DeviceState *dev; 2648999c9cafSGreg Kurz 2649999c9cafSGreg Kurz dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE); 2650999c9cafSGreg Kurz qdev_prop_set_uint32(dev, "index", 0); 2651999c9cafSGreg Kurz qdev_init_nofail(dev); 2652999c9cafSGreg Kurz 2653999c9cafSGreg Kurz return PCI_HOST_BRIDGE(dev); 2654999c9cafSGreg Kurz } 2655999c9cafSGreg Kurz 265653018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */ 2657bcb5ce08SDavid Gibson static void spapr_machine_init(MachineState *machine) 265853018216SPaolo Bonzini { 2659ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(machine); 2660ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 26613ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 26623ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 266353018216SPaolo Bonzini PCIHostState *phb; 266453018216SPaolo Bonzini int i; 266553018216SPaolo Bonzini MemoryRegion *sysmem = get_system_memory(); 266653018216SPaolo Bonzini MemoryRegion *ram = g_new(MemoryRegion, 1); 2667c86c1affSDaniel Henrique Barboza hwaddr node0_size = spapr_node0_size(machine); 2668b7d1f77aSBenjamin Herrenschmidt long load_limit, fw_size; 266953018216SPaolo Bonzini char *filename; 267030f4b05bSDavid Gibson Error *resize_hpt_err = NULL; 267153018216SPaolo Bonzini 2672226419d6SMichael S. Tsirkin msi_nonbroken = true; 267353018216SPaolo Bonzini 267453018216SPaolo Bonzini QLIST_INIT(&spapr->phbs); 26750cffce56SDavid Gibson QTAILQ_INIT(&spapr->pending_dimm_unplugs); 267653018216SPaolo Bonzini 26779f6edd06SDavid Gibson /* Determine capabilities to run with */ 26789f6edd06SDavid Gibson spapr_caps_init(spapr); 26799f6edd06SDavid Gibson 268030f4b05bSDavid Gibson kvmppc_check_papr_resize_hpt(&resize_hpt_err); 268130f4b05bSDavid Gibson if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) { 268230f4b05bSDavid Gibson /* 268330f4b05bSDavid Gibson * If the user explicitly requested a mode we should either 268430f4b05bSDavid Gibson * supply it, or fail completely (which we do below). But if 268530f4b05bSDavid Gibson * it's not set explicitly, we reset our mode to something 268630f4b05bSDavid Gibson * that works 268730f4b05bSDavid Gibson */ 268830f4b05bSDavid Gibson if (resize_hpt_err) { 268930f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 269030f4b05bSDavid Gibson error_free(resize_hpt_err); 269130f4b05bSDavid Gibson resize_hpt_err = NULL; 269230f4b05bSDavid Gibson } else { 269330f4b05bSDavid Gibson spapr->resize_hpt = smc->resize_hpt_default; 269430f4b05bSDavid Gibson } 269530f4b05bSDavid Gibson } 269630f4b05bSDavid Gibson 269730f4b05bSDavid Gibson assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT); 269830f4b05bSDavid Gibson 269930f4b05bSDavid Gibson if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && resize_hpt_err) { 270030f4b05bSDavid Gibson /* 270130f4b05bSDavid Gibson * User requested HPT resize, but this host can't supply it. Bail out 270230f4b05bSDavid Gibson */ 270330f4b05bSDavid Gibson error_report_err(resize_hpt_err); 270430f4b05bSDavid Gibson exit(1); 270530f4b05bSDavid Gibson } 270630f4b05bSDavid Gibson 2707c4177479SAlexey Kardashevskiy spapr->rma_size = node0_size; 270853018216SPaolo Bonzini 270953018216SPaolo Bonzini /* With KVM, we don't actually know whether KVM supports an 271053018216SPaolo Bonzini * unbounded RMA (PR KVM) or is limited by the hash table size 271153018216SPaolo Bonzini * (HV KVM using VRMA), so we always assume the latter 271253018216SPaolo Bonzini * 271353018216SPaolo Bonzini * In that case, we also limit the initial allocations for RTAS 271453018216SPaolo Bonzini * etc... to 256M since we have no way to know what the VRMA size 271553018216SPaolo Bonzini * is going to be as it depends on the size of the hash table 2716090052aaSDavid Gibson * which isn't determined yet. 271753018216SPaolo Bonzini */ 271853018216SPaolo Bonzini if (kvm_enabled()) { 271953018216SPaolo Bonzini spapr->vrma_adjust = 1; 272053018216SPaolo Bonzini spapr->rma_size = MIN(spapr->rma_size, 0x10000000); 272153018216SPaolo Bonzini } 2722912acdf4SBenjamin Herrenschmidt 2723090052aaSDavid Gibson /* Actually we don't support unbounded RMA anymore since we added 2724090052aaSDavid Gibson * proper emulation of HV mode. The max we can get is 16G which 2725090052aaSDavid Gibson * also happens to be what we configure for PAPR mode so make sure 2726090052aaSDavid Gibson * we don't do anything bigger than that 2727912acdf4SBenjamin Herrenschmidt */ 2728912acdf4SBenjamin Herrenschmidt spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull); 272953018216SPaolo Bonzini 2730c4177479SAlexey Kardashevskiy if (spapr->rma_size > node0_size) { 2731d54e4d76SDavid Gibson error_report("Numa node 0 has to span the RMA (%#08"HWADDR_PRIx")", 2732c4177479SAlexey Kardashevskiy spapr->rma_size); 2733c4177479SAlexey Kardashevskiy exit(1); 2734c4177479SAlexey Kardashevskiy } 2735c4177479SAlexey Kardashevskiy 2736b7d1f77aSBenjamin Herrenschmidt /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */ 2737b7d1f77aSBenjamin Herrenschmidt load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; 273853018216SPaolo Bonzini 2739482969d6SCédric Le Goater /* 2740482969d6SCédric Le Goater * VSMT must be set in order to be able to compute VCPU ids, ie to 27411a518e76SCédric Le Goater * call spapr_max_server_number() or spapr_vcpu_id(). 2742482969d6SCédric Le Goater */ 2743482969d6SCédric Le Goater spapr_set_vsmt_mode(spapr, &error_fatal); 2744482969d6SCédric Le Goater 27457b565160SDavid Gibson /* Set up Interrupt Controller before we create the VCPUs */ 2746fab397d8SCédric Le Goater spapr_irq_init(spapr, &error_fatal); 27477b565160SDavid Gibson 2748dc1b5eeeSGreg Kurz /* Set up containers for ibm,client-architecture-support negotiated options 2749dc1b5eeeSGreg Kurz */ 2750facdb8b6SMichael Roth spapr->ov5 = spapr_ovec_new(); 2751facdb8b6SMichael Roth spapr->ov5_cas = spapr_ovec_new(); 2752facdb8b6SMichael Roth 2753224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2754facdb8b6SMichael Roth spapr_ovec_set(spapr->ov5, OV5_DRCONF_MEMORY); 27557c150d6fSDavid Gibson spapr_validate_node_memory(machine, &error_fatal); 2756224245bfSDavid Gibson } 2757224245bfSDavid Gibson 2758417ece33SMichael Roth spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY); 2759417ece33SMichael Roth 2760ffbb1705SMichael Roth /* advertise support for dedicated HP event source to guests */ 2761ffbb1705SMichael Roth if (spapr->use_hotplug_event_source) { 2762ffbb1705SMichael Roth spapr_ovec_set(spapr->ov5, OV5_HP_EVT); 2763ffbb1705SMichael Roth } 2764ffbb1705SMichael Roth 27652772cf6bSDavid Gibson /* advertise support for HPT resizing */ 27662772cf6bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { 27672772cf6bSDavid Gibson spapr_ovec_set(spapr->ov5, OV5_HPT_RESIZE); 27682772cf6bSDavid Gibson } 27692772cf6bSDavid Gibson 2770a324d6f1SBharata B Rao /* advertise support for ibm,dyamic-memory-v2 */ 2771a324d6f1SBharata B Rao spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2); 2772a324d6f1SBharata B Rao 2773db592b5bSCédric Le Goater /* advertise XIVE on POWER9 machines */ 2774ca62823bSDavid Gibson if (spapr->irq->xive) { 2775db592b5bSCédric Le Goater spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT); 2776db592b5bSCédric Le Goater } 2777db592b5bSCédric Le Goater 277853018216SPaolo Bonzini /* init CPUs */ 27790c86d0fdSDavid Gibson spapr_init_cpus(spapr); 278053018216SPaolo Bonzini 278158c46efaSLaurent Vivier /* 278258c46efaSLaurent Vivier * check we don't have a memory-less/cpu-less NUMA node 278358c46efaSLaurent Vivier * Firmware relies on the existing memory/cpu topology to provide the 278458c46efaSLaurent Vivier * NUMA topology to the kernel. 278558c46efaSLaurent Vivier * And the linux kernel needs to know the NUMA topology at start 278658c46efaSLaurent Vivier * to be able to hotplug CPUs later. 278758c46efaSLaurent Vivier */ 278858c46efaSLaurent Vivier if (machine->numa_state->num_nodes) { 278958c46efaSLaurent Vivier for (i = 0; i < machine->numa_state->num_nodes; ++i) { 279058c46efaSLaurent Vivier /* check for memory-less node */ 279158c46efaSLaurent Vivier if (machine->numa_state->nodes[i].node_mem == 0) { 279258c46efaSLaurent Vivier CPUState *cs; 279358c46efaSLaurent Vivier int found = 0; 279458c46efaSLaurent Vivier /* check for cpu-less node */ 279558c46efaSLaurent Vivier CPU_FOREACH(cs) { 279658c46efaSLaurent Vivier PowerPCCPU *cpu = POWERPC_CPU(cs); 279758c46efaSLaurent Vivier if (cpu->node_id == i) { 279858c46efaSLaurent Vivier found = 1; 279958c46efaSLaurent Vivier break; 280058c46efaSLaurent Vivier } 280158c46efaSLaurent Vivier } 280258c46efaSLaurent Vivier /* memory-less and cpu-less node */ 280358c46efaSLaurent Vivier if (!found) { 280458c46efaSLaurent Vivier error_report( 280558c46efaSLaurent Vivier "Memory-less/cpu-less nodes are not supported (node %d)", 280658c46efaSLaurent Vivier i); 280758c46efaSLaurent Vivier exit(1); 280858c46efaSLaurent Vivier } 280958c46efaSLaurent Vivier } 281058c46efaSLaurent Vivier } 281158c46efaSLaurent Vivier 281258c46efaSLaurent Vivier } 281358c46efaSLaurent Vivier 2814db5127b2SDavid Gibson /* 2815db5127b2SDavid Gibson * NVLink2-connected GPU RAM needs to be placed on a separate NUMA node. 2816db5127b2SDavid Gibson * We assign a new numa ID per GPU in spapr_pci_collect_nvgpu() which is 2817db5127b2SDavid Gibson * called from vPHB reset handler so we initialize the counter here. 2818db5127b2SDavid Gibson * If no NUMA is configured from the QEMU side, we start from 1 as GPU RAM 2819db5127b2SDavid Gibson * must be equally distant from any other node. 2820db5127b2SDavid Gibson * The final value of spapr->gpu_numa_id is going to be written to 2821db5127b2SDavid Gibson * max-associativity-domains in spapr_build_fdt(). 2822db5127b2SDavid Gibson */ 2823db5127b2SDavid Gibson spapr->gpu_numa_id = MAX(1, machine->numa_state->num_nodes); 2824db5127b2SDavid Gibson 28250550b120SGreg Kurz if ((!kvm_enabled() || kvmppc_has_cap_mmu_radix()) && 2826ad99d04cSDavid Gibson ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, 28270550b120SGreg Kurz spapr->max_compat_pvr)) { 28280550b120SGreg Kurz /* KVM and TCG always allow GTSE with radix... */ 28290550b120SGreg Kurz spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE); 28300550b120SGreg Kurz } 28310550b120SGreg Kurz /* ... but not with hash (currently). */ 28320550b120SGreg Kurz 2833026bfd89SDavid Gibson if (kvm_enabled()) { 2834026bfd89SDavid Gibson /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ 2835026bfd89SDavid Gibson kvmppc_enable_logical_ci_hcalls(); 2836ef9971ddSAlexey Kardashevskiy kvmppc_enable_set_mode_hcall(); 28375145ad4fSNathan Whitehorn 28385145ad4fSNathan Whitehorn /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */ 28395145ad4fSNathan Whitehorn kvmppc_enable_clear_ref_mod_hcalls(); 284068f9f708SSuraj Jitindar Singh 284168f9f708SSuraj Jitindar Singh /* Enable H_PAGE_INIT */ 284268f9f708SSuraj Jitindar Singh kvmppc_enable_h_page_init(); 2843026bfd89SDavid Gibson } 2844026bfd89SDavid Gibson 284553018216SPaolo Bonzini /* allocate RAM */ 2846f92f5da1SAlexey Kardashevskiy memory_region_allocate_system_memory(ram, NULL, "ppc_spapr.ram", 2847fb164994SDavid Gibson machine->ram_size); 2848f92f5da1SAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, ram); 284953018216SPaolo Bonzini 2850b0c14ec4SDavid Hildenbrand /* always allocate the device memory information */ 2851b0c14ec4SDavid Hildenbrand machine->device_memory = g_malloc0(sizeof(*machine->device_memory)); 2852b0c14ec4SDavid Hildenbrand 28534a1c9cf0SBharata B Rao /* initialize hotplug memory address space */ 28544a1c9cf0SBharata B Rao if (machine->ram_size < machine->maxram_size) { 28550c9269a5SDavid Hildenbrand ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size; 285671c9a3ddSBharata B Rao /* 285771c9a3ddSBharata B Rao * Limit the number of hotpluggable memory slots to half the number 285871c9a3ddSBharata B Rao * slots that KVM supports, leaving the other half for PCI and other 285971c9a3ddSBharata B Rao * devices. However ensure that number of slots doesn't drop below 32. 286071c9a3ddSBharata B Rao */ 286171c9a3ddSBharata B Rao int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 : 286271c9a3ddSBharata B Rao SPAPR_MAX_RAM_SLOTS; 28634a1c9cf0SBharata B Rao 286471c9a3ddSBharata B Rao if (max_memslots < SPAPR_MAX_RAM_SLOTS) { 286571c9a3ddSBharata B Rao max_memslots = SPAPR_MAX_RAM_SLOTS; 286671c9a3ddSBharata B Rao } 286771c9a3ddSBharata B Rao if (machine->ram_slots > max_memslots) { 2868d54e4d76SDavid Gibson error_report("Specified number of memory slots %" 2869d54e4d76SDavid Gibson PRIu64" exceeds max supported %d", 287071c9a3ddSBharata B Rao machine->ram_slots, max_memslots); 2871d54e4d76SDavid Gibson exit(1); 28724a1c9cf0SBharata B Rao } 28734a1c9cf0SBharata B Rao 2874b0c14ec4SDavid Hildenbrand machine->device_memory->base = ROUND_UP(machine->ram_size, 28750c9269a5SDavid Hildenbrand SPAPR_DEVICE_MEM_ALIGN); 2876b0c14ec4SDavid Hildenbrand memory_region_init(&machine->device_memory->mr, OBJECT(spapr), 28770c9269a5SDavid Hildenbrand "device-memory", device_mem_size); 2878b0c14ec4SDavid Hildenbrand memory_region_add_subregion(sysmem, machine->device_memory->base, 2879b0c14ec4SDavid Hildenbrand &machine->device_memory->mr); 28804a1c9cf0SBharata B Rao } 28814a1c9cf0SBharata B Rao 2882224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2883224245bfSDavid Gibson spapr_create_lmb_dr_connectors(spapr); 2884224245bfSDavid Gibson } 2885224245bfSDavid Gibson 2886ffbb1705SMichael Roth /* Set up RTAS event infrastructure */ 288753018216SPaolo Bonzini spapr_events_init(spapr); 288853018216SPaolo Bonzini 288912f42174SDavid Gibson /* Set up the RTC RTAS interfaces */ 289028df36a1SDavid Gibson spapr_rtc_create(spapr); 289112f42174SDavid Gibson 289253018216SPaolo Bonzini /* Set up VIO bus */ 289353018216SPaolo Bonzini spapr->vio_bus = spapr_vio_bus_init(); 289453018216SPaolo Bonzini 2895b8846a4dSPeter Maydell for (i = 0; i < serial_max_hds(); i++) { 28969bca0edbSPeter Maydell if (serial_hd(i)) { 28979bca0edbSPeter Maydell spapr_vty_create(spapr->vio_bus, serial_hd(i)); 289853018216SPaolo Bonzini } 289953018216SPaolo Bonzini } 290053018216SPaolo Bonzini 290153018216SPaolo Bonzini /* We always have at least the nvram device on VIO */ 290253018216SPaolo Bonzini spapr_create_nvram(spapr); 290353018216SPaolo Bonzini 2904962b6c36SMichael Roth /* 2905962b6c36SMichael Roth * Setup hotplug / dynamic-reconfiguration connectors. top-level 2906962b6c36SMichael Roth * connectors (described in root DT node's "ibm,drc-types" property) 2907962b6c36SMichael Roth * are pre-initialized here. additional child connectors (such as 2908962b6c36SMichael Roth * connectors for a PHBs PCI slots) are added as needed during their 2909962b6c36SMichael Roth * parent's realization. 2910962b6c36SMichael Roth */ 2911962b6c36SMichael Roth if (smc->dr_phb_enabled) { 2912962b6c36SMichael Roth for (i = 0; i < SPAPR_MAX_PHBS; i++) { 2913962b6c36SMichael Roth spapr_dr_connector_new(OBJECT(machine), TYPE_SPAPR_DRC_PHB, i); 2914962b6c36SMichael Roth } 2915962b6c36SMichael Roth } 2916962b6c36SMichael Roth 291753018216SPaolo Bonzini /* Set up PCI */ 291853018216SPaolo Bonzini spapr_pci_rtas_init(); 291953018216SPaolo Bonzini 2920999c9cafSGreg Kurz phb = spapr_create_default_phb(); 292153018216SPaolo Bonzini 292253018216SPaolo Bonzini for (i = 0; i < nb_nics; i++) { 292353018216SPaolo Bonzini NICInfo *nd = &nd_table[i]; 292453018216SPaolo Bonzini 292553018216SPaolo Bonzini if (!nd->model) { 29263c3a4e7aSThomas Huth nd->model = g_strdup("spapr-vlan"); 292753018216SPaolo Bonzini } 292853018216SPaolo Bonzini 29293c3a4e7aSThomas Huth if (g_str_equal(nd->model, "spapr-vlan") || 29303c3a4e7aSThomas Huth g_str_equal(nd->model, "ibmveth")) { 293153018216SPaolo Bonzini spapr_vlan_create(spapr->vio_bus, nd); 293253018216SPaolo Bonzini } else { 293329b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL); 293453018216SPaolo Bonzini } 293553018216SPaolo Bonzini } 293653018216SPaolo Bonzini 293753018216SPaolo Bonzini for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { 293853018216SPaolo Bonzini spapr_vscsi_create(spapr->vio_bus); 293953018216SPaolo Bonzini } 294053018216SPaolo Bonzini 294153018216SPaolo Bonzini /* Graphics */ 294214c6a894SDavid Gibson if (spapr_vga_init(phb->bus, &error_fatal)) { 294353018216SPaolo Bonzini spapr->has_graphics = true; 2944c6e76503SPaolo Bonzini machine->usb |= defaults_enabled() && !machine->usb_disabled; 294553018216SPaolo Bonzini } 294653018216SPaolo Bonzini 29474ee9ced9SMarcel Apfelbaum if (machine->usb) { 294857040d45SThomas Huth if (smc->use_ohci_by_default) { 294953018216SPaolo Bonzini pci_create_simple(phb->bus, -1, "pci-ohci"); 295057040d45SThomas Huth } else { 295157040d45SThomas Huth pci_create_simple(phb->bus, -1, "nec-usb-xhci"); 295257040d45SThomas Huth } 2953c86580b8SMarkus Armbruster 295453018216SPaolo Bonzini if (spapr->has_graphics) { 2955c86580b8SMarkus Armbruster USBBus *usb_bus = usb_bus_find(-1); 2956c86580b8SMarkus Armbruster 2957c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-kbd"); 2958c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-mouse"); 295953018216SPaolo Bonzini } 296053018216SPaolo Bonzini } 296153018216SPaolo Bonzini 2962ab3dd749SPhilippe Mathieu-Daudé if (spapr->rma_size < (MIN_RMA_SLOF * MiB)) { 2963d54e4d76SDavid Gibson error_report( 2964d54e4d76SDavid Gibson "pSeries SLOF firmware requires >= %ldM guest RMA (Real Mode Area memory)", 2965d54e4d76SDavid Gibson MIN_RMA_SLOF); 296653018216SPaolo Bonzini exit(1); 296753018216SPaolo Bonzini } 296853018216SPaolo Bonzini 296953018216SPaolo Bonzini if (kernel_filename) { 297053018216SPaolo Bonzini uint64_t lowaddr = 0; 297153018216SPaolo Bonzini 29724366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL, 29734366e1dbSLiam Merwick translate_kernel_address, NULL, 29744366e1dbSLiam Merwick NULL, &lowaddr, NULL, 1, 2975a19f7fb0SDavid Gibson PPC_ELF_MACHINE, 0, 0); 2976a19f7fb0SDavid Gibson if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) { 29774366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL, 2978a19f7fb0SDavid Gibson translate_kernel_address, NULL, NULL, 2979a19f7fb0SDavid Gibson &lowaddr, NULL, 0, PPC_ELF_MACHINE, 29807ef295eaSPeter Crosthwaite 0, 0); 2981a19f7fb0SDavid Gibson spapr->kernel_le = spapr->kernel_size > 0; 298216457e7fSBenjamin Herrenschmidt } 2983a19f7fb0SDavid Gibson if (spapr->kernel_size < 0) { 2984a19f7fb0SDavid Gibson error_report("error loading %s: %s", kernel_filename, 2985a19f7fb0SDavid Gibson load_elf_strerror(spapr->kernel_size)); 298653018216SPaolo Bonzini exit(1); 298753018216SPaolo Bonzini } 298853018216SPaolo Bonzini 298953018216SPaolo Bonzini /* load initrd */ 299053018216SPaolo Bonzini if (initrd_filename) { 299153018216SPaolo Bonzini /* Try to locate the initrd in the gap between the kernel 299253018216SPaolo Bonzini * and the firmware. Add a bit of space just in case 299353018216SPaolo Bonzini */ 2994a19f7fb0SDavid Gibson spapr->initrd_base = (KERNEL_LOAD_ADDR + spapr->kernel_size 2995a19f7fb0SDavid Gibson + 0x1ffff) & ~0xffff; 2996a19f7fb0SDavid Gibson spapr->initrd_size = load_image_targphys(initrd_filename, 2997a19f7fb0SDavid Gibson spapr->initrd_base, 2998a19f7fb0SDavid Gibson load_limit 2999a19f7fb0SDavid Gibson - spapr->initrd_base); 3000a19f7fb0SDavid Gibson if (spapr->initrd_size < 0) { 3001d54e4d76SDavid Gibson error_report("could not load initial ram disk '%s'", 300253018216SPaolo Bonzini initrd_filename); 300353018216SPaolo Bonzini exit(1); 300453018216SPaolo Bonzini } 300553018216SPaolo Bonzini } 300653018216SPaolo Bonzini } 300753018216SPaolo Bonzini 30088e7ea787SAndreas Färber if (bios_name == NULL) { 30098e7ea787SAndreas Färber bios_name = FW_FILE_NAME; 30108e7ea787SAndreas Färber } 30118e7ea787SAndreas Färber filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 30124c56440dSStefan Weil if (!filename) { 301368fea5a0SThomas Huth error_report("Could not find LPAR firmware '%s'", bios_name); 30144c56440dSStefan Weil exit(1); 30154c56440dSStefan Weil } 301653018216SPaolo Bonzini fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); 301768fea5a0SThomas Huth if (fw_size <= 0) { 301868fea5a0SThomas Huth error_report("Could not load LPAR firmware '%s'", filename); 301953018216SPaolo Bonzini exit(1); 302053018216SPaolo Bonzini } 302153018216SPaolo Bonzini g_free(filename); 302253018216SPaolo Bonzini 302328e02042SDavid Gibson /* FIXME: Should register things through the MachineState's qdev 302428e02042SDavid Gibson * interface, this is a legacy from the sPAPREnvironment structure 302528e02042SDavid Gibson * which predated MachineState but had a similar function */ 30264be21d56SDavid Gibson vmstate_register(NULL, 0, &vmstate_spapr, spapr); 3027ce62df53SDr. David Alan Gilbert register_savevm_live("spapr/htab", -1, 1, 30284be21d56SDavid Gibson &savevm_htab_handlers, spapr); 30294be21d56SDavid Gibson 3030bb2bdd81SGreg Kurz qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine), 3031bb2bdd81SGreg Kurz &error_fatal); 3032bb2bdd81SGreg Kurz 30335b2128d2SAlexander Graf qemu_register_boot_set(spapr_boot_set, spapr); 303442043e4fSLaurent Vivier 303593eac7b8SNicholas Piggin /* 303693eac7b8SNicholas Piggin * Nothing needs to be done to resume a suspended guest because 303793eac7b8SNicholas Piggin * suspending does not change the machine state, so no need for 303893eac7b8SNicholas Piggin * a ->wakeup method. 303993eac7b8SNicholas Piggin */ 304093eac7b8SNicholas Piggin qemu_register_wakeup_support(); 304193eac7b8SNicholas Piggin 304242043e4fSLaurent Vivier if (kvm_enabled()) { 30433dc410aeSAlexey Kardashevskiy /* to stop and start vmclock */ 304442043e4fSLaurent Vivier qemu_add_vm_change_state_handler(cpu_ppc_clock_vm_state_change, 304542043e4fSLaurent Vivier &spapr->tb); 30463dc410aeSAlexey Kardashevskiy 30473dc410aeSAlexey Kardashevskiy kvmppc_spapr_enable_inkernel_multitce(); 304842043e4fSLaurent Vivier } 304953018216SPaolo Bonzini } 305053018216SPaolo Bonzini 3051dc0ca80eSEric Auger static int spapr_kvm_type(MachineState *machine, const char *vm_type) 3052135a129aSAneesh Kumar K.V { 3053135a129aSAneesh Kumar K.V if (!vm_type) { 3054135a129aSAneesh Kumar K.V return 0; 3055135a129aSAneesh Kumar K.V } 3056135a129aSAneesh Kumar K.V 3057135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "HV")) { 3058135a129aSAneesh Kumar K.V return 1; 3059135a129aSAneesh Kumar K.V } 3060135a129aSAneesh Kumar K.V 3061135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "PR")) { 3062135a129aSAneesh Kumar K.V return 2; 3063135a129aSAneesh Kumar K.V } 3064135a129aSAneesh Kumar K.V 3065135a129aSAneesh Kumar K.V error_report("Unknown kvm-type specified '%s'", vm_type); 3066135a129aSAneesh Kumar K.V exit(1); 3067135a129aSAneesh Kumar K.V } 3068135a129aSAneesh Kumar K.V 306971461b0fSAlexey Kardashevskiy /* 3070627b84f4SGonglei * Implementation of an interface to adjust firmware path 307171461b0fSAlexey Kardashevskiy * for the bootindex property handling. 307271461b0fSAlexey Kardashevskiy */ 307371461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, 307471461b0fSAlexey Kardashevskiy DeviceState *dev) 307571461b0fSAlexey Kardashevskiy { 307671461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \ 307771461b0fSAlexey Kardashevskiy ((type *)object_dynamic_cast(OBJECT(obj), (name))) 307871461b0fSAlexey Kardashevskiy SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); 3079ce2918cbSDavid Gibson SpaprPhbState *phb = CAST(SpaprPhbState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); 3080c4e13492SFelipe Franciosi VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON); 308171461b0fSAlexey Kardashevskiy 308271461b0fSAlexey Kardashevskiy if (d) { 308371461b0fSAlexey Kardashevskiy void *spapr = CAST(void, bus->parent, "spapr-vscsi"); 308471461b0fSAlexey Kardashevskiy VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); 308571461b0fSAlexey Kardashevskiy USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); 308671461b0fSAlexey Kardashevskiy 308771461b0fSAlexey Kardashevskiy if (spapr) { 308871461b0fSAlexey Kardashevskiy /* 308971461b0fSAlexey Kardashevskiy * Replace "channel@0/disk@0,0" with "disk@8000000000000000": 30901ac24c91SThomas Huth * In the top 16 bits of the 64-bit LUN, we use SRP luns of the form 30911ac24c91SThomas Huth * 0x8000 | (target << 8) | (bus << 5) | lun 30921ac24c91SThomas Huth * (see the "Logical unit addressing format" table in SAM5) 309371461b0fSAlexey Kardashevskiy */ 30941ac24c91SThomas Huth unsigned id = 0x8000 | (d->id << 8) | (d->channel << 5) | d->lun; 309571461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 309671461b0fSAlexey Kardashevskiy (uint64_t)id << 48); 309771461b0fSAlexey Kardashevskiy } else if (virtio) { 309871461b0fSAlexey Kardashevskiy /* 309971461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (target << 8) | lun 310071461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 310171461b0fSAlexey Kardashevskiy * Note: the quote above is from SLOF and it is wrong, 310271461b0fSAlexey Kardashevskiy * the actual binding is: 310371461b0fSAlexey Kardashevskiy * swap 0100 or 10 << or 20 << ( target lun-id -- srplun ) 310471461b0fSAlexey Kardashevskiy */ 310571461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (d->id << 16) | d->lun; 3106bac658d1SThomas Huth if (d->lun >= 256) { 3107bac658d1SThomas Huth /* Use the LUN "flat space addressing method" */ 3108bac658d1SThomas Huth id |= 0x4000; 3109bac658d1SThomas Huth } 311071461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 311171461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 311271461b0fSAlexey Kardashevskiy } else if (usb) { 311371461b0fSAlexey Kardashevskiy /* 311471461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (usb-port << 16) | lun 311571461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 311671461b0fSAlexey Kardashevskiy */ 311771461b0fSAlexey Kardashevskiy unsigned usb_port = atoi(usb->port->path); 311871461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (usb_port << 16) | d->lun; 311971461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 312071461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 312171461b0fSAlexey Kardashevskiy } 312271461b0fSAlexey Kardashevskiy } 312371461b0fSAlexey Kardashevskiy 3124b99260ebSThomas Huth /* 3125b99260ebSThomas Huth * SLOF probes the USB devices, and if it recognizes that the device is a 3126b99260ebSThomas Huth * storage device, it changes its name to "storage" instead of "usb-host", 3127b99260ebSThomas Huth * and additionally adds a child node for the SCSI LUN, so the correct 3128b99260ebSThomas Huth * boot path in SLOF is something like .../storage@1/disk@xxx" instead. 3129b99260ebSThomas Huth */ 3130b99260ebSThomas Huth if (strcmp("usb-host", qdev_fw_name(dev)) == 0) { 3131b99260ebSThomas Huth USBDevice *usbdev = CAST(USBDevice, dev, TYPE_USB_DEVICE); 3132b99260ebSThomas Huth if (usb_host_dev_is_scsi_storage(usbdev)) { 3133b99260ebSThomas Huth return g_strdup_printf("storage@%s/disk", usbdev->port->path); 3134b99260ebSThomas Huth } 3135b99260ebSThomas Huth } 3136b99260ebSThomas Huth 313771461b0fSAlexey Kardashevskiy if (phb) { 313871461b0fSAlexey Kardashevskiy /* Replace "pci" with "pci@800000020000000" */ 313971461b0fSAlexey Kardashevskiy return g_strdup_printf("pci@%"PRIX64, phb->buid); 314071461b0fSAlexey Kardashevskiy } 314171461b0fSAlexey Kardashevskiy 3142c4e13492SFelipe Franciosi if (vsc) { 3143c4e13492SFelipe Franciosi /* Same logic as virtio above */ 3144c4e13492SFelipe Franciosi unsigned id = 0x1000000 | (vsc->target << 16) | vsc->lun; 3145c4e13492SFelipe Franciosi return g_strdup_printf("disk@%"PRIX64, (uint64_t)id << 32); 3146c4e13492SFelipe Franciosi } 3147c4e13492SFelipe Franciosi 31484871dd4cSThomas Huth if (g_str_equal("pci-bridge", qdev_fw_name(dev))) { 31494871dd4cSThomas Huth /* SLOF uses "pci" instead of "pci-bridge" for PCI bridges */ 31504871dd4cSThomas Huth PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); 31514871dd4cSThomas Huth return g_strdup_printf("pci@%x", PCI_SLOT(pcidev->devfn)); 31524871dd4cSThomas Huth } 31534871dd4cSThomas Huth 315471461b0fSAlexey Kardashevskiy return NULL; 315571461b0fSAlexey Kardashevskiy } 315671461b0fSAlexey Kardashevskiy 315723825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp) 315823825581SEduardo Habkost { 3159ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 316023825581SEduardo Habkost 316128e02042SDavid Gibson return g_strdup(spapr->kvm_type); 316223825581SEduardo Habkost } 316323825581SEduardo Habkost 316423825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp) 316523825581SEduardo Habkost { 3166ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 316723825581SEduardo Habkost 316828e02042SDavid Gibson g_free(spapr->kvm_type); 316928e02042SDavid Gibson spapr->kvm_type = g_strdup(value); 317023825581SEduardo Habkost } 317123825581SEduardo Habkost 3172f6229214SMichael Roth static bool spapr_get_modern_hotplug_events(Object *obj, Error **errp) 3173f6229214SMichael Roth { 3174ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3175f6229214SMichael Roth 3176f6229214SMichael Roth return spapr->use_hotplug_event_source; 3177f6229214SMichael Roth } 3178f6229214SMichael Roth 3179f6229214SMichael Roth static void spapr_set_modern_hotplug_events(Object *obj, bool value, 3180f6229214SMichael Roth Error **errp) 3181f6229214SMichael Roth { 3182ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3183f6229214SMichael Roth 3184f6229214SMichael Roth spapr->use_hotplug_event_source = value; 3185f6229214SMichael Roth } 3186f6229214SMichael Roth 3187fcad0d21SAlexey Kardashevskiy static bool spapr_get_msix_emulation(Object *obj, Error **errp) 3188fcad0d21SAlexey Kardashevskiy { 3189fcad0d21SAlexey Kardashevskiy return true; 3190fcad0d21SAlexey Kardashevskiy } 3191fcad0d21SAlexey Kardashevskiy 319230f4b05bSDavid Gibson static char *spapr_get_resize_hpt(Object *obj, Error **errp) 319330f4b05bSDavid Gibson { 3194ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 319530f4b05bSDavid Gibson 319630f4b05bSDavid Gibson switch (spapr->resize_hpt) { 319730f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DEFAULT: 319830f4b05bSDavid Gibson return g_strdup("default"); 319930f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DISABLED: 320030f4b05bSDavid Gibson return g_strdup("disabled"); 320130f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_ENABLED: 320230f4b05bSDavid Gibson return g_strdup("enabled"); 320330f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_REQUIRED: 320430f4b05bSDavid Gibson return g_strdup("required"); 320530f4b05bSDavid Gibson } 320630f4b05bSDavid Gibson g_assert_not_reached(); 320730f4b05bSDavid Gibson } 320830f4b05bSDavid Gibson 320930f4b05bSDavid Gibson static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp) 321030f4b05bSDavid Gibson { 3211ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 321230f4b05bSDavid Gibson 321330f4b05bSDavid Gibson if (strcmp(value, "default") == 0) { 321430f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DEFAULT; 321530f4b05bSDavid Gibson } else if (strcmp(value, "disabled") == 0) { 321630f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 321730f4b05bSDavid Gibson } else if (strcmp(value, "enabled") == 0) { 321830f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_ENABLED; 321930f4b05bSDavid Gibson } else if (strcmp(value, "required") == 0) { 322030f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_REQUIRED; 322130f4b05bSDavid Gibson } else { 322230f4b05bSDavid Gibson error_setg(errp, "Bad value for \"resize-hpt\" property"); 322330f4b05bSDavid Gibson } 322430f4b05bSDavid Gibson } 322530f4b05bSDavid Gibson 3226fa98fbfcSSam Bobroff static void spapr_get_vsmt(Object *obj, Visitor *v, const char *name, 3227fa98fbfcSSam Bobroff void *opaque, Error **errp) 3228fa98fbfcSSam Bobroff { 3229fa98fbfcSSam Bobroff visit_type_uint32(v, name, (uint32_t *)opaque, errp); 3230fa98fbfcSSam Bobroff } 3231fa98fbfcSSam Bobroff 3232fa98fbfcSSam Bobroff static void spapr_set_vsmt(Object *obj, Visitor *v, const char *name, 3233fa98fbfcSSam Bobroff void *opaque, Error **errp) 3234fa98fbfcSSam Bobroff { 3235fa98fbfcSSam Bobroff visit_type_uint32(v, name, (uint32_t *)opaque, errp); 3236fa98fbfcSSam Bobroff } 3237fa98fbfcSSam Bobroff 32383ba3d0bcSCédric Le Goater static char *spapr_get_ic_mode(Object *obj, Error **errp) 32393ba3d0bcSCédric Le Goater { 3240ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 32413ba3d0bcSCédric Le Goater 32423ba3d0bcSCédric Le Goater if (spapr->irq == &spapr_irq_xics_legacy) { 32433ba3d0bcSCédric Le Goater return g_strdup("legacy"); 32443ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xics) { 32453ba3d0bcSCédric Le Goater return g_strdup("xics"); 32463ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xive) { 32473ba3d0bcSCédric Le Goater return g_strdup("xive"); 324813db0cd9SCédric Le Goater } else if (spapr->irq == &spapr_irq_dual) { 324913db0cd9SCédric Le Goater return g_strdup("dual"); 32503ba3d0bcSCédric Le Goater } 32513ba3d0bcSCédric Le Goater g_assert_not_reached(); 32523ba3d0bcSCédric Le Goater } 32533ba3d0bcSCédric Le Goater 32543ba3d0bcSCédric Le Goater static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp) 32553ba3d0bcSCédric Le Goater { 3256ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 32573ba3d0bcSCédric Le Goater 325821df5e4fSGreg Kurz if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { 325921df5e4fSGreg Kurz error_setg(errp, "This machine only uses the legacy XICS backend, don't pass ic-mode"); 326021df5e4fSGreg Kurz return; 326121df5e4fSGreg Kurz } 326221df5e4fSGreg Kurz 32633ba3d0bcSCédric Le Goater /* The legacy IRQ backend can not be set */ 32643ba3d0bcSCédric Le Goater if (strcmp(value, "xics") == 0) { 32653ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xics; 32663ba3d0bcSCédric Le Goater } else if (strcmp(value, "xive") == 0) { 32673ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xive; 326813db0cd9SCédric Le Goater } else if (strcmp(value, "dual") == 0) { 326913db0cd9SCédric Le Goater spapr->irq = &spapr_irq_dual; 32703ba3d0bcSCédric Le Goater } else { 32713ba3d0bcSCédric Le Goater error_setg(errp, "Bad value for \"ic-mode\" property"); 32723ba3d0bcSCédric Le Goater } 32733ba3d0bcSCédric Le Goater } 32743ba3d0bcSCédric Le Goater 327527461d69SPrasad J Pandit static char *spapr_get_host_model(Object *obj, Error **errp) 327627461d69SPrasad J Pandit { 3277ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 327827461d69SPrasad J Pandit 327927461d69SPrasad J Pandit return g_strdup(spapr->host_model); 328027461d69SPrasad J Pandit } 328127461d69SPrasad J Pandit 328227461d69SPrasad J Pandit static void spapr_set_host_model(Object *obj, const char *value, Error **errp) 328327461d69SPrasad J Pandit { 3284ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 328527461d69SPrasad J Pandit 328627461d69SPrasad J Pandit g_free(spapr->host_model); 328727461d69SPrasad J Pandit spapr->host_model = g_strdup(value); 328827461d69SPrasad J Pandit } 328927461d69SPrasad J Pandit 329027461d69SPrasad J Pandit static char *spapr_get_host_serial(Object *obj, Error **errp) 329127461d69SPrasad J Pandit { 3292ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 329327461d69SPrasad J Pandit 329427461d69SPrasad J Pandit return g_strdup(spapr->host_serial); 329527461d69SPrasad J Pandit } 329627461d69SPrasad J Pandit 329727461d69SPrasad J Pandit static void spapr_set_host_serial(Object *obj, const char *value, Error **errp) 329827461d69SPrasad J Pandit { 3299ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 330027461d69SPrasad J Pandit 330127461d69SPrasad J Pandit g_free(spapr->host_serial); 330227461d69SPrasad J Pandit spapr->host_serial = g_strdup(value); 330327461d69SPrasad J Pandit } 330427461d69SPrasad J Pandit 3305bcb5ce08SDavid Gibson static void spapr_instance_init(Object *obj) 330623825581SEduardo Habkost { 3307ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3308ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 3309715c5407SDavid Gibson 3310715c5407SDavid Gibson spapr->htab_fd = -1; 3311f6229214SMichael Roth spapr->use_hotplug_event_source = true; 331223825581SEduardo Habkost object_property_add_str(obj, "kvm-type", 331323825581SEduardo Habkost spapr_get_kvm_type, spapr_set_kvm_type, NULL); 331449d2e648SMarcel Apfelbaum object_property_set_description(obj, "kvm-type", 331549d2e648SMarcel Apfelbaum "Specifies the KVM virtualization mode (HV, PR)", 331649d2e648SMarcel Apfelbaum NULL); 3317f6229214SMichael Roth object_property_add_bool(obj, "modern-hotplug-events", 3318f6229214SMichael Roth spapr_get_modern_hotplug_events, 3319f6229214SMichael Roth spapr_set_modern_hotplug_events, 3320f6229214SMichael Roth NULL); 3321f6229214SMichael Roth object_property_set_description(obj, "modern-hotplug-events", 3322f6229214SMichael Roth "Use dedicated hotplug event mechanism in" 3323f6229214SMichael Roth " place of standard EPOW events when possible" 3324f6229214SMichael Roth " (required for memory hot-unplug support)", 3325f6229214SMichael Roth NULL); 33267843c0d6SDavid Gibson ppc_compat_add_property(obj, "max-cpu-compat", &spapr->max_compat_pvr, 33277843c0d6SDavid Gibson "Maximum permitted CPU compatibility mode", 33287843c0d6SDavid Gibson &error_fatal); 332930f4b05bSDavid Gibson 333030f4b05bSDavid Gibson object_property_add_str(obj, "resize-hpt", 333130f4b05bSDavid Gibson spapr_get_resize_hpt, spapr_set_resize_hpt, NULL); 333230f4b05bSDavid Gibson object_property_set_description(obj, "resize-hpt", 333330f4b05bSDavid Gibson "Resizing of the Hash Page Table (enabled, disabled, required)", 333430f4b05bSDavid Gibson NULL); 3335fa98fbfcSSam Bobroff object_property_add(obj, "vsmt", "uint32", spapr_get_vsmt, 3336fa98fbfcSSam Bobroff spapr_set_vsmt, NULL, &spapr->vsmt, &error_abort); 3337fa98fbfcSSam Bobroff object_property_set_description(obj, "vsmt", 3338fa98fbfcSSam Bobroff "Virtual SMT: KVM behaves as if this were" 3339fa98fbfcSSam Bobroff " the host's SMT mode", &error_abort); 3340fcad0d21SAlexey Kardashevskiy object_property_add_bool(obj, "vfio-no-msix-emulation", 3341fcad0d21SAlexey Kardashevskiy spapr_get_msix_emulation, NULL, NULL); 33423ba3d0bcSCédric Le Goater 33433ba3d0bcSCédric Le Goater /* The machine class defines the default interrupt controller mode */ 33443ba3d0bcSCédric Le Goater spapr->irq = smc->irq; 33453ba3d0bcSCédric Le Goater object_property_add_str(obj, "ic-mode", spapr_get_ic_mode, 33463ba3d0bcSCédric Le Goater spapr_set_ic_mode, NULL); 33473ba3d0bcSCédric Le Goater object_property_set_description(obj, "ic-mode", 334813db0cd9SCédric Le Goater "Specifies the interrupt controller mode (xics, xive, dual)", 33493ba3d0bcSCédric Le Goater NULL); 335027461d69SPrasad J Pandit 335127461d69SPrasad J Pandit object_property_add_str(obj, "host-model", 335227461d69SPrasad J Pandit spapr_get_host_model, spapr_set_host_model, 335327461d69SPrasad J Pandit &error_abort); 335427461d69SPrasad J Pandit object_property_set_description(obj, "host-model", 33550a794529SDavid Gibson "Host model to advertise in guest device tree", &error_abort); 335627461d69SPrasad J Pandit object_property_add_str(obj, "host-serial", 335727461d69SPrasad J Pandit spapr_get_host_serial, spapr_set_host_serial, 335827461d69SPrasad J Pandit &error_abort); 335927461d69SPrasad J Pandit object_property_set_description(obj, "host-serial", 33600a794529SDavid Gibson "Host serial number to advertise in guest device tree", &error_abort); 336123825581SEduardo Habkost } 336223825581SEduardo Habkost 336387bbdd9cSDavid Gibson static void spapr_machine_finalizefn(Object *obj) 336487bbdd9cSDavid Gibson { 3365ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 336687bbdd9cSDavid Gibson 336787bbdd9cSDavid Gibson g_free(spapr->kvm_type); 336887bbdd9cSDavid Gibson } 336987bbdd9cSDavid Gibson 33701c7ad77eSNicholas Piggin void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg) 337134316482SAlexey Kardashevskiy { 337234316482SAlexey Kardashevskiy cpu_synchronize_state(cs); 337334316482SAlexey Kardashevskiy ppc_cpu_do_system_reset(cs); 337434316482SAlexey Kardashevskiy } 337534316482SAlexey Kardashevskiy 337634316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) 337734316482SAlexey Kardashevskiy { 337834316482SAlexey Kardashevskiy CPUState *cs; 337934316482SAlexey Kardashevskiy 338034316482SAlexey Kardashevskiy CPU_FOREACH(cs) { 33811c7ad77eSNicholas Piggin async_run_on_cpu(cs, spapr_do_system_reset_on_cpu, RUN_ON_CPU_NULL); 338234316482SAlexey Kardashevskiy } 338334316482SAlexey Kardashevskiy } 338434316482SAlexey Kardashevskiy 3385ce2918cbSDavid Gibson int spapr_lmb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 338662d38c9bSGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 338762d38c9bSGreg Kurz { 338862d38c9bSGreg Kurz uint64_t addr; 338962d38c9bSGreg Kurz uint32_t node; 339062d38c9bSGreg Kurz 339162d38c9bSGreg Kurz addr = spapr_drc_index(drc) * SPAPR_MEMORY_BLOCK_SIZE; 339262d38c9bSGreg Kurz node = object_property_get_uint(OBJECT(drc->dev), PC_DIMM_NODE_PROP, 339362d38c9bSGreg Kurz &error_abort); 339462d38c9bSGreg Kurz *fdt_start_offset = spapr_populate_memory_node(fdt, node, addr, 339562d38c9bSGreg Kurz SPAPR_MEMORY_BLOCK_SIZE); 339662d38c9bSGreg Kurz return 0; 339762d38c9bSGreg Kurz } 339862d38c9bSGreg Kurz 339979b78a6bSMichael Roth static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, 340062d38c9bSGreg Kurz bool dedicated_hp_event_source, Error **errp) 3401c20d332aSBharata B Rao { 3402ce2918cbSDavid Gibson SpaprDrc *drc; 3403c20d332aSBharata B Rao uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; 340462d38c9bSGreg Kurz int i; 340579b78a6bSMichael Roth uint64_t addr = addr_start; 340694fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 3407160bb678SGreg Kurz Error *local_err = NULL; 3408c20d332aSBharata B Rao 3409c20d332aSBharata B Rao for (i = 0; i < nr_lmbs; i++) { 3410fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 3411c20d332aSBharata B Rao addr / SPAPR_MEMORY_BLOCK_SIZE); 3412c20d332aSBharata B Rao g_assert(drc); 3413c20d332aSBharata B Rao 341409d876ceSGreg Kurz spapr_drc_attach(drc, dev, &local_err); 3415160bb678SGreg Kurz if (local_err) { 3416160bb678SGreg Kurz while (addr > addr_start) { 3417160bb678SGreg Kurz addr -= SPAPR_MEMORY_BLOCK_SIZE; 3418160bb678SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 3419160bb678SGreg Kurz addr / SPAPR_MEMORY_BLOCK_SIZE); 3420a8dc47fdSDavid Gibson spapr_drc_detach(drc); 3421160bb678SGreg Kurz } 3422160bb678SGreg Kurz error_propagate(errp, local_err); 3423160bb678SGreg Kurz return; 3424160bb678SGreg Kurz } 342594fd9cbaSLaurent Vivier if (!hotplugged) { 342694fd9cbaSLaurent Vivier spapr_drc_reset(drc); 342794fd9cbaSLaurent Vivier } 3428c20d332aSBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE; 3429c20d332aSBharata B Rao } 34305dd5238cSJianjun Duan /* send hotplug notification to the 34315dd5238cSJianjun Duan * guest only in case of hotplugged memory 34325dd5238cSJianjun Duan */ 343394fd9cbaSLaurent Vivier if (hotplugged) { 343479b78a6bSMichael Roth if (dedicated_hp_event_source) { 3435fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 343679b78a6bSMichael Roth addr_start / SPAPR_MEMORY_BLOCK_SIZE); 343779b78a6bSMichael Roth spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 343879b78a6bSMichael Roth nr_lmbs, 34390b55aa91SDavid Gibson spapr_drc_index(drc)); 344079b78a6bSMichael Roth } else { 344179b78a6bSMichael Roth spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, 344279b78a6bSMichael Roth nr_lmbs); 344379b78a6bSMichael Roth } 3444c20d332aSBharata B Rao } 34455dd5238cSJianjun Duan } 3446c20d332aSBharata B Rao 3447c20d332aSBharata B Rao static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 344881985f3bSDavid Hildenbrand Error **errp) 3449c20d332aSBharata B Rao { 3450c20d332aSBharata B Rao Error *local_err = NULL; 3451ce2918cbSDavid Gibson SpaprMachineState *ms = SPAPR_MACHINE(hotplug_dev); 3452c20d332aSBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 3453b0e62443SDavid Hildenbrand uint64_t size, addr; 345404790978SThomas Huth 3455946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dev), &error_abort); 3456df587133SThomas Huth 3457fd3416f5SDavid Hildenbrand pc_dimm_plug(dimm, MACHINE(ms), &local_err); 3458c20d332aSBharata B Rao if (local_err) { 3459c20d332aSBharata B Rao goto out; 3460c20d332aSBharata B Rao } 3461c20d332aSBharata B Rao 34629ed442b8SMarc-André Lureau addr = object_property_get_uint(OBJECT(dimm), 34639ed442b8SMarc-André Lureau PC_DIMM_ADDR_PROP, &local_err); 3464c20d332aSBharata B Rao if (local_err) { 3465160bb678SGreg Kurz goto out_unplug; 3466c20d332aSBharata B Rao } 3467c20d332aSBharata B Rao 346862d38c9bSGreg Kurz spapr_add_lmbs(dev, addr, size, spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), 3469160bb678SGreg Kurz &local_err); 3470160bb678SGreg Kurz if (local_err) { 3471160bb678SGreg Kurz goto out_unplug; 3472160bb678SGreg Kurz } 3473c20d332aSBharata B Rao 3474160bb678SGreg Kurz return; 3475160bb678SGreg Kurz 3476160bb678SGreg Kurz out_unplug: 3477fd3416f5SDavid Hildenbrand pc_dimm_unplug(dimm, MACHINE(ms)); 3478c20d332aSBharata B Rao out: 3479c20d332aSBharata B Rao error_propagate(errp, local_err); 3480c20d332aSBharata B Rao } 3481c20d332aSBharata B Rao 3482c871bc70SLaurent Vivier static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3483c871bc70SLaurent Vivier Error **errp) 3484c871bc70SLaurent Vivier { 3485ce2918cbSDavid Gibson const SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev); 3486ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3487c871bc70SLaurent Vivier PCDIMMDevice *dimm = PC_DIMM(dev); 34888f1ffe5bSDavid Hildenbrand Error *local_err = NULL; 348904790978SThomas Huth uint64_t size; 3490123eec65SDavid Gibson Object *memdev; 3491123eec65SDavid Gibson hwaddr pagesize; 3492c871bc70SLaurent Vivier 34934e8a01bdSDavid Hildenbrand if (!smc->dr_lmb_enabled) { 34944e8a01bdSDavid Hildenbrand error_setg(errp, "Memory hotplug not supported for this machine"); 34954e8a01bdSDavid Hildenbrand return; 34964e8a01bdSDavid Hildenbrand } 34974e8a01bdSDavid Hildenbrand 3498946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &local_err); 3499946d6154SDavid Hildenbrand if (local_err) { 3500946d6154SDavid Hildenbrand error_propagate(errp, local_err); 350104790978SThomas Huth return; 350204790978SThomas Huth } 350304790978SThomas Huth 3504c871bc70SLaurent Vivier if (size % SPAPR_MEMORY_BLOCK_SIZE) { 3505c871bc70SLaurent Vivier error_setg(errp, "Hotplugged memory size must be a multiple of " 3506ab3dd749SPhilippe Mathieu-Daudé "%" PRIu64 " MB", SPAPR_MEMORY_BLOCK_SIZE / MiB); 3507c871bc70SLaurent Vivier return; 3508c871bc70SLaurent Vivier } 3509c871bc70SLaurent Vivier 3510123eec65SDavid Gibson memdev = object_property_get_link(OBJECT(dimm), PC_DIMM_MEMDEV_PROP, 3511123eec65SDavid Gibson &error_abort); 3512123eec65SDavid Gibson pagesize = host_memory_backend_pagesize(MEMORY_BACKEND(memdev)); 35138f1ffe5bSDavid Hildenbrand spapr_check_pagesize(spapr, pagesize, &local_err); 35148f1ffe5bSDavid Hildenbrand if (local_err) { 35158f1ffe5bSDavid Hildenbrand error_propagate(errp, local_err); 35168f1ffe5bSDavid Hildenbrand return; 35178f1ffe5bSDavid Hildenbrand } 35188f1ffe5bSDavid Hildenbrand 3519fd3416f5SDavid Hildenbrand pc_dimm_pre_plug(dimm, MACHINE(hotplug_dev), NULL, errp); 3520c871bc70SLaurent Vivier } 3521c871bc70SLaurent Vivier 3522ce2918cbSDavid Gibson struct SpaprDimmState { 35230cffce56SDavid Gibson PCDIMMDevice *dimm; 3524cf632463SBharata B Rao uint32_t nr_lmbs; 3525ce2918cbSDavid Gibson QTAILQ_ENTRY(SpaprDimmState) next; 35260cffce56SDavid Gibson }; 35270cffce56SDavid Gibson 3528ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_find(SpaprMachineState *s, 35290cffce56SDavid Gibson PCDIMMDevice *dimm) 35300cffce56SDavid Gibson { 3531ce2918cbSDavid Gibson SpaprDimmState *dimm_state = NULL; 35320cffce56SDavid Gibson 35330cffce56SDavid Gibson QTAILQ_FOREACH(dimm_state, &s->pending_dimm_unplugs, next) { 35340cffce56SDavid Gibson if (dimm_state->dimm == dimm) { 35350cffce56SDavid Gibson break; 35360cffce56SDavid Gibson } 35370cffce56SDavid Gibson } 35380cffce56SDavid Gibson return dimm_state; 35390cffce56SDavid Gibson } 35400cffce56SDavid Gibson 3541ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_add(SpaprMachineState *spapr, 35428d5981c4SBharata B Rao uint32_t nr_lmbs, 35438d5981c4SBharata B Rao PCDIMMDevice *dimm) 35440cffce56SDavid Gibson { 3545ce2918cbSDavid Gibson SpaprDimmState *ds = NULL; 35468d5981c4SBharata B Rao 35478d5981c4SBharata B Rao /* 35488d5981c4SBharata B Rao * If this request is for a DIMM whose removal had failed earlier 35498d5981c4SBharata B Rao * (due to guest's refusal to remove the LMBs), we would have this 35508d5981c4SBharata B Rao * dimm already in the pending_dimm_unplugs list. In that 35518d5981c4SBharata B Rao * case don't add again. 35528d5981c4SBharata B Rao */ 35538d5981c4SBharata B Rao ds = spapr_pending_dimm_unplugs_find(spapr, dimm); 35548d5981c4SBharata B Rao if (!ds) { 3555ce2918cbSDavid Gibson ds = g_malloc0(sizeof(SpaprDimmState)); 35568d5981c4SBharata B Rao ds->nr_lmbs = nr_lmbs; 35578d5981c4SBharata B Rao ds->dimm = dimm; 35588d5981c4SBharata B Rao QTAILQ_INSERT_HEAD(&spapr->pending_dimm_unplugs, ds, next); 35598d5981c4SBharata B Rao } 35608d5981c4SBharata B Rao return ds; 35610cffce56SDavid Gibson } 35620cffce56SDavid Gibson 3563ce2918cbSDavid Gibson static void spapr_pending_dimm_unplugs_remove(SpaprMachineState *spapr, 3564ce2918cbSDavid Gibson SpaprDimmState *dimm_state) 35650cffce56SDavid Gibson { 35660cffce56SDavid Gibson QTAILQ_REMOVE(&spapr->pending_dimm_unplugs, dimm_state, next); 35670cffce56SDavid Gibson g_free(dimm_state); 35680cffce56SDavid Gibson } 3569cf632463SBharata B Rao 3570ce2918cbSDavid Gibson static SpaprDimmState *spapr_recover_pending_dimm_state(SpaprMachineState *ms, 357116ee9980SDaniel Henrique Barboza PCDIMMDevice *dimm) 357216ee9980SDaniel Henrique Barboza { 3573ce2918cbSDavid Gibson SpaprDrc *drc; 3574946d6154SDavid Hildenbrand uint64_t size = memory_device_get_region_size(MEMORY_DEVICE(dimm), 3575946d6154SDavid Hildenbrand &error_abort); 357616ee9980SDaniel Henrique Barboza uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 357716ee9980SDaniel Henrique Barboza uint32_t avail_lmbs = 0; 357816ee9980SDaniel Henrique Barboza uint64_t addr_start, addr; 357916ee9980SDaniel Henrique Barboza int i; 358016ee9980SDaniel Henrique Barboza 358116ee9980SDaniel Henrique Barboza addr_start = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, 358216ee9980SDaniel Henrique Barboza &error_abort); 358316ee9980SDaniel Henrique Barboza 358416ee9980SDaniel Henrique Barboza addr = addr_start; 358516ee9980SDaniel Henrique Barboza for (i = 0; i < nr_lmbs; i++) { 3586fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 358716ee9980SDaniel Henrique Barboza addr / SPAPR_MEMORY_BLOCK_SIZE); 358816ee9980SDaniel Henrique Barboza g_assert(drc); 3589454b580aSDavid Gibson if (drc->dev) { 359016ee9980SDaniel Henrique Barboza avail_lmbs++; 359116ee9980SDaniel Henrique Barboza } 359216ee9980SDaniel Henrique Barboza addr += SPAPR_MEMORY_BLOCK_SIZE; 359316ee9980SDaniel Henrique Barboza } 359416ee9980SDaniel Henrique Barboza 35958d5981c4SBharata B Rao return spapr_pending_dimm_unplugs_add(ms, avail_lmbs, dimm); 359616ee9980SDaniel Henrique Barboza } 359716ee9980SDaniel Henrique Barboza 359831834723SDaniel Henrique Barboza /* Callback to be called during DRC release. */ 359931834723SDaniel Henrique Barboza void spapr_lmb_release(DeviceState *dev) 3600cf632463SBharata B Rao { 36013ec71474SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3602ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl); 3603ce2918cbSDavid Gibson SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); 3604cf632463SBharata B Rao 360516ee9980SDaniel Henrique Barboza /* This information will get lost if a migration occurs 360616ee9980SDaniel Henrique Barboza * during the unplug process. In this case recover it. */ 360716ee9980SDaniel Henrique Barboza if (ds == NULL) { 360816ee9980SDaniel Henrique Barboza ds = spapr_recover_pending_dimm_state(spapr, PC_DIMM(dev)); 36098d5981c4SBharata B Rao g_assert(ds); 3610454b580aSDavid Gibson /* The DRC being examined by the caller at least must be counted */ 3611454b580aSDavid Gibson g_assert(ds->nr_lmbs); 361216ee9980SDaniel Henrique Barboza } 3613454b580aSDavid Gibson 3614454b580aSDavid Gibson if (--ds->nr_lmbs) { 3615cf632463SBharata B Rao return; 3616cf632463SBharata B Rao } 3617cf632463SBharata B Rao 3618cf632463SBharata B Rao /* 3619cf632463SBharata B Rao * Now that all the LMBs have been removed by the guest, call the 36203ec71474SDavid Hildenbrand * unplug handler chain. This can never fail. 3621cf632463SBharata B Rao */ 36223ec71474SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 362307578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 36243ec71474SDavid Hildenbrand } 36253ec71474SDavid Hildenbrand 36263ec71474SDavid Hildenbrand static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 36273ec71474SDavid Hildenbrand { 3628ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3629ce2918cbSDavid Gibson SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); 36303ec71474SDavid Hildenbrand 3631fd3416f5SDavid Hildenbrand pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev)); 363207578b0aSDavid Hildenbrand object_property_set_bool(OBJECT(dev), false, "realized", NULL); 36332a129767SDaniel Henrique Barboza spapr_pending_dimm_unplugs_remove(spapr, ds); 3634cf632463SBharata B Rao } 3635cf632463SBharata B Rao 3636cf632463SBharata B Rao static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, 3637cf632463SBharata B Rao DeviceState *dev, Error **errp) 3638cf632463SBharata B Rao { 3639ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3640cf632463SBharata B Rao Error *local_err = NULL; 3641cf632463SBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 364204790978SThomas Huth uint32_t nr_lmbs; 364304790978SThomas Huth uint64_t size, addr_start, addr; 36440cffce56SDavid Gibson int i; 3645ce2918cbSDavid Gibson SpaprDrc *drc; 364604790978SThomas Huth 3647946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &error_abort); 364804790978SThomas Huth nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 364904790978SThomas Huth 36509ed442b8SMarc-André Lureau addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, 36510cffce56SDavid Gibson &local_err); 3652cf632463SBharata B Rao if (local_err) { 3653cf632463SBharata B Rao goto out; 3654cf632463SBharata B Rao } 3655cf632463SBharata B Rao 36562a129767SDaniel Henrique Barboza /* 36572a129767SDaniel Henrique Barboza * An existing pending dimm state for this DIMM means that there is an 36582a129767SDaniel Henrique Barboza * unplug operation in progress, waiting for the spapr_lmb_release 36592a129767SDaniel Henrique Barboza * callback to complete the job (BQL can't cover that far). In this case, 36602a129767SDaniel Henrique Barboza * bail out to avoid detaching DRCs that were already released. 36612a129767SDaniel Henrique Barboza */ 36622a129767SDaniel Henrique Barboza if (spapr_pending_dimm_unplugs_find(spapr, dimm)) { 36632a129767SDaniel Henrique Barboza error_setg(&local_err, 36642a129767SDaniel Henrique Barboza "Memory unplug already in progress for device %s", 36652a129767SDaniel Henrique Barboza dev->id); 36662a129767SDaniel Henrique Barboza goto out; 36672a129767SDaniel Henrique Barboza } 36682a129767SDaniel Henrique Barboza 36698d5981c4SBharata B Rao spapr_pending_dimm_unplugs_add(spapr, nr_lmbs, dimm); 36700cffce56SDavid Gibson 36710cffce56SDavid Gibson addr = addr_start; 36720cffce56SDavid Gibson for (i = 0; i < nr_lmbs; i++) { 3673fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 36740cffce56SDavid Gibson addr / SPAPR_MEMORY_BLOCK_SIZE); 36750cffce56SDavid Gibson g_assert(drc); 36760cffce56SDavid Gibson 3677a8dc47fdSDavid Gibson spapr_drc_detach(drc); 36780cffce56SDavid Gibson addr += SPAPR_MEMORY_BLOCK_SIZE; 36790cffce56SDavid Gibson } 36800cffce56SDavid Gibson 3681fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 36820cffce56SDavid Gibson addr_start / SPAPR_MEMORY_BLOCK_SIZE); 36830cffce56SDavid Gibson spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 36840b55aa91SDavid Gibson nr_lmbs, spapr_drc_index(drc)); 3685cf632463SBharata B Rao out: 3686cf632463SBharata B Rao error_propagate(errp, local_err); 3687cf632463SBharata B Rao } 3688cf632463SBharata B Rao 3689765d1bddSDavid Gibson /* Callback to be called during DRC release. */ 3690765d1bddSDavid Gibson void spapr_core_release(DeviceState *dev) 3691ff9006ddSIgor Mammedov { 3692a4261be1SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3693a4261be1SDavid Hildenbrand 3694a4261be1SDavid Hildenbrand /* Call the unplug handler chain. This can never fail. */ 3695a4261be1SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 369607578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 3697a4261be1SDavid Hildenbrand } 3698a4261be1SDavid Hildenbrand 3699a4261be1SDavid Hildenbrand static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 3700a4261be1SDavid Hildenbrand { 3701a4261be1SDavid Hildenbrand MachineState *ms = MACHINE(hotplug_dev); 3702ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms); 3703ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3704535455fdSIgor Mammedov CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL); 3705ff9006ddSIgor Mammedov 370646f7afa3SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 3707ce2918cbSDavid Gibson SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); 370846f7afa3SGreg Kurz int i; 370946f7afa3SGreg Kurz 371046f7afa3SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 371194ad93bdSGreg Kurz CPUState *cs = CPU(sc->threads[i]); 371246f7afa3SGreg Kurz 371346f7afa3SGreg Kurz pre_2_10_vmstate_register_dummy_icp(cs->cpu_index); 371446f7afa3SGreg Kurz } 371546f7afa3SGreg Kurz } 371646f7afa3SGreg Kurz 371707572c06SGreg Kurz assert(core_slot); 3718535455fdSIgor Mammedov core_slot->cpu = NULL; 371907578b0aSDavid Hildenbrand object_property_set_bool(OBJECT(dev), false, "realized", NULL); 3720ff9006ddSIgor Mammedov } 3721ff9006ddSIgor Mammedov 3722115debf2SIgor Mammedov static 3723115debf2SIgor Mammedov void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, 3724ff9006ddSIgor Mammedov Error **errp) 3725ff9006ddSIgor Mammedov { 3726ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3727535455fdSIgor Mammedov int index; 3728ce2918cbSDavid Gibson SpaprDrc *drc; 3729535455fdSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3730ff9006ddSIgor Mammedov 3731535455fdSIgor Mammedov if (!spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index)) { 3732535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 3733535455fdSIgor Mammedov cc->core_id); 3734535455fdSIgor Mammedov return; 3735535455fdSIgor Mammedov } 3736ff9006ddSIgor Mammedov if (index == 0) { 3737ff9006ddSIgor Mammedov error_setg(errp, "Boot CPU core may not be unplugged"); 3738ff9006ddSIgor Mammedov return; 3739ff9006ddSIgor Mammedov } 3740ff9006ddSIgor Mammedov 37415d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 37425d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 3743ff9006ddSIgor Mammedov g_assert(drc); 3744ff9006ddSIgor Mammedov 3745a8dc47fdSDavid Gibson spapr_drc_detach(drc); 3746ff9006ddSIgor Mammedov 3747ff9006ddSIgor Mammedov spapr_hotplug_req_remove_by_index(drc); 3748ff9006ddSIgor Mammedov } 3749ff9006ddSIgor Mammedov 3750ce2918cbSDavid Gibson int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 3751345b12b9SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 3752345b12b9SGreg Kurz { 3753ce2918cbSDavid Gibson SpaprCpuCore *core = SPAPR_CPU_CORE(drc->dev); 3754345b12b9SGreg Kurz CPUState *cs = CPU(core->threads[0]); 3755345b12b9SGreg Kurz PowerPCCPU *cpu = POWERPC_CPU(cs); 3756345b12b9SGreg Kurz DeviceClass *dc = DEVICE_GET_CLASS(cs); 3757345b12b9SGreg Kurz int id = spapr_get_vcpu_id(cpu); 3758345b12b9SGreg Kurz char *nodename; 3759345b12b9SGreg Kurz int offset; 3760345b12b9SGreg Kurz 3761345b12b9SGreg Kurz nodename = g_strdup_printf("%s@%x", dc->fw_name, id); 3762345b12b9SGreg Kurz offset = fdt_add_subnode(fdt, 0, nodename); 3763345b12b9SGreg Kurz g_free(nodename); 3764345b12b9SGreg Kurz 3765345b12b9SGreg Kurz spapr_populate_cpu_dt(cs, fdt, offset, spapr); 3766345b12b9SGreg Kurz 3767345b12b9SGreg Kurz *fdt_start_offset = offset; 3768345b12b9SGreg Kurz return 0; 3769345b12b9SGreg Kurz } 3770345b12b9SGreg Kurz 3771ff9006ddSIgor Mammedov static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3772ff9006ddSIgor Mammedov Error **errp) 3773ff9006ddSIgor Mammedov { 3774ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3775ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(spapr); 3776ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 3777ce2918cbSDavid Gibson SpaprCpuCore *core = SPAPR_CPU_CORE(OBJECT(dev)); 3778ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3779345b12b9SGreg Kurz CPUState *cs; 3780ce2918cbSDavid Gibson SpaprDrc *drc; 3781ff9006ddSIgor Mammedov Error *local_err = NULL; 3782535455fdSIgor Mammedov CPUArchId *core_slot; 3783535455fdSIgor Mammedov int index; 378494fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 3785b1e81567SGreg Kurz int i; 3786ff9006ddSIgor Mammedov 3787535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 3788535455fdSIgor Mammedov if (!core_slot) { 3789535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 3790535455fdSIgor Mammedov cc->core_id); 3791535455fdSIgor Mammedov return; 3792535455fdSIgor Mammedov } 37935d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 37945d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 3795ff9006ddSIgor Mammedov 3796c5514d0eSIgor Mammedov g_assert(drc || !mc->has_hotpluggable_cpus); 3797ff9006ddSIgor Mammedov 3798e49c63d5SGreg Kurz if (drc) { 379909d876ceSGreg Kurz spapr_drc_attach(drc, dev, &local_err); 3800ff9006ddSIgor Mammedov if (local_err) { 3801ff9006ddSIgor Mammedov error_propagate(errp, local_err); 3802ff9006ddSIgor Mammedov return; 3803ff9006ddSIgor Mammedov } 3804ff9006ddSIgor Mammedov 380594fd9cbaSLaurent Vivier if (hotplugged) { 3806ff9006ddSIgor Mammedov /* 380794fd9cbaSLaurent Vivier * Send hotplug notification interrupt to the guest only 380894fd9cbaSLaurent Vivier * in case of hotplugged CPUs. 3809ff9006ddSIgor Mammedov */ 3810ff9006ddSIgor Mammedov spapr_hotplug_req_add_by_index(drc); 381194fd9cbaSLaurent Vivier } else { 381294fd9cbaSLaurent Vivier spapr_drc_reset(drc); 3813ff9006ddSIgor Mammedov } 381494fd9cbaSLaurent Vivier } 381594fd9cbaSLaurent Vivier 3816535455fdSIgor Mammedov core_slot->cpu = OBJECT(dev); 381746f7afa3SGreg Kurz 381846f7afa3SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 381946f7afa3SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 3820bc877283SGreg Kurz cs = CPU(core->threads[i]); 382146f7afa3SGreg Kurz pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index); 382246f7afa3SGreg Kurz } 382346f7afa3SGreg Kurz } 3824b1e81567SGreg Kurz 3825b1e81567SGreg Kurz /* 3826b1e81567SGreg Kurz * Set compatibility mode to match the boot CPU, which was either set 3827b1e81567SGreg Kurz * by the machine reset code or by CAS. 3828b1e81567SGreg Kurz */ 3829b1e81567SGreg Kurz if (hotplugged) { 3830b1e81567SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 3831b1e81567SGreg Kurz ppc_set_compat(core->threads[i], POWERPC_CPU(first_cpu)->compat_pvr, 3832b1e81567SGreg Kurz &local_err); 3833b1e81567SGreg Kurz if (local_err) { 3834b1e81567SGreg Kurz error_propagate(errp, local_err); 3835b1e81567SGreg Kurz return; 3836b1e81567SGreg Kurz } 3837b1e81567SGreg Kurz } 3838b1e81567SGreg Kurz } 3839ff9006ddSIgor Mammedov } 3840ff9006ddSIgor Mammedov 3841ff9006ddSIgor Mammedov static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3842ff9006ddSIgor Mammedov Error **errp) 3843ff9006ddSIgor Mammedov { 3844ff9006ddSIgor Mammedov MachineState *machine = MACHINE(OBJECT(hotplug_dev)); 3845ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); 3846ff9006ddSIgor Mammedov Error *local_err = NULL; 3847ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 38482e9c10ebSIgor Mammedov const char *base_core_type = spapr_get_cpu_core_type(machine->cpu_type); 3849ff9006ddSIgor Mammedov const char *type = object_get_typename(OBJECT(dev)); 3850535455fdSIgor Mammedov CPUArchId *core_slot; 3851535455fdSIgor Mammedov int index; 3852fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 3853ff9006ddSIgor Mammedov 3854c5514d0eSIgor Mammedov if (dev->hotplugged && !mc->has_hotpluggable_cpus) { 3855ff9006ddSIgor Mammedov error_setg(&local_err, "CPU hotplug not supported for this machine"); 3856ff9006ddSIgor Mammedov goto out; 3857ff9006ddSIgor Mammedov } 3858ff9006ddSIgor Mammedov 3859ff9006ddSIgor Mammedov if (strcmp(base_core_type, type)) { 3860ff9006ddSIgor Mammedov error_setg(&local_err, "CPU core type should be %s", base_core_type); 3861ff9006ddSIgor Mammedov goto out; 3862ff9006ddSIgor Mammedov } 3863ff9006ddSIgor Mammedov 3864ff9006ddSIgor Mammedov if (cc->core_id % smp_threads) { 3865ff9006ddSIgor Mammedov error_setg(&local_err, "invalid core id %d", cc->core_id); 3866ff9006ddSIgor Mammedov goto out; 3867ff9006ddSIgor Mammedov } 3868ff9006ddSIgor Mammedov 3869459264efSDavid Gibson /* 3870459264efSDavid Gibson * In general we should have homogeneous threads-per-core, but old 3871459264efSDavid Gibson * (pre hotplug support) machine types allow the last core to have 3872459264efSDavid Gibson * reduced threads as a compatibility hack for when we allowed 3873459264efSDavid Gibson * total vcpus not a multiple of threads-per-core. 3874459264efSDavid Gibson */ 3875459264efSDavid Gibson if (mc->has_hotpluggable_cpus && (cc->nr_threads != smp_threads)) { 3876df8658deSGreg Kurz error_setg(&local_err, "invalid nr-threads %d, must be %d", 38778149e299SDavid Gibson cc->nr_threads, smp_threads); 3878df8658deSGreg Kurz goto out; 38798149e299SDavid Gibson } 38808149e299SDavid Gibson 3881535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 3882535455fdSIgor Mammedov if (!core_slot) { 3883ff9006ddSIgor Mammedov error_setg(&local_err, "core id %d out of range", cc->core_id); 3884ff9006ddSIgor Mammedov goto out; 3885ff9006ddSIgor Mammedov } 3886ff9006ddSIgor Mammedov 3887535455fdSIgor Mammedov if (core_slot->cpu) { 3888ff9006ddSIgor Mammedov error_setg(&local_err, "core %d already populated", cc->core_id); 3889ff9006ddSIgor Mammedov goto out; 3890ff9006ddSIgor Mammedov } 3891ff9006ddSIgor Mammedov 3892a0ceb640SIgor Mammedov numa_cpu_pre_plug(core_slot, dev, &local_err); 38930b8497f0SIgor Mammedov 3894ff9006ddSIgor Mammedov out: 3895ff9006ddSIgor Mammedov error_propagate(errp, local_err); 3896ff9006ddSIgor Mammedov } 3897ff9006ddSIgor Mammedov 3898ce2918cbSDavid Gibson int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 3899bb2bdd81SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 3900bb2bdd81SGreg Kurz { 3901ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(drc->dev); 3902bb2bdd81SGreg Kurz int intc_phandle; 3903bb2bdd81SGreg Kurz 3904bb2bdd81SGreg Kurz intc_phandle = spapr_irq_get_phandle(spapr, spapr->fdt_blob, errp); 3905bb2bdd81SGreg Kurz if (intc_phandle <= 0) { 3906bb2bdd81SGreg Kurz return -1; 3907bb2bdd81SGreg Kurz } 3908bb2bdd81SGreg Kurz 3909466e8831SDavid Gibson if (spapr_dt_phb(sphb, intc_phandle, fdt, spapr->irq->nr_msis, 3910bb2bdd81SGreg Kurz fdt_start_offset)) { 3911bb2bdd81SGreg Kurz error_setg(errp, "unable to create FDT node for PHB %d", sphb->index); 3912bb2bdd81SGreg Kurz return -1; 3913bb2bdd81SGreg Kurz } 3914bb2bdd81SGreg Kurz 3915bb2bdd81SGreg Kurz /* generally SLOF creates these, for hotplug it's up to QEMU */ 3916bb2bdd81SGreg Kurz _FDT(fdt_setprop_string(fdt, *fdt_start_offset, "name", "pci")); 3917bb2bdd81SGreg Kurz 3918bb2bdd81SGreg Kurz return 0; 3919bb2bdd81SGreg Kurz } 3920bb2bdd81SGreg Kurz 3921bb2bdd81SGreg Kurz static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3922bb2bdd81SGreg Kurz Error **errp) 3923bb2bdd81SGreg Kurz { 3924ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3925ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 3926ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 3927bb2bdd81SGreg Kurz const unsigned windows_supported = spapr_phb_windows_supported(sphb); 3928bb2bdd81SGreg Kurz 3929bb2bdd81SGreg Kurz if (dev->hotplugged && !smc->dr_phb_enabled) { 3930bb2bdd81SGreg Kurz error_setg(errp, "PHB hotplug not supported for this machine"); 3931bb2bdd81SGreg Kurz return; 3932bb2bdd81SGreg Kurz } 3933bb2bdd81SGreg Kurz 3934bb2bdd81SGreg Kurz if (sphb->index == (uint32_t)-1) { 3935bb2bdd81SGreg Kurz error_setg(errp, "\"index\" for PAPR PHB is mandatory"); 3936bb2bdd81SGreg Kurz return; 3937bb2bdd81SGreg Kurz } 3938bb2bdd81SGreg Kurz 3939bb2bdd81SGreg Kurz /* 3940bb2bdd81SGreg Kurz * This will check that sphb->index doesn't exceed the maximum number of 3941bb2bdd81SGreg Kurz * PHBs for the current machine type. 3942bb2bdd81SGreg Kurz */ 3943bb2bdd81SGreg Kurz smc->phb_placement(spapr, sphb->index, 3944bb2bdd81SGreg Kurz &sphb->buid, &sphb->io_win_addr, 3945bb2bdd81SGreg Kurz &sphb->mem_win_addr, &sphb->mem64_win_addr, 3946ec132efaSAlexey Kardashevskiy windows_supported, sphb->dma_liobn, 3947ec132efaSAlexey Kardashevskiy &sphb->nv2_gpa_win_addr, &sphb->nv2_atsd_win_addr, 3948ec132efaSAlexey Kardashevskiy errp); 3949bb2bdd81SGreg Kurz } 3950bb2bdd81SGreg Kurz 3951bb2bdd81SGreg Kurz static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3952bb2bdd81SGreg Kurz Error **errp) 3953bb2bdd81SGreg Kurz { 3954ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3955ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 3956ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 3957ce2918cbSDavid Gibson SpaprDrc *drc; 3958bb2bdd81SGreg Kurz bool hotplugged = spapr_drc_hotplugged(dev); 3959bb2bdd81SGreg Kurz Error *local_err = NULL; 3960bb2bdd81SGreg Kurz 3961bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) { 3962bb2bdd81SGreg Kurz return; 3963bb2bdd81SGreg Kurz } 3964bb2bdd81SGreg Kurz 3965bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); 3966bb2bdd81SGreg Kurz /* hotplug hooks should check it's enabled before getting this far */ 3967bb2bdd81SGreg Kurz assert(drc); 3968bb2bdd81SGreg Kurz 3969bb2bdd81SGreg Kurz spapr_drc_attach(drc, DEVICE(dev), &local_err); 3970bb2bdd81SGreg Kurz if (local_err) { 3971bb2bdd81SGreg Kurz error_propagate(errp, local_err); 3972bb2bdd81SGreg Kurz return; 3973bb2bdd81SGreg Kurz } 3974bb2bdd81SGreg Kurz 3975bb2bdd81SGreg Kurz if (hotplugged) { 3976bb2bdd81SGreg Kurz spapr_hotplug_req_add_by_index(drc); 3977bb2bdd81SGreg Kurz } else { 3978bb2bdd81SGreg Kurz spapr_drc_reset(drc); 3979bb2bdd81SGreg Kurz } 3980bb2bdd81SGreg Kurz } 3981bb2bdd81SGreg Kurz 3982bb2bdd81SGreg Kurz void spapr_phb_release(DeviceState *dev) 3983bb2bdd81SGreg Kurz { 3984bb2bdd81SGreg Kurz HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3985bb2bdd81SGreg Kurz 3986bb2bdd81SGreg Kurz hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 398707578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 3988bb2bdd81SGreg Kurz } 3989bb2bdd81SGreg Kurz 3990bb2bdd81SGreg Kurz static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 3991bb2bdd81SGreg Kurz { 399207578b0aSDavid Hildenbrand object_property_set_bool(OBJECT(dev), false, "realized", NULL); 3993bb2bdd81SGreg Kurz } 3994bb2bdd81SGreg Kurz 3995bb2bdd81SGreg Kurz static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev, 3996bb2bdd81SGreg Kurz DeviceState *dev, Error **errp) 3997bb2bdd81SGreg Kurz { 3998ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 3999ce2918cbSDavid Gibson SpaprDrc *drc; 4000bb2bdd81SGreg Kurz 4001bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); 4002bb2bdd81SGreg Kurz assert(drc); 4003bb2bdd81SGreg Kurz 4004bb2bdd81SGreg Kurz if (!spapr_drc_unplug_requested(drc)) { 4005bb2bdd81SGreg Kurz spapr_drc_detach(drc); 4006bb2bdd81SGreg Kurz spapr_hotplug_req_remove_by_index(drc); 4007bb2bdd81SGreg Kurz } 4008bb2bdd81SGreg Kurz } 4009bb2bdd81SGreg Kurz 40100fb6bd07SMichael Roth static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 40110fb6bd07SMichael Roth Error **errp) 40120fb6bd07SMichael Roth { 40130fb6bd07SMichael Roth SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 40140fb6bd07SMichael Roth SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(dev); 40150fb6bd07SMichael Roth 40160fb6bd07SMichael Roth if (spapr->tpm_proxy != NULL) { 40170fb6bd07SMichael Roth error_setg(errp, "Only one TPM proxy can be specified for this machine"); 40180fb6bd07SMichael Roth return; 40190fb6bd07SMichael Roth } 40200fb6bd07SMichael Roth 40210fb6bd07SMichael Roth spapr->tpm_proxy = tpm_proxy; 40220fb6bd07SMichael Roth } 40230fb6bd07SMichael Roth 40240fb6bd07SMichael Roth static void spapr_tpm_proxy_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 40250fb6bd07SMichael Roth { 40260fb6bd07SMichael Roth SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 40270fb6bd07SMichael Roth 40280fb6bd07SMichael Roth object_property_set_bool(OBJECT(dev), false, "realized", NULL); 40290fb6bd07SMichael Roth object_unparent(OBJECT(dev)); 40300fb6bd07SMichael Roth spapr->tpm_proxy = NULL; 40310fb6bd07SMichael Roth } 40320fb6bd07SMichael Roth 4033c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, 4034c20d332aSBharata B Rao DeviceState *dev, Error **errp) 4035c20d332aSBharata B Rao { 4036c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 403781985f3bSDavid Hildenbrand spapr_memory_plug(hotplug_dev, dev, errp); 4038af81cf32SBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4039af81cf32SBharata B Rao spapr_core_plug(hotplug_dev, dev, errp); 4040bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4041bb2bdd81SGreg Kurz spapr_phb_plug(hotplug_dev, dev, errp); 40420fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 40430fb6bd07SMichael Roth spapr_tpm_proxy_plug(hotplug_dev, dev, errp); 4044c20d332aSBharata B Rao } 4045c20d332aSBharata B Rao } 4046c20d332aSBharata B Rao 404788432f44SDavid Hildenbrand static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, 404888432f44SDavid Hildenbrand DeviceState *dev, Error **errp) 404988432f44SDavid Hildenbrand { 40503ec71474SDavid Hildenbrand if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 40513ec71474SDavid Hildenbrand spapr_memory_unplug(hotplug_dev, dev); 4052a4261be1SDavid Hildenbrand } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4053a4261be1SDavid Hildenbrand spapr_core_unplug(hotplug_dev, dev); 4054bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4055bb2bdd81SGreg Kurz spapr_phb_unplug(hotplug_dev, dev); 40560fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 40570fb6bd07SMichael Roth spapr_tpm_proxy_unplug(hotplug_dev, dev); 40583ec71474SDavid Hildenbrand } 405988432f44SDavid Hildenbrand } 406088432f44SDavid Hildenbrand 4061cf632463SBharata B Rao static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev, 4062cf632463SBharata B Rao DeviceState *dev, Error **errp) 4063cf632463SBharata B Rao { 4064ce2918cbSDavid Gibson SpaprMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev)); 4065c86c1affSDaniel Henrique Barboza MachineClass *mc = MACHINE_GET_CLASS(sms); 4066ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4067cf632463SBharata B Rao 4068cf632463SBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 4069cf632463SBharata B Rao if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) { 4070cf632463SBharata B Rao spapr_memory_unplug_request(hotplug_dev, dev, errp); 4071cf632463SBharata B Rao } else { 4072cf632463SBharata B Rao /* NOTE: this means there is a window after guest reset, prior to 4073cf632463SBharata B Rao * CAS negotiation, where unplug requests will fail due to the 4074cf632463SBharata B Rao * capability not being detected yet. This is a bit different than 4075cf632463SBharata B Rao * the case with PCI unplug, where the events will be queued and 4076cf632463SBharata B Rao * eventually handled by the guest after boot 4077cf632463SBharata B Rao */ 4078cf632463SBharata B Rao error_setg(errp, "Memory hot unplug not supported for this guest"); 4079cf632463SBharata B Rao } 40806f4b5c3eSBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4081c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 40826f4b5c3eSBharata B Rao error_setg(errp, "CPU hot unplug not supported on this machine"); 40836f4b5c3eSBharata B Rao return; 40846f4b5c3eSBharata B Rao } 4085115debf2SIgor Mammedov spapr_core_unplug_request(hotplug_dev, dev, errp); 4086bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4087bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) { 4088bb2bdd81SGreg Kurz error_setg(errp, "PHB hot unplug not supported on this machine"); 4089bb2bdd81SGreg Kurz return; 4090bb2bdd81SGreg Kurz } 4091bb2bdd81SGreg Kurz spapr_phb_unplug_request(hotplug_dev, dev, errp); 40920fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 40930fb6bd07SMichael Roth spapr_tpm_proxy_unplug(hotplug_dev, dev); 4094c20d332aSBharata B Rao } 4095c20d332aSBharata B Rao } 4096c20d332aSBharata B Rao 409794a94e4cSBharata B Rao static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, 409894a94e4cSBharata B Rao DeviceState *dev, Error **errp) 409994a94e4cSBharata B Rao { 4100c871bc70SLaurent Vivier if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 4101c871bc70SLaurent Vivier spapr_memory_pre_plug(hotplug_dev, dev, errp); 4102c871bc70SLaurent Vivier } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 410394a94e4cSBharata B Rao spapr_core_pre_plug(hotplug_dev, dev, errp); 4104bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4105bb2bdd81SGreg Kurz spapr_phb_pre_plug(hotplug_dev, dev, errp); 410694a94e4cSBharata B Rao } 410794a94e4cSBharata B Rao } 410894a94e4cSBharata B Rao 41097ebaf795SBharata B Rao static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine, 4110c20d332aSBharata B Rao DeviceState *dev) 4111c20d332aSBharata B Rao { 411294a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || 4113bb2bdd81SGreg Kurz object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE) || 41140fb6bd07SMichael Roth object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE) || 41150fb6bd07SMichael Roth object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 4116c20d332aSBharata B Rao return HOTPLUG_HANDLER(machine); 4117c20d332aSBharata B Rao } 4118cb600087SDavid Gibson if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { 4119cb600087SDavid Gibson PCIDevice *pcidev = PCI_DEVICE(dev); 4120cb600087SDavid Gibson PCIBus *root = pci_device_root_bus(pcidev); 4121cb600087SDavid Gibson SpaprPhbState *phb = 4122cb600087SDavid Gibson (SpaprPhbState *)object_dynamic_cast(OBJECT(BUS(root)->parent), 4123cb600087SDavid Gibson TYPE_SPAPR_PCI_HOST_BRIDGE); 4124cb600087SDavid Gibson 4125cb600087SDavid Gibson if (phb) { 4126cb600087SDavid Gibson return HOTPLUG_HANDLER(phb); 4127cb600087SDavid Gibson } 4128cb600087SDavid Gibson } 4129c20d332aSBharata B Rao return NULL; 4130c20d332aSBharata B Rao } 4131c20d332aSBharata B Rao 4132ea089eebSIgor Mammedov static CpuInstanceProperties 4133ea089eebSIgor Mammedov spapr_cpu_index_to_props(MachineState *machine, unsigned cpu_index) 413420bb648dSDavid Gibson { 4135ea089eebSIgor Mammedov CPUArchId *core_slot; 4136ea089eebSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 4137ea089eebSIgor Mammedov 4138ea089eebSIgor Mammedov /* make sure possible_cpu are intialized */ 4139ea089eebSIgor Mammedov mc->possible_cpu_arch_ids(machine); 4140ea089eebSIgor Mammedov /* get CPU core slot containing thread that matches cpu_index */ 4141ea089eebSIgor Mammedov core_slot = spapr_find_cpu_slot(machine, cpu_index, NULL); 4142ea089eebSIgor Mammedov assert(core_slot); 4143ea089eebSIgor Mammedov return core_slot->props; 414420bb648dSDavid Gibson } 414520bb648dSDavid Gibson 414679e07936SIgor Mammedov static int64_t spapr_get_default_cpu_node_id(const MachineState *ms, int idx) 414779e07936SIgor Mammedov { 4148aa570207STao Xu return idx / ms->smp.cores % ms->numa_state->num_nodes; 414979e07936SIgor Mammedov } 415079e07936SIgor Mammedov 4151535455fdSIgor Mammedov static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine) 4152535455fdSIgor Mammedov { 4153535455fdSIgor Mammedov int i; 4154fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 4155fe6b6346SLike Xu unsigned int smp_cpus = machine->smp.cpus; 4156d342eb76SIgor Mammedov const char *core_type; 4157fe6b6346SLike Xu int spapr_max_cores = machine->smp.max_cpus / smp_threads; 4158535455fdSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 4159535455fdSIgor Mammedov 4160c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 4161535455fdSIgor Mammedov spapr_max_cores = QEMU_ALIGN_UP(smp_cpus, smp_threads) / smp_threads; 4162535455fdSIgor Mammedov } 4163535455fdSIgor Mammedov if (machine->possible_cpus) { 4164535455fdSIgor Mammedov assert(machine->possible_cpus->len == spapr_max_cores); 4165535455fdSIgor Mammedov return machine->possible_cpus; 4166535455fdSIgor Mammedov } 4167535455fdSIgor Mammedov 4168d342eb76SIgor Mammedov core_type = spapr_get_cpu_core_type(machine->cpu_type); 4169d342eb76SIgor Mammedov if (!core_type) { 4170d342eb76SIgor Mammedov error_report("Unable to find sPAPR CPU Core definition"); 4171d342eb76SIgor Mammedov exit(1); 4172d342eb76SIgor Mammedov } 4173d342eb76SIgor Mammedov 4174535455fdSIgor Mammedov machine->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + 4175535455fdSIgor Mammedov sizeof(CPUArchId) * spapr_max_cores); 4176535455fdSIgor Mammedov machine->possible_cpus->len = spapr_max_cores; 4177535455fdSIgor Mammedov for (i = 0; i < machine->possible_cpus->len; i++) { 4178535455fdSIgor Mammedov int core_id = i * smp_threads; 4179535455fdSIgor Mammedov 4180d342eb76SIgor Mammedov machine->possible_cpus->cpus[i].type = core_type; 4181f2d672c2SIgor Mammedov machine->possible_cpus->cpus[i].vcpus_count = smp_threads; 4182535455fdSIgor Mammedov machine->possible_cpus->cpus[i].arch_id = core_id; 4183535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.has_core_id = true; 4184535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.core_id = core_id; 4185535455fdSIgor Mammedov } 4186535455fdSIgor Mammedov return machine->possible_cpus; 4187535455fdSIgor Mammedov } 4188535455fdSIgor Mammedov 4189ce2918cbSDavid Gibson static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index, 4190daa23699SDavid Gibson uint64_t *buid, hwaddr *pio, 4191daa23699SDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 4192ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4193ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 41946737d9adSDavid Gibson { 4195357d1e3bSDavid Gibson /* 4196357d1e3bSDavid Gibson * New-style PHB window placement. 4197357d1e3bSDavid Gibson * 4198357d1e3bSDavid Gibson * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window 4199357d1e3bSDavid Gibson * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO 4200357d1e3bSDavid Gibson * windows. 4201357d1e3bSDavid Gibson * 4202357d1e3bSDavid Gibson * Some guest kernels can't work with MMIO windows above 1<<46 4203357d1e3bSDavid Gibson * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB 4204357d1e3bSDavid Gibson * 4205357d1e3bSDavid Gibson * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each 4206357d1e3bSDavid Gibson * PHB stacked together. (32TiB+2GiB)..(32TiB+64GiB) contains the 4207357d1e3bSDavid Gibson * 2GiB 32-bit MMIO windows for each PHB. Then 33..64TiB has the 4208357d1e3bSDavid Gibson * 1TiB 64-bit MMIO windows for each PHB. 4209357d1e3bSDavid Gibson */ 42106737d9adSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 42116737d9adSDavid Gibson int i; 42126737d9adSDavid Gibson 4213357d1e3bSDavid Gibson /* Sanity check natural alignments */ 4214357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 4215357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 4216357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0); 4217357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0); 4218357d1e3bSDavid Gibson /* Sanity check bounds */ 421925e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_IO_WIN_SIZE) > 422025e6a118SMichael S. Tsirkin SPAPR_PCI_MEM32_WIN_SIZE); 422125e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_MEM32_WIN_SIZE) > 422225e6a118SMichael S. Tsirkin SPAPR_PCI_MEM64_WIN_SIZE); 42232efff1c0SDavid Gibson 422425e6a118SMichael S. Tsirkin if (index >= SPAPR_MAX_PHBS) { 422525e6a118SMichael S. Tsirkin error_setg(errp, "\"index\" for PAPR PHB is too large (max %llu)", 422625e6a118SMichael S. Tsirkin SPAPR_MAX_PHBS - 1); 42276737d9adSDavid Gibson return; 42286737d9adSDavid Gibson } 42296737d9adSDavid Gibson 42306737d9adSDavid Gibson *buid = base_buid + index; 42316737d9adSDavid Gibson for (i = 0; i < n_dma; ++i) { 42326737d9adSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 42336737d9adSDavid Gibson } 42346737d9adSDavid Gibson 4235357d1e3bSDavid Gibson *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE; 4236357d1e3bSDavid Gibson *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE; 4237357d1e3bSDavid Gibson *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE; 4238ec132efaSAlexey Kardashevskiy 4239ec132efaSAlexey Kardashevskiy *nv2gpa = SPAPR_PCI_NV2RAM64_WIN_BASE + index * SPAPR_PCI_NV2RAM64_WIN_SIZE; 4240ec132efaSAlexey Kardashevskiy *nv2atsd = SPAPR_PCI_NV2ATSD_WIN_BASE + index * SPAPR_PCI_NV2ATSD_WIN_SIZE; 42416737d9adSDavid Gibson } 42426737d9adSDavid Gibson 42437844e12bSCédric Le Goater static ICSState *spapr_ics_get(XICSFabric *dev, int irq) 42447844e12bSCédric Le Goater { 4245ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(dev); 42467844e12bSCédric Le Goater 42477844e12bSCédric Le Goater return ics_valid_irq(spapr->ics, irq) ? spapr->ics : NULL; 42487844e12bSCédric Le Goater } 42497844e12bSCédric Le Goater 42507844e12bSCédric Le Goater static void spapr_ics_resend(XICSFabric *dev) 42517844e12bSCédric Le Goater { 4252ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(dev); 42537844e12bSCédric Le Goater 42547844e12bSCédric Le Goater ics_resend(spapr->ics); 42557844e12bSCédric Le Goater } 42567844e12bSCédric Le Goater 425781210c20SSam Bobroff static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id) 4258b2fc59aaSCédric Le Goater { 42592e886fb3SSam Bobroff PowerPCCPU *cpu = spapr_find_cpu(vcpu_id); 4260b2fc59aaSCédric Le Goater 4261a28b9a5aSCédric Le Goater return cpu ? spapr_cpu_state(cpu)->icp : NULL; 4262b2fc59aaSCédric Le Goater } 4263b2fc59aaSCédric Le Goater 42646449da45SCédric Le Goater static void spapr_pic_print_info(InterruptStatsProvider *obj, 42656449da45SCédric Le Goater Monitor *mon) 42666449da45SCédric Le Goater { 4267ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 42686449da45SCédric Le Goater 42693ba3d0bcSCédric Le Goater spapr->irq->print_info(spapr, mon); 4270f041d6afSGreg Kurz monitor_printf(mon, "irqchip: %s\n", 4271f041d6afSGreg Kurz kvm_irqchip_in_kernel() ? "in-kernel" : "emulated"); 42726449da45SCédric Le Goater } 42736449da45SCédric Le Goater 427414bb4486SGreg Kurz int spapr_get_vcpu_id(PowerPCCPU *cpu) 42752e886fb3SSam Bobroff { 4276b1a568c1SGreg Kurz return cpu->vcpu_id; 42772e886fb3SSam Bobroff } 42782e886fb3SSam Bobroff 4279648edb64SGreg Kurz void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp) 4280648edb64SGreg Kurz { 4281ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 4282fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 4283648edb64SGreg Kurz int vcpu_id; 4284648edb64SGreg Kurz 42855d0fb150SGreg Kurz vcpu_id = spapr_vcpu_id(spapr, cpu_index); 4286648edb64SGreg Kurz 4287648edb64SGreg Kurz if (kvm_enabled() && !kvm_vcpu_id_is_valid(vcpu_id)) { 4288648edb64SGreg Kurz error_setg(errp, "Can't create CPU with id %d in KVM", vcpu_id); 4289648edb64SGreg Kurz error_append_hint(errp, "Adjust the number of cpus to %d " 4290648edb64SGreg Kurz "or try to raise the number of threads per core\n", 4291fe6b6346SLike Xu vcpu_id * ms->smp.threads / spapr->vsmt); 4292648edb64SGreg Kurz return; 4293648edb64SGreg Kurz } 4294648edb64SGreg Kurz 4295648edb64SGreg Kurz cpu->vcpu_id = vcpu_id; 4296648edb64SGreg Kurz } 4297648edb64SGreg Kurz 42982e886fb3SSam Bobroff PowerPCCPU *spapr_find_cpu(int vcpu_id) 42992e886fb3SSam Bobroff { 43002e886fb3SSam Bobroff CPUState *cs; 43012e886fb3SSam Bobroff 43022e886fb3SSam Bobroff CPU_FOREACH(cs) { 43032e886fb3SSam Bobroff PowerPCCPU *cpu = POWERPC_CPU(cs); 43042e886fb3SSam Bobroff 430514bb4486SGreg Kurz if (spapr_get_vcpu_id(cpu) == vcpu_id) { 43062e886fb3SSam Bobroff return cpu; 43072e886fb3SSam Bobroff } 43082e886fb3SSam Bobroff } 43092e886fb3SSam Bobroff 43102e886fb3SSam Bobroff return NULL; 43112e886fb3SSam Bobroff } 43122e886fb3SSam Bobroff 431303ef074cSNicholas Piggin static void spapr_cpu_exec_enter(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) 431403ef074cSNicholas Piggin { 431503ef074cSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 431603ef074cSNicholas Piggin 431703ef074cSNicholas Piggin /* These are only called by TCG, KVM maintains dispatch state */ 431803ef074cSNicholas Piggin 43193a6e6224SNicholas Piggin spapr_cpu->prod = false; 432003ef074cSNicholas Piggin if (spapr_cpu->vpa_addr) { 432103ef074cSNicholas Piggin CPUState *cs = CPU(cpu); 432203ef074cSNicholas Piggin uint32_t dispatch; 432303ef074cSNicholas Piggin 432403ef074cSNicholas Piggin dispatch = ldl_be_phys(cs->as, 432503ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER); 432603ef074cSNicholas Piggin dispatch++; 432703ef074cSNicholas Piggin if ((dispatch & 1) != 0) { 432803ef074cSNicholas Piggin qemu_log_mask(LOG_GUEST_ERROR, 432903ef074cSNicholas Piggin "VPA: incorrect dispatch counter value for " 433003ef074cSNicholas Piggin "dispatched partition %u, correcting.\n", dispatch); 433103ef074cSNicholas Piggin dispatch++; 433203ef074cSNicholas Piggin } 433303ef074cSNicholas Piggin stl_be_phys(cs->as, 433403ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch); 433503ef074cSNicholas Piggin } 433603ef074cSNicholas Piggin } 433703ef074cSNicholas Piggin 433803ef074cSNicholas Piggin static void spapr_cpu_exec_exit(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) 433903ef074cSNicholas Piggin { 434003ef074cSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 434103ef074cSNicholas Piggin 434203ef074cSNicholas Piggin if (spapr_cpu->vpa_addr) { 434303ef074cSNicholas Piggin CPUState *cs = CPU(cpu); 434403ef074cSNicholas Piggin uint32_t dispatch; 434503ef074cSNicholas Piggin 434603ef074cSNicholas Piggin dispatch = ldl_be_phys(cs->as, 434703ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER); 434803ef074cSNicholas Piggin dispatch++; 434903ef074cSNicholas Piggin if ((dispatch & 1) != 1) { 435003ef074cSNicholas Piggin qemu_log_mask(LOG_GUEST_ERROR, 435103ef074cSNicholas Piggin "VPA: incorrect dispatch counter value for " 435203ef074cSNicholas Piggin "preempted partition %u, correcting.\n", dispatch); 435303ef074cSNicholas Piggin dispatch++; 435403ef074cSNicholas Piggin } 435503ef074cSNicholas Piggin stl_be_phys(cs->as, 435603ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch); 435703ef074cSNicholas Piggin } 435803ef074cSNicholas Piggin } 435903ef074cSNicholas Piggin 436029ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data) 436153018216SPaolo Bonzini { 436229ee3247SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 4363ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(oc); 436471461b0fSAlexey Kardashevskiy FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); 436534316482SAlexey Kardashevskiy NMIClass *nc = NMI_CLASS(oc); 4366c20d332aSBharata B Rao HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); 43671d1be34dSDavid Gibson PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc); 43687844e12bSCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 43696449da45SCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 437029ee3247SAlexey Kardashevskiy 43710eb9054cSDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant)"; 4372907aac2fSMark Cave-Ayland mc->ignore_boot_device_suffixes = true; 4373fc9f38c3SDavid Gibson 4374fc9f38c3SDavid Gibson /* 4375fc9f38c3SDavid Gibson * We set up the default / latest behaviour here. The class_init 4376fc9f38c3SDavid Gibson * functions for the specific versioned machine types can override 4377fc9f38c3SDavid Gibson * these details for backwards compatibility 4378fc9f38c3SDavid Gibson */ 4379bcb5ce08SDavid Gibson mc->init = spapr_machine_init; 4380bcb5ce08SDavid Gibson mc->reset = spapr_machine_reset; 4381958db90cSMarcel Apfelbaum mc->block_default_type = IF_SCSI; 43826244bb7eSGreg Kurz mc->max_cpus = 1024; 4383958db90cSMarcel Apfelbaum mc->no_parallel = 1; 43845b2128d2SAlexander Graf mc->default_boot_order = ""; 4385d23b6caaSPhilippe Mathieu-Daudé mc->default_ram_size = 512 * MiB; 438629f9cef3SSebastian Bauer mc->default_display = "std"; 4387958db90cSMarcel Apfelbaum mc->kvm_type = spapr_kvm_type; 43887da79a16SEduardo Habkost machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SPAPR_PCI_HOST_BRIDGE); 4389e4024630SLaurent Vivier mc->pci_allow_0_address = true; 4390debbdc00SIgor Mammedov assert(!mc->get_hotplug_handler); 43917ebaf795SBharata B Rao mc->get_hotplug_handler = spapr_get_hotplug_handler; 439294a94e4cSBharata B Rao hc->pre_plug = spapr_machine_device_pre_plug; 4393c20d332aSBharata B Rao hc->plug = spapr_machine_device_plug; 4394ea089eebSIgor Mammedov mc->cpu_index_to_instance_props = spapr_cpu_index_to_props; 439579e07936SIgor Mammedov mc->get_default_cpu_node_id = spapr_get_default_cpu_node_id; 4396535455fdSIgor Mammedov mc->possible_cpu_arch_ids = spapr_possible_cpu_arch_ids; 4397cf632463SBharata B Rao hc->unplug_request = spapr_machine_device_unplug_request; 439888432f44SDavid Hildenbrand hc->unplug = spapr_machine_device_unplug; 439900b4fbe2SMarcel Apfelbaum 4400fc9f38c3SDavid Gibson smc->dr_lmb_enabled = true; 4401fea35ca4SAlexey Kardashevskiy smc->update_dt_enabled = true; 440234a6b015SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 4403c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = true; 440452b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED; 440571461b0fSAlexey Kardashevskiy fwc->get_dev_path = spapr_get_fw_dev_path; 440634316482SAlexey Kardashevskiy nc->nmi_monitor_handler = spapr_nmi; 44076737d9adSDavid Gibson smc->phb_placement = spapr_phb_placement; 44081d1be34dSDavid Gibson vhc->hypercall = emulate_spapr_hypercall; 4409e57ca75cSDavid Gibson vhc->hpt_mask = spapr_hpt_mask; 4410e57ca75cSDavid Gibson vhc->map_hptes = spapr_map_hptes; 4411e57ca75cSDavid Gibson vhc->unmap_hptes = spapr_unmap_hptes; 4412a2dd4e83SBenjamin Herrenschmidt vhc->hpte_set_c = spapr_hpte_set_c; 4413a2dd4e83SBenjamin Herrenschmidt vhc->hpte_set_r = spapr_hpte_set_r; 441479825f4dSBenjamin Herrenschmidt vhc->get_pate = spapr_get_pate; 44151ec26c75SGreg Kurz vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr; 441603ef074cSNicholas Piggin vhc->cpu_exec_enter = spapr_cpu_exec_enter; 441703ef074cSNicholas Piggin vhc->cpu_exec_exit = spapr_cpu_exec_exit; 44187844e12bSCédric Le Goater xic->ics_get = spapr_ics_get; 44197844e12bSCédric Le Goater xic->ics_resend = spapr_ics_resend; 4420b2fc59aaSCédric Le Goater xic->icp_get = spapr_icp_get; 44216449da45SCédric Le Goater ispc->print_info = spapr_pic_print_info; 442255641213SLaurent Vivier /* Force NUMA node memory size to be a multiple of 442355641213SLaurent Vivier * SPAPR_MEMORY_BLOCK_SIZE (256M) since that's the granularity 442455641213SLaurent Vivier * in which LMBs are represented and hot-added 442555641213SLaurent Vivier */ 442655641213SLaurent Vivier mc->numa_mem_align_shift = 28; 4427cd5ff833SIgor Mammedov mc->numa_mem_supported = true; 44280533ef5fSTao Xu mc->auto_enable_numa = true; 442933face6bSDavid Gibson 44304e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF; 44314e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON; 44324e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON; 44332782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND; 44342782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND; 44352782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_WORKAROUND; 44362309832aSDavid Gibson smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */ 4437b9a477b7SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF; 4438edaa7995SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON; 44398ff43ee4SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF; 444033face6bSDavid Gibson spapr_caps_add_properties(smc, &error_abort); 4441bd94bc06SCédric Le Goater smc->irq = &spapr_irq_dual; 4442dae5e39aSMichael Roth smc->dr_phb_enabled = true; 44436c3829a2SAlexey Kardashevskiy smc->linux_pci_probe = true; 4444*29cb4187SGreg Kurz smc->smp_threads_vsmt = true; 444553018216SPaolo Bonzini } 444653018216SPaolo Bonzini 444729ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = { 444829ee3247SAlexey Kardashevskiy .name = TYPE_SPAPR_MACHINE, 444929ee3247SAlexey Kardashevskiy .parent = TYPE_MACHINE, 44504aee7362SDavid Gibson .abstract = true, 4451ce2918cbSDavid Gibson .instance_size = sizeof(SpaprMachineState), 4452bcb5ce08SDavid Gibson .instance_init = spapr_instance_init, 445387bbdd9cSDavid Gibson .instance_finalize = spapr_machine_finalizefn, 4454ce2918cbSDavid Gibson .class_size = sizeof(SpaprMachineClass), 445529ee3247SAlexey Kardashevskiy .class_init = spapr_machine_class_init, 445671461b0fSAlexey Kardashevskiy .interfaces = (InterfaceInfo[]) { 445771461b0fSAlexey Kardashevskiy { TYPE_FW_PATH_PROVIDER }, 445834316482SAlexey Kardashevskiy { TYPE_NMI }, 4459c20d332aSBharata B Rao { TYPE_HOTPLUG_HANDLER }, 44601d1be34dSDavid Gibson { TYPE_PPC_VIRTUAL_HYPERVISOR }, 44617844e12bSCédric Le Goater { TYPE_XICS_FABRIC }, 44626449da45SCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 446371461b0fSAlexey Kardashevskiy { } 446471461b0fSAlexey Kardashevskiy }, 446529ee3247SAlexey Kardashevskiy }; 446629ee3247SAlexey Kardashevskiy 4467fccbc785SDavid Gibson #define DEFINE_SPAPR_MACHINE(suffix, verstr, latest) \ 44685013c547SDavid Gibson static void spapr_machine_##suffix##_class_init(ObjectClass *oc, \ 44695013c547SDavid Gibson void *data) \ 44705013c547SDavid Gibson { \ 44715013c547SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); \ 44725013c547SDavid Gibson spapr_machine_##suffix##_class_options(mc); \ 4473fccbc785SDavid Gibson if (latest) { \ 4474fccbc785SDavid Gibson mc->alias = "pseries"; \ 4475fccbc785SDavid Gibson mc->is_default = 1; \ 4476fccbc785SDavid Gibson } \ 44775013c547SDavid Gibson } \ 44785013c547SDavid Gibson static const TypeInfo spapr_machine_##suffix##_info = { \ 44795013c547SDavid Gibson .name = MACHINE_TYPE_NAME("pseries-" verstr), \ 44805013c547SDavid Gibson .parent = TYPE_SPAPR_MACHINE, \ 44815013c547SDavid Gibson .class_init = spapr_machine_##suffix##_class_init, \ 44825013c547SDavid Gibson }; \ 44835013c547SDavid Gibson static void spapr_machine_register_##suffix(void) \ 44845013c547SDavid Gibson { \ 44855013c547SDavid Gibson type_register(&spapr_machine_##suffix##_info); \ 44865013c547SDavid Gibson } \ 44870e6aac87SEduardo Habkost type_init(spapr_machine_register_##suffix) 44885013c547SDavid Gibson 44891c5f29bbSDavid Gibson /* 44909aec2e52SCornelia Huck * pseries-4.2 4491e2676b16SGreg Kurz */ 44929aec2e52SCornelia Huck static void spapr_machine_4_2_class_options(MachineClass *mc) 4493e2676b16SGreg Kurz { 4494e2676b16SGreg Kurz /* Defaults for the latest behaviour inherited from the base class */ 4495e2676b16SGreg Kurz } 4496e2676b16SGreg Kurz 44979aec2e52SCornelia Huck DEFINE_SPAPR_MACHINE(4_2, "4.2", true); 44989aec2e52SCornelia Huck 44999aec2e52SCornelia Huck /* 45009aec2e52SCornelia Huck * pseries-4.1 45019aec2e52SCornelia Huck */ 45029aec2e52SCornelia Huck static void spapr_machine_4_1_class_options(MachineClass *mc) 45039aec2e52SCornelia Huck { 45046c3829a2SAlexey Kardashevskiy SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4505d15d4ad6SDavid Gibson static GlobalProperty compat[] = { 4506d15d4ad6SDavid Gibson /* Only allow 4kiB and 64kiB IOMMU pagesizes */ 4507d15d4ad6SDavid Gibson { TYPE_SPAPR_PCI_HOST_BRIDGE, "pgsz", "0x11000" }, 4508d15d4ad6SDavid Gibson }; 4509d15d4ad6SDavid Gibson 45109aec2e52SCornelia Huck spapr_machine_4_2_class_options(mc); 45116c3829a2SAlexey Kardashevskiy smc->linux_pci_probe = false; 4512*29cb4187SGreg Kurz smc->smp_threads_vsmt = false; 45139aec2e52SCornelia Huck compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len); 4514d15d4ad6SDavid Gibson compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 45159aec2e52SCornelia Huck } 45169aec2e52SCornelia Huck 45179aec2e52SCornelia Huck DEFINE_SPAPR_MACHINE(4_1, "4.1", false); 45189bf2650bSCornelia Huck 45199bf2650bSCornelia Huck /* 45209bf2650bSCornelia Huck * pseries-4.0 45219bf2650bSCornelia Huck */ 4522eb3cba82SDavid Gibson static void phb_placement_4_0(SpaprMachineState *spapr, uint32_t index, 4523ec132efaSAlexey Kardashevskiy uint64_t *buid, hwaddr *pio, 4524ec132efaSAlexey Kardashevskiy hwaddr *mmio32, hwaddr *mmio64, 4525ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4526ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 4527ec132efaSAlexey Kardashevskiy { 4528ec132efaSAlexey Kardashevskiy spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma, liobns, 4529ec132efaSAlexey Kardashevskiy nv2gpa, nv2atsd, errp); 4530ec132efaSAlexey Kardashevskiy *nv2gpa = 0; 4531ec132efaSAlexey Kardashevskiy *nv2atsd = 0; 4532ec132efaSAlexey Kardashevskiy } 4533ec132efaSAlexey Kardashevskiy 4534eb3cba82SDavid Gibson static void spapr_machine_4_0_class_options(MachineClass *mc) 4535eb3cba82SDavid Gibson { 4536eb3cba82SDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4537eb3cba82SDavid Gibson 4538eb3cba82SDavid Gibson spapr_machine_4_1_class_options(mc); 4539eb3cba82SDavid Gibson compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); 4540eb3cba82SDavid Gibson smc->phb_placement = phb_placement_4_0; 4541bd94bc06SCédric Le Goater smc->irq = &spapr_irq_xics; 45423725ef1aSGreg Kurz smc->pre_4_1_migration = true; 4543eb3cba82SDavid Gibson } 4544eb3cba82SDavid Gibson 4545eb3cba82SDavid Gibson DEFINE_SPAPR_MACHINE(4_0, "4.0", false); 4546eb3cba82SDavid Gibson 4547eb3cba82SDavid Gibson /* 4548eb3cba82SDavid Gibson * pseries-3.1 4549eb3cba82SDavid Gibson */ 455088cbe073SMarc-André Lureau static void spapr_machine_3_1_class_options(MachineClass *mc) 455188cbe073SMarc-André Lureau { 4552ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4553fea35ca4SAlexey Kardashevskiy 455484e060bfSAlex Williamson spapr_machine_4_0_class_options(mc); 4555abd93cc7SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len); 455627461d69SPrasad J Pandit 455734a6b015SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 4558fea35ca4SAlexey Kardashevskiy smc->update_dt_enabled = false; 4559dae5e39aSMichael Roth smc->dr_phb_enabled = false; 45600a794529SDavid Gibson smc->broken_host_serial_model = true; 45612782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN; 45622782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN; 45632782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN; 4564edaa7995SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF; 456584e060bfSAlex Williamson } 456684e060bfSAlex Williamson 456784e060bfSAlex Williamson DEFINE_SPAPR_MACHINE(3_1, "3.1", false); 4568d45360d9SCédric Le Goater 4569d45360d9SCédric Le Goater /* 4570d45360d9SCédric Le Goater * pseries-3.0 4571d45360d9SCédric Le Goater */ 4572d45360d9SCédric Le Goater 4573d45360d9SCédric Le Goater static void spapr_machine_3_0_class_options(MachineClass *mc) 4574d45360d9SCédric Le Goater { 4575ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 457682cffa2eSCédric Le Goater 4577d45360d9SCédric Le Goater spapr_machine_3_1_class_options(mc); 4578ddb3235dSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len); 457982cffa2eSCédric Le Goater 458082cffa2eSCédric Le Goater smc->legacy_irq_allocation = true; 4581ae837402SCédric Le Goater smc->irq = &spapr_irq_xics_legacy; 4582d45360d9SCédric Le Goater } 4583d45360d9SCédric Le Goater 4584d45360d9SCédric Le Goater DEFINE_SPAPR_MACHINE(3_0, "3.0", false); 45858a4fd427SDavid Gibson 45868a4fd427SDavid Gibson /* 45878a4fd427SDavid Gibson * pseries-2.12 45888a4fd427SDavid Gibson */ 458988cbe073SMarc-André Lureau static void spapr_machine_2_12_class_options(MachineClass *mc) 459088cbe073SMarc-André Lureau { 4591ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 459288cbe073SMarc-André Lureau static GlobalProperty compat[] = { 45936c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-3.0-migration", "on" }, 45946c36bddfSEduardo Habkost { TYPE_SPAPR_CPU_CORE, "pre-3.0-migration", "on" }, 4595fa386d98SMarc-André Lureau }; 45968a4fd427SDavid Gibson 4597d8c0c7afSPeter Maydell spapr_machine_3_0_class_options(mc); 45980d47310bSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_12, hw_compat_2_12_len); 459988cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 46002309832aSDavid Gibson 4601e8937295SGreg Kurz /* We depend on kvm_enabled() to choose a default value for the 4602e8937295SGreg Kurz * hpt-max-page-size capability. Of course we can't do it here 4603e8937295SGreg Kurz * because this is too early and the HW accelerator isn't initialzed 4604e8937295SGreg Kurz * yet. Postpone this to machine init (see default_caps_with_cpu()). 4605e8937295SGreg Kurz */ 4606e8937295SGreg Kurz smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 0; 46078a4fd427SDavid Gibson } 46088a4fd427SDavid Gibson 46098a4fd427SDavid Gibson DEFINE_SPAPR_MACHINE(2_12, "2.12", false); 46102b615412SDavid Gibson 4611813f3cf6SSuraj Jitindar Singh static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc) 4612813f3cf6SSuraj Jitindar Singh { 4613ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4614813f3cf6SSuraj Jitindar Singh 4615813f3cf6SSuraj Jitindar Singh spapr_machine_2_12_class_options(mc); 4616813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND; 4617813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND; 4618813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_FIXED_CCD; 4619813f3cf6SSuraj Jitindar Singh } 4620813f3cf6SSuraj Jitindar Singh 4621813f3cf6SSuraj Jitindar Singh DEFINE_SPAPR_MACHINE(2_12_sxxm, "2.12-sxxm", false); 4622813f3cf6SSuraj Jitindar Singh 46232b615412SDavid Gibson /* 46242b615412SDavid Gibson * pseries-2.11 46252b615412SDavid Gibson */ 46262b615412SDavid Gibson 46272b615412SDavid Gibson static void spapr_machine_2_11_class_options(MachineClass *mc) 46282b615412SDavid Gibson { 4629ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4630ee76a09fSDavid Gibson 46312b615412SDavid Gibson spapr_machine_2_12_class_options(mc); 46324e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON; 463343df70a9SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len); 46342b615412SDavid Gibson } 46352b615412SDavid Gibson 46362b615412SDavid Gibson DEFINE_SPAPR_MACHINE(2_11, "2.11", false); 4637e2676b16SGreg Kurz 4638e2676b16SGreg Kurz /* 46393fa14fbeSDavid Gibson * pseries-2.10 4640db800b21SDavid Gibson */ 4641e2676b16SGreg Kurz 46423fa14fbeSDavid Gibson static void spapr_machine_2_10_class_options(MachineClass *mc) 4643db800b21SDavid Gibson { 4644e2676b16SGreg Kurz spapr_machine_2_11_class_options(mc); 4645503224f4SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_10, hw_compat_2_10_len); 4646db800b21SDavid Gibson } 4647db800b21SDavid Gibson 4648e2676b16SGreg Kurz DEFINE_SPAPR_MACHINE(2_10, "2.10", false); 46493fa14fbeSDavid Gibson 46503fa14fbeSDavid Gibson /* 46513fa14fbeSDavid Gibson * pseries-2.9 46523fa14fbeSDavid Gibson */ 465388cbe073SMarc-André Lureau 465488cbe073SMarc-André Lureau static void spapr_machine_2_9_class_options(MachineClass *mc) 465588cbe073SMarc-André Lureau { 4656ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 465788cbe073SMarc-André Lureau static GlobalProperty compat[] = { 46586c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-2.10-migration", "on" }, 4659fa386d98SMarc-André Lureau }; 46603fa14fbeSDavid Gibson 46613fa14fbeSDavid Gibson spapr_machine_2_10_class_options(mc); 46623e803152SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len); 466388cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 46643bfe5716SLaurent Vivier mc->numa_auto_assign_ram = numa_legacy_auto_assign_ram; 466546f7afa3SGreg Kurz smc->pre_2_10_has_unused_icps = true; 466652b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED; 46673fa14fbeSDavid Gibson } 46683fa14fbeSDavid Gibson 46693fa14fbeSDavid Gibson DEFINE_SPAPR_MACHINE(2_9, "2.9", false); 4670fa325e6cSDavid Gibson 4671fa325e6cSDavid Gibson /* 4672fa325e6cSDavid Gibson * pseries-2.8 4673fa325e6cSDavid Gibson */ 467488cbe073SMarc-André Lureau 467588cbe073SMarc-André Lureau static void spapr_machine_2_8_class_options(MachineClass *mc) 467688cbe073SMarc-André Lureau { 467788cbe073SMarc-André Lureau static GlobalProperty compat[] = { 46786c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "pcie-extended-configuration-space", "off" }, 4679fa386d98SMarc-André Lureau }; 4680fa325e6cSDavid Gibson 4681fa325e6cSDavid Gibson spapr_machine_2_9_class_options(mc); 4682edc24ccdSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len); 468388cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 468455641213SLaurent Vivier mc->numa_mem_align_shift = 23; 4685fa325e6cSDavid Gibson } 4686fa325e6cSDavid Gibson 4687fa325e6cSDavid Gibson DEFINE_SPAPR_MACHINE(2_8, "2.8", false); 4688db800b21SDavid Gibson 4689db800b21SDavid Gibson /* 46901ea1eefcSBharata B Rao * pseries-2.7 46911ea1eefcSBharata B Rao */ 4692357d1e3bSDavid Gibson 4693ce2918cbSDavid Gibson static void phb_placement_2_7(SpaprMachineState *spapr, uint32_t index, 4694357d1e3bSDavid Gibson uint64_t *buid, hwaddr *pio, 4695357d1e3bSDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 4696ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4697ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 4698357d1e3bSDavid Gibson { 4699357d1e3bSDavid Gibson /* Legacy PHB placement for pseries-2.7 and earlier machine types */ 4700357d1e3bSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 4701357d1e3bSDavid Gibson const hwaddr phb_spacing = 0x1000000000ULL; /* 64 GiB */ 4702357d1e3bSDavid Gibson const hwaddr mmio_offset = 0xa0000000; /* 2 GiB + 512 MiB */ 4703357d1e3bSDavid Gibson const hwaddr pio_offset = 0x80000000; /* 2 GiB */ 4704357d1e3bSDavid Gibson const uint32_t max_index = 255; 4705357d1e3bSDavid Gibson const hwaddr phb0_alignment = 0x10000000000ULL; /* 1 TiB */ 4706357d1e3bSDavid Gibson 4707357d1e3bSDavid Gibson uint64_t ram_top = MACHINE(spapr)->ram_size; 4708357d1e3bSDavid Gibson hwaddr phb0_base, phb_base; 4709357d1e3bSDavid Gibson int i; 4710357d1e3bSDavid Gibson 47110c9269a5SDavid Hildenbrand /* Do we have device memory? */ 4712357d1e3bSDavid Gibson if (MACHINE(spapr)->maxram_size > ram_top) { 4713357d1e3bSDavid Gibson /* Can't just use maxram_size, because there may be an 47140c9269a5SDavid Hildenbrand * alignment gap between normal and device memory regions 47150c9269a5SDavid Hildenbrand */ 4716b0c14ec4SDavid Hildenbrand ram_top = MACHINE(spapr)->device_memory->base + 4717b0c14ec4SDavid Hildenbrand memory_region_size(&MACHINE(spapr)->device_memory->mr); 4718357d1e3bSDavid Gibson } 4719357d1e3bSDavid Gibson 4720357d1e3bSDavid Gibson phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment); 4721357d1e3bSDavid Gibson 4722357d1e3bSDavid Gibson if (index > max_index) { 4723357d1e3bSDavid Gibson error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", 4724357d1e3bSDavid Gibson max_index); 4725357d1e3bSDavid Gibson return; 4726357d1e3bSDavid Gibson } 4727357d1e3bSDavid Gibson 4728357d1e3bSDavid Gibson *buid = base_buid + index; 4729357d1e3bSDavid Gibson for (i = 0; i < n_dma; ++i) { 4730357d1e3bSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 4731357d1e3bSDavid Gibson } 4732357d1e3bSDavid Gibson 4733357d1e3bSDavid Gibson phb_base = phb0_base + index * phb_spacing; 4734357d1e3bSDavid Gibson *pio = phb_base + pio_offset; 4735357d1e3bSDavid Gibson *mmio32 = phb_base + mmio_offset; 4736357d1e3bSDavid Gibson /* 4737357d1e3bSDavid Gibson * We don't set the 64-bit MMIO window, relying on the PHB's 4738357d1e3bSDavid Gibson * fallback behaviour of automatically splitting a large "32-bit" 4739357d1e3bSDavid Gibson * window into contiguous 32-bit and 64-bit windows 4740357d1e3bSDavid Gibson */ 4741ec132efaSAlexey Kardashevskiy 4742ec132efaSAlexey Kardashevskiy *nv2gpa = 0; 4743ec132efaSAlexey Kardashevskiy *nv2atsd = 0; 4744357d1e3bSDavid Gibson } 4745db800b21SDavid Gibson 47461ea1eefcSBharata B Rao static void spapr_machine_2_7_class_options(MachineClass *mc) 47471ea1eefcSBharata B Rao { 4748ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 474988cbe073SMarc-André Lureau static GlobalProperty compat[] = { 47506c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0xf80000000", }, 47516c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem64_win_size", "0", }, 47526c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-2.8-migration", "on", }, 47536c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-2.8-migration", "on", }, 475488cbe073SMarc-André Lureau }; 47553daa4a9fSThomas Huth 4756db800b21SDavid Gibson spapr_machine_2_8_class_options(mc); 47572e9c10ebSIgor Mammedov mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power7_v2.3"); 4758a140c199SEduardo Habkost mc->default_machine_opts = "modern-hotplug-events=off"; 47595a995064SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_7, hw_compat_2_7_len); 476088cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 4761357d1e3bSDavid Gibson smc->phb_placement = phb_placement_2_7; 47621ea1eefcSBharata B Rao } 47631ea1eefcSBharata B Rao 4764db800b21SDavid Gibson DEFINE_SPAPR_MACHINE(2_7, "2.7", false); 47651ea1eefcSBharata B Rao 47661ea1eefcSBharata B Rao /* 47674b23699cSDavid Gibson * pseries-2.6 47684b23699cSDavid Gibson */ 476988cbe073SMarc-André Lureau 477088cbe073SMarc-André Lureau static void spapr_machine_2_6_class_options(MachineClass *mc) 477188cbe073SMarc-André Lureau { 477288cbe073SMarc-André Lureau static GlobalProperty compat[] = { 47736c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "ddw", "off" }, 4774fa386d98SMarc-André Lureau }; 47751ea1eefcSBharata B Rao 47761ea1eefcSBharata B Rao spapr_machine_2_7_class_options(mc); 4777c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = false; 4778ff8f261fSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_6, hw_compat_2_6_len); 477988cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 47804b23699cSDavid Gibson } 47814b23699cSDavid Gibson 47821ea1eefcSBharata B Rao DEFINE_SPAPR_MACHINE(2_6, "2.6", false); 47834b23699cSDavid Gibson 47844b23699cSDavid Gibson /* 47851c5f29bbSDavid Gibson * pseries-2.5 47861c5f29bbSDavid Gibson */ 478788cbe073SMarc-André Lureau 478888cbe073SMarc-André Lureau static void spapr_machine_2_5_class_options(MachineClass *mc) 478988cbe073SMarc-André Lureau { 4790ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 479188cbe073SMarc-André Lureau static GlobalProperty compat[] = { 47926c36bddfSEduardo Habkost { "spapr-vlan", "use-rx-buffer-pools", "off" }, 4793fa386d98SMarc-André Lureau }; 47944b23699cSDavid Gibson 47954b23699cSDavid Gibson spapr_machine_2_6_class_options(mc); 479657040d45SThomas Huth smc->use_ohci_by_default = true; 4797fe759610SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_5, hw_compat_2_5_len); 479888cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 47991c5f29bbSDavid Gibson } 48001c5f29bbSDavid Gibson 48014b23699cSDavid Gibson DEFINE_SPAPR_MACHINE(2_5, "2.5", false); 48021c5f29bbSDavid Gibson 48031c5f29bbSDavid Gibson /* 48041c5f29bbSDavid Gibson * pseries-2.4 48051c5f29bbSDavid Gibson */ 480680fd50f9SCornelia Huck 48075013c547SDavid Gibson static void spapr_machine_2_4_class_options(MachineClass *mc) 48085013c547SDavid Gibson { 4809ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4810fc9f38c3SDavid Gibson 4811fc9f38c3SDavid Gibson spapr_machine_2_5_class_options(mc); 4812fc9f38c3SDavid Gibson smc->dr_lmb_enabled = false; 48132f99b9c2SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_4, hw_compat_2_4_len); 48141c5f29bbSDavid Gibson } 48151c5f29bbSDavid Gibson 4816fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_4, "2.4", false); 48171c5f29bbSDavid Gibson 48181c5f29bbSDavid Gibson /* 48191c5f29bbSDavid Gibson * pseries-2.3 48201c5f29bbSDavid Gibson */ 482188cbe073SMarc-André Lureau 482288cbe073SMarc-André Lureau static void spapr_machine_2_3_class_options(MachineClass *mc) 482388cbe073SMarc-André Lureau { 482488cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48256c36bddfSEduardo Habkost { "spapr-pci-host-bridge", "dynamic-reconfiguration", "off" }, 4826fa386d98SMarc-André Lureau }; 4827fc9f38c3SDavid Gibson spapr_machine_2_4_class_options(mc); 48288995dd90SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_3, hw_compat_2_3_len); 482988cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 48301c5f29bbSDavid Gibson } 4831fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_3, "2.3", false); 48321c5f29bbSDavid Gibson 48331c5f29bbSDavid Gibson /* 48341c5f29bbSDavid Gibson * pseries-2.2 48351c5f29bbSDavid Gibson */ 483688cbe073SMarc-André Lureau 483788cbe073SMarc-André Lureau static void spapr_machine_2_2_class_options(MachineClass *mc) 483888cbe073SMarc-André Lureau { 483988cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48406c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0x20000000" }, 4841fa386d98SMarc-André Lureau }; 4842b194df47SAlexey Kardashevskiy 4843fc9f38c3SDavid Gibson spapr_machine_2_3_class_options(mc); 48441c30044eSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_2, hw_compat_2_2_len); 484588cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 4846f6d0656bSEduardo Habkost mc->default_machine_opts = "modern-hotplug-events=off,suppress-vmdesc=on"; 48471c5f29bbSDavid Gibson } 4848fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_2, "2.2", false); 48491c5f29bbSDavid Gibson 48501c5f29bbSDavid Gibson /* 48511c5f29bbSDavid Gibson * pseries-2.1 48521c5f29bbSDavid Gibson */ 48531c5f29bbSDavid Gibson 48545013c547SDavid Gibson static void spapr_machine_2_1_class_options(MachineClass *mc) 4855b0e966d0SJason Wang { 4856fc9f38c3SDavid Gibson spapr_machine_2_2_class_options(mc); 4857c4fc5695SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_1, hw_compat_2_1_len); 48586026db45SAlexey Kardashevskiy } 4859fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_1, "2.1", false); 48606026db45SAlexey Kardashevskiy 486129ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void) 486229ee3247SAlexey Kardashevskiy { 486329ee3247SAlexey Kardashevskiy type_register_static(&spapr_machine_info); 486429ee3247SAlexey Kardashevskiy } 486529ee3247SAlexey Kardashevskiy 486629ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types) 4867