153018216SPaolo Bonzini /* 253018216SPaolo Bonzini * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator 353018216SPaolo Bonzini * 453018216SPaolo Bonzini * Copyright (c) 2004-2007 Fabrice Bellard 553018216SPaolo Bonzini * Copyright (c) 2007 Jocelyn Mayer 653018216SPaolo Bonzini * Copyright (c) 2010 David Gibson, IBM Corporation. 753018216SPaolo Bonzini * 853018216SPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy 953018216SPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal 1053018216SPaolo Bonzini * in the Software without restriction, including without limitation the rights 1153018216SPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1253018216SPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is 1353018216SPaolo Bonzini * furnished to do so, subject to the following conditions: 1453018216SPaolo Bonzini * 1553018216SPaolo Bonzini * The above copyright notice and this permission notice shall be included in 1653018216SPaolo Bonzini * all copies or substantial portions of the Software. 1753018216SPaolo Bonzini * 1853018216SPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1953018216SPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2053018216SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2153018216SPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2253018216SPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2353018216SPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 2453018216SPaolo Bonzini * THE SOFTWARE. 2553018216SPaolo Bonzini */ 26a8d25326SMarkus Armbruster 270d75590dSPeter Maydell #include "qemu/osdep.h" 28a8d25326SMarkus Armbruster #include "qemu-common.h" 29da34e65cSMarkus Armbruster #include "qapi/error.h" 30fa98fbfcSSam Bobroff #include "qapi/visitor.h" 3153018216SPaolo Bonzini #include "sysemu/sysemu.h" 32b58c5c2dSMarkus Armbruster #include "sysemu/hostmem.h" 33e35704baSEduardo Habkost #include "sysemu/numa.h" 3423ff81bdSGreg Kurz #include "sysemu/qtest.h" 3571e8a915SMarkus Armbruster #include "sysemu/reset.h" 3654d31236SMarkus Armbruster #include "sysemu/runstate.h" 3703dd024fSPaolo Bonzini #include "qemu/log.h" 3871461b0fSAlexey Kardashevskiy #include "hw/fw-path-provider.h" 3953018216SPaolo Bonzini #include "elf.h" 4053018216SPaolo Bonzini #include "net/net.h" 41ad440b4aSAndrew Jones #include "sysemu/device_tree.h" 4253018216SPaolo Bonzini #include "sysemu/cpus.h" 43b3946626SVincent Palatin #include "sysemu/hw_accel.h" 4453018216SPaolo Bonzini #include "kvm_ppc.h" 45c4b63b7cSJuan Quintela #include "migration/misc.h" 46ca77ee28SMarkus Armbruster #include "migration/qemu-file-types.h" 4784a899deSJuan Quintela #include "migration/global_state.h" 48f2a8f0a6SJuan Quintela #include "migration/register.h" 492500fb42SAravinda Prasad #include "migration/blocker.h" 504be21d56SDavid Gibson #include "mmu-hash64.h" 51b4db5413SSuraj Jitindar Singh #include "mmu-book3s-v3.h" 527abd43baSSuraj Jitindar Singh #include "cpu-models.h" 532e5b09fdSMarkus Armbruster #include "hw/core/cpu.h" 5453018216SPaolo Bonzini 5553018216SPaolo Bonzini #include "hw/boards.h" 560d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h" 5753018216SPaolo Bonzini #include "hw/loader.h" 5853018216SPaolo Bonzini 597804c353SCédric Le Goater #include "hw/ppc/fdt.h" 600d09e41aSPaolo Bonzini #include "hw/ppc/spapr.h" 610d09e41aSPaolo Bonzini #include "hw/ppc/spapr_vio.h" 62a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 630d09e41aSPaolo Bonzini #include "hw/pci-host/spapr.h" 6453018216SPaolo Bonzini #include "hw/pci/msi.h" 6553018216SPaolo Bonzini 6653018216SPaolo Bonzini #include "hw/pci/pci.h" 6771461b0fSAlexey Kardashevskiy #include "hw/scsi/scsi.h" 6871461b0fSAlexey Kardashevskiy #include "hw/virtio/virtio-scsi.h" 69c4e13492SFelipe Franciosi #include "hw/virtio/vhost-scsi-common.h" 7053018216SPaolo Bonzini 7153018216SPaolo Bonzini #include "exec/address-spaces.h" 722309832aSDavid Gibson #include "exec/ram_addr.h" 7353018216SPaolo Bonzini #include "hw/usb.h" 7453018216SPaolo Bonzini #include "qemu/config-file.h" 75135a129aSAneesh Kumar K.V #include "qemu/error-report.h" 762a6593cbSAlexey Kardashevskiy #include "trace.h" 7734316482SAlexey Kardashevskiy #include "hw/nmi.h" 786449da45SCédric Le Goater #include "hw/intc/intc.h" 7953018216SPaolo Bonzini 8094a94e4cSBharata B Rao #include "hw/ppc/spapr_cpu_core.h" 812cc0e2e8SDavid Hildenbrand #include "hw/mem/memory-device.h" 820fb6bd07SMichael Roth #include "hw/ppc/spapr_tpm_proxy.h" 83ee3a71e3SShivaprasad G Bhat #include "hw/ppc/spapr_nvdimm.h" 841eee9950SDaniel Henrique Barboza #include "hw/ppc/spapr_numa.h" 8568a27b20SMichael S. Tsirkin 86f041d6afSGreg Kurz #include "monitor/monitor.h" 87f041d6afSGreg Kurz 8853018216SPaolo Bonzini #include <libfdt.h> 8953018216SPaolo Bonzini 9053018216SPaolo Bonzini /* SLOF memory layout: 9153018216SPaolo Bonzini * 9253018216SPaolo Bonzini * SLOF raw image loaded at 0, copies its romfs right below the flat 9353018216SPaolo Bonzini * device-tree, then position SLOF itself 31M below that 9453018216SPaolo Bonzini * 9553018216SPaolo Bonzini * So we set FW_OVERHEAD to 40MB which should account for all of that 9653018216SPaolo Bonzini * and more 9753018216SPaolo Bonzini * 9853018216SPaolo Bonzini * We load our kernel at 4M, leaving space for SLOF initial image 9953018216SPaolo Bonzini */ 100b7d1f77aSBenjamin Herrenschmidt #define RTAS_MAX_ADDR 0x80000000 /* RTAS must stay below that */ 10153018216SPaolo Bonzini #define FW_MAX_SIZE 0x400000 10253018216SPaolo Bonzini #define FW_FILE_NAME "slof.bin" 10353018216SPaolo Bonzini #define FW_OVERHEAD 0x2800000 10453018216SPaolo Bonzini #define KERNEL_LOAD_ADDR FW_MAX_SIZE 10553018216SPaolo Bonzini 1069943266eSDavid Gibson #define MIN_RMA_SLOF (128 * MiB) 10753018216SPaolo Bonzini 1085c7adcf4SGreg Kurz #define PHANDLE_INTC 0x00001111 10953018216SPaolo Bonzini 1105d0fb150SGreg Kurz /* These two functions implement the VCPU id numbering: one to compute them 1115d0fb150SGreg Kurz * all and one to identify thread 0 of a VCORE. Any change to the first one 1125d0fb150SGreg Kurz * is likely to have an impact on the second one, so let's keep them close. 1135d0fb150SGreg Kurz */ 114ce2918cbSDavid Gibson static int spapr_vcpu_id(SpaprMachineState *spapr, int cpu_index) 1155d0fb150SGreg Kurz { 116fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 117fe6b6346SLike Xu unsigned int smp_threads = ms->smp.threads; 118fe6b6346SLike Xu 1191a5008fcSGreg Kurz assert(spapr->vsmt); 1205d0fb150SGreg Kurz return 1215d0fb150SGreg Kurz (cpu_index / smp_threads) * spapr->vsmt + cpu_index % smp_threads; 1225d0fb150SGreg Kurz } 123ce2918cbSDavid Gibson static bool spapr_is_thread0_in_vcore(SpaprMachineState *spapr, 1245d0fb150SGreg Kurz PowerPCCPU *cpu) 1255d0fb150SGreg Kurz { 1261a5008fcSGreg Kurz assert(spapr->vsmt); 1275d0fb150SGreg Kurz return spapr_get_vcpu_id(cpu) % spapr->vsmt == 0; 1285d0fb150SGreg Kurz } 1295d0fb150SGreg Kurz 13046f7afa3SGreg Kurz static bool pre_2_10_vmstate_dummy_icp_needed(void *opaque) 13146f7afa3SGreg Kurz { 13246f7afa3SGreg Kurz /* Dummy entries correspond to unused ICPState objects in older QEMUs, 13346f7afa3SGreg Kurz * and newer QEMUs don't even have them. In both cases, we don't want 13446f7afa3SGreg Kurz * to send anything on the wire. 13546f7afa3SGreg Kurz */ 13646f7afa3SGreg Kurz return false; 13746f7afa3SGreg Kurz } 13846f7afa3SGreg Kurz 13946f7afa3SGreg Kurz static const VMStateDescription pre_2_10_vmstate_dummy_icp = { 14046f7afa3SGreg Kurz .name = "icp/server", 14146f7afa3SGreg Kurz .version_id = 1, 14246f7afa3SGreg Kurz .minimum_version_id = 1, 14346f7afa3SGreg Kurz .needed = pre_2_10_vmstate_dummy_icp_needed, 14446f7afa3SGreg Kurz .fields = (VMStateField[]) { 14546f7afa3SGreg Kurz VMSTATE_UNUSED(4), /* uint32_t xirr */ 14646f7afa3SGreg Kurz VMSTATE_UNUSED(1), /* uint8_t pending_priority */ 14746f7afa3SGreg Kurz VMSTATE_UNUSED(1), /* uint8_t mfrr */ 14846f7afa3SGreg Kurz VMSTATE_END_OF_LIST() 14946f7afa3SGreg Kurz }, 15046f7afa3SGreg Kurz }; 15146f7afa3SGreg Kurz 15246f7afa3SGreg Kurz static void pre_2_10_vmstate_register_dummy_icp(int i) 15346f7afa3SGreg Kurz { 15446f7afa3SGreg Kurz vmstate_register(NULL, i, &pre_2_10_vmstate_dummy_icp, 15546f7afa3SGreg Kurz (void *)(uintptr_t) i); 15646f7afa3SGreg Kurz } 15746f7afa3SGreg Kurz 15846f7afa3SGreg Kurz static void pre_2_10_vmstate_unregister_dummy_icp(int i) 15946f7afa3SGreg Kurz { 16046f7afa3SGreg Kurz vmstate_unregister(NULL, &pre_2_10_vmstate_dummy_icp, 16146f7afa3SGreg Kurz (void *)(uintptr_t) i); 16246f7afa3SGreg Kurz } 16346f7afa3SGreg Kurz 164ce2918cbSDavid Gibson int spapr_max_server_number(SpaprMachineState *spapr) 16546f7afa3SGreg Kurz { 166fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 167fe6b6346SLike Xu 1681a5008fcSGreg Kurz assert(spapr->vsmt); 169fe6b6346SLike Xu return DIV_ROUND_UP(ms->smp.max_cpus * spapr->vsmt, ms->smp.threads); 17046f7afa3SGreg Kurz } 17146f7afa3SGreg Kurz 172833d4668SAlexey Kardashevskiy static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, 173833d4668SAlexey Kardashevskiy int smt_threads) 174833d4668SAlexey Kardashevskiy { 175833d4668SAlexey Kardashevskiy int i, ret = 0; 176833d4668SAlexey Kardashevskiy uint32_t servers_prop[smt_threads]; 177833d4668SAlexey Kardashevskiy uint32_t gservers_prop[smt_threads * 2]; 17814bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 179833d4668SAlexey Kardashevskiy 180d6e166c0SDavid Gibson if (cpu->compat_pvr) { 181d6e166c0SDavid Gibson ret = fdt_setprop_cell(fdt, offset, "cpu-version", cpu->compat_pvr); 1826d9412eaSAlexey Kardashevskiy if (ret < 0) { 1836d9412eaSAlexey Kardashevskiy return ret; 1846d9412eaSAlexey Kardashevskiy } 1856d9412eaSAlexey Kardashevskiy } 1866d9412eaSAlexey Kardashevskiy 187833d4668SAlexey Kardashevskiy /* Build interrupt servers and gservers properties */ 188833d4668SAlexey Kardashevskiy for (i = 0; i < smt_threads; i++) { 189833d4668SAlexey Kardashevskiy servers_prop[i] = cpu_to_be32(index + i); 190833d4668SAlexey Kardashevskiy /* Hack, direct the group queues back to cpu 0 */ 191833d4668SAlexey Kardashevskiy gservers_prop[i*2] = cpu_to_be32(index + i); 192833d4668SAlexey Kardashevskiy gservers_prop[i*2 + 1] = 0; 193833d4668SAlexey Kardashevskiy } 194833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 195833d4668SAlexey Kardashevskiy servers_prop, sizeof(servers_prop)); 196833d4668SAlexey Kardashevskiy if (ret < 0) { 197833d4668SAlexey Kardashevskiy return ret; 198833d4668SAlexey Kardashevskiy } 199833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-gserver#s", 200833d4668SAlexey Kardashevskiy gservers_prop, sizeof(gservers_prop)); 201833d4668SAlexey Kardashevskiy 202833d4668SAlexey Kardashevskiy return ret; 203833d4668SAlexey Kardashevskiy } 204833d4668SAlexey Kardashevskiy 20591335a5eSDavid Gibson static void spapr_dt_pa_features(SpaprMachineState *spapr, 206ee76a09fSDavid Gibson PowerPCCPU *cpu, 207daa36379SDavid Gibson void *fdt, int offset) 20886d5771aSSam Bobroff { 20986d5771aSSam Bobroff uint8_t pa_features_206[] = { 6, 0, 21086d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 }; 21186d5771aSSam Bobroff uint8_t pa_features_207[] = { 24, 0, 21286d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, 21386d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 21486d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 21586d5771aSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 }; 2169fb4541fSSam Bobroff uint8_t pa_features_300[] = { 66, 0, 2179fb4541fSSam Bobroff /* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */ 2189fb4541fSSam Bobroff /* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, SSO, 5: LE|CFAR|EB|LSQ */ 21986d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, /* 0 - 5 */ 2209fb4541fSSam Bobroff /* 6: DS207 */ 22186d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */ 2229fb4541fSSam Bobroff /* 16: Vector */ 22386d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */ 2249fb4541fSSam Bobroff /* 18: Vec. Scalar, 20: Vec. XOR, 22: HTM */ 2259bf502feSDavid Gibson 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */ 2269fb4541fSSam Bobroff /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */ 2279fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */ 2289fb4541fSSam Bobroff /* 30: MMR, 32: LE atomic, 34: EBB + ext EBB */ 2299fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */ 2309fb4541fSSam Bobroff /* 36: SPR SO, 38: Copy/Paste, 40: Radix MMU */ 2319fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 36 - 41 */ 2329fb4541fSSam Bobroff /* 42: PM, 44: PC RA, 46: SC vec'd */ 2339fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */ 2349fb4541fSSam Bobroff /* 48: SIMD, 50: QP BFP, 52: String */ 2359fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */ 2369fb4541fSSam Bobroff /* 54: DecFP, 56: DecI, 58: SHA */ 2379fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */ 2389fb4541fSSam Bobroff /* 60: NM atomic, 62: RNG */ 2399fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */ 2409fb4541fSSam Bobroff }; 2417abd43baSSuraj Jitindar Singh uint8_t *pa_features = NULL; 24286d5771aSSam Bobroff size_t pa_size; 24386d5771aSSam Bobroff 2447abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06, 0, cpu->compat_pvr)) { 24586d5771aSSam Bobroff pa_features = pa_features_206; 24686d5771aSSam Bobroff pa_size = sizeof(pa_features_206); 2477abd43baSSuraj Jitindar Singh } 2487abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07, 0, cpu->compat_pvr)) { 24986d5771aSSam Bobroff pa_features = pa_features_207; 25086d5771aSSam Bobroff pa_size = sizeof(pa_features_207); 2517abd43baSSuraj Jitindar Singh } 2527abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0, cpu->compat_pvr)) { 25386d5771aSSam Bobroff pa_features = pa_features_300; 25486d5771aSSam Bobroff pa_size = sizeof(pa_features_300); 2557abd43baSSuraj Jitindar Singh } 2567abd43baSSuraj Jitindar Singh if (!pa_features) { 25786d5771aSSam Bobroff return; 25886d5771aSSam Bobroff } 25986d5771aSSam Bobroff 26026cd35b8SDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_CI_LARGEPAGE)) { 26186d5771aSSam Bobroff /* 26286d5771aSSam Bobroff * Note: we keep CI large pages off by default because a 64K capable 26386d5771aSSam Bobroff * guest provisioned with large pages might otherwise try to map a qemu 26486d5771aSSam Bobroff * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages 26586d5771aSSam Bobroff * even if that qemu runs on a 4k host. 26686d5771aSSam Bobroff * We dd this bit back here if we are confident this is not an issue 26786d5771aSSam Bobroff */ 26886d5771aSSam Bobroff pa_features[3] |= 0x20; 26986d5771aSSam Bobroff } 2704e5fe368SSuraj Jitindar Singh if ((spapr_get_cap(spapr, SPAPR_CAP_HTM) != 0) && pa_size > 24) { 27186d5771aSSam Bobroff pa_features[24] |= 0x80; /* Transactional memory support */ 27286d5771aSSam Bobroff } 273daa36379SDavid Gibson if (spapr->cas_pre_isa3_guest && pa_size > 40) { 274e957f6a9SSam Bobroff /* Workaround for broken kernels that attempt (guest) radix 275e957f6a9SSam Bobroff * mode when they can't handle it, if they see the radix bit set 276e957f6a9SSam Bobroff * in pa-features. So hide it from them. */ 277e957f6a9SSam Bobroff pa_features[40 + 2] &= ~0x80; /* Radix MMU */ 278e957f6a9SSam Bobroff } 27986d5771aSSam Bobroff 28086d5771aSSam Bobroff _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size))); 28186d5771aSSam Bobroff } 28286d5771aSSam Bobroff 283c86c1affSDaniel Henrique Barboza static hwaddr spapr_node0_size(MachineState *machine) 284b082d65aSAlexey Kardashevskiy { 285aa570207STao Xu if (machine->numa_state->num_nodes) { 286b082d65aSAlexey Kardashevskiy int i; 287aa570207STao Xu for (i = 0; i < machine->numa_state->num_nodes; ++i) { 2887e721e7bSTao Xu if (machine->numa_state->nodes[i].node_mem) { 2897e721e7bSTao Xu return MIN(pow2floor(machine->numa_state->nodes[i].node_mem), 290fb164994SDavid Gibson machine->ram_size); 291b082d65aSAlexey Kardashevskiy } 292b082d65aSAlexey Kardashevskiy } 293b082d65aSAlexey Kardashevskiy } 294fb164994SDavid Gibson return machine->ram_size; 295b082d65aSAlexey Kardashevskiy } 296b082d65aSAlexey Kardashevskiy 29729bfe52aSDaniel Henrique Barboza bool spapr_machine_using_legacy_numa(SpaprMachineState *spapr) 29829bfe52aSDaniel Henrique Barboza { 29929bfe52aSDaniel Henrique Barboza MachineState *machine = MACHINE(spapr); 30029bfe52aSDaniel Henrique Barboza SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 30129bfe52aSDaniel Henrique Barboza 30229bfe52aSDaniel Henrique Barboza return smc->pre_5_2_numa_associativity || 30329bfe52aSDaniel Henrique Barboza machine->numa_state->num_nodes <= 1; 30429bfe52aSDaniel Henrique Barboza } 30529bfe52aSDaniel Henrique Barboza 306a1d59c0fSAlexey Kardashevskiy static void add_str(GString *s, const gchar *s1) 307a1d59c0fSAlexey Kardashevskiy { 308a1d59c0fSAlexey Kardashevskiy g_string_append_len(s, s1, strlen(s1) + 1); 309a1d59c0fSAlexey Kardashevskiy } 31053018216SPaolo Bonzini 311f1aa45ffSDaniel Henrique Barboza static int spapr_dt_memory_node(SpaprMachineState *spapr, void *fdt, int nodeid, 312f1aa45ffSDaniel Henrique Barboza hwaddr start, hwaddr size) 31326a8c353SAlexey Kardashevskiy { 31426a8c353SAlexey Kardashevskiy char mem_name[32]; 31526a8c353SAlexey Kardashevskiy uint64_t mem_reg_property[2]; 31626a8c353SAlexey Kardashevskiy int off; 31726a8c353SAlexey Kardashevskiy 31826a8c353SAlexey Kardashevskiy mem_reg_property[0] = cpu_to_be64(start); 31926a8c353SAlexey Kardashevskiy mem_reg_property[1] = cpu_to_be64(size); 32026a8c353SAlexey Kardashevskiy 3213a17e38fSAlexey Kardashevskiy sprintf(mem_name, "memory@%" HWADDR_PRIx, start); 32226a8c353SAlexey Kardashevskiy off = fdt_add_subnode(fdt, 0, mem_name); 32326a8c353SAlexey Kardashevskiy _FDT(off); 32426a8c353SAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 32526a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 32626a8c353SAlexey Kardashevskiy sizeof(mem_reg_property)))); 327f1aa45ffSDaniel Henrique Barboza spapr_numa_write_associativity_dt(spapr, fdt, off, nodeid); 32803d196b7SBharata B Rao return off; 32926a8c353SAlexey Kardashevskiy } 33026a8c353SAlexey Kardashevskiy 331f47bd1c8SIgor Mammedov static uint32_t spapr_pc_dimm_node(MemoryDeviceInfoList *list, ram_addr_t addr) 332f47bd1c8SIgor Mammedov { 333f47bd1c8SIgor Mammedov MemoryDeviceInfoList *info; 334f47bd1c8SIgor Mammedov 335f47bd1c8SIgor Mammedov for (info = list; info; info = info->next) { 336f47bd1c8SIgor Mammedov MemoryDeviceInfo *value = info->value; 337f47bd1c8SIgor Mammedov 338f47bd1c8SIgor Mammedov if (value && value->type == MEMORY_DEVICE_INFO_KIND_DIMM) { 339f47bd1c8SIgor Mammedov PCDIMMDeviceInfo *pcdimm_info = value->u.dimm.data; 340f47bd1c8SIgor Mammedov 341ccc2cef8SDavid Gibson if (addr >= pcdimm_info->addr && 342f47bd1c8SIgor Mammedov addr < (pcdimm_info->addr + pcdimm_info->size)) { 343f47bd1c8SIgor Mammedov return pcdimm_info->node; 344f47bd1c8SIgor Mammedov } 345f47bd1c8SIgor Mammedov } 346f47bd1c8SIgor Mammedov } 347f47bd1c8SIgor Mammedov 348f47bd1c8SIgor Mammedov return -1; 349f47bd1c8SIgor Mammedov } 350f47bd1c8SIgor Mammedov 351a324d6f1SBharata B Rao struct sPAPRDrconfCellV2 { 352a324d6f1SBharata B Rao uint32_t seq_lmbs; 353a324d6f1SBharata B Rao uint64_t base_addr; 354a324d6f1SBharata B Rao uint32_t drc_index; 355a324d6f1SBharata B Rao uint32_t aa_index; 356a324d6f1SBharata B Rao uint32_t flags; 357a324d6f1SBharata B Rao } QEMU_PACKED; 358a324d6f1SBharata B Rao 359a324d6f1SBharata B Rao typedef struct DrconfCellQueue { 360a324d6f1SBharata B Rao struct sPAPRDrconfCellV2 cell; 361a324d6f1SBharata B Rao QSIMPLEQ_ENTRY(DrconfCellQueue) entry; 362a324d6f1SBharata B Rao } DrconfCellQueue; 363a324d6f1SBharata B Rao 364a324d6f1SBharata B Rao static DrconfCellQueue * 365a324d6f1SBharata B Rao spapr_get_drconf_cell(uint32_t seq_lmbs, uint64_t base_addr, 366a324d6f1SBharata B Rao uint32_t drc_index, uint32_t aa_index, 367a324d6f1SBharata B Rao uint32_t flags) 36803d196b7SBharata B Rao { 369a324d6f1SBharata B Rao DrconfCellQueue *elem; 370a324d6f1SBharata B Rao 371a324d6f1SBharata B Rao elem = g_malloc0(sizeof(*elem)); 372a324d6f1SBharata B Rao elem->cell.seq_lmbs = cpu_to_be32(seq_lmbs); 373a324d6f1SBharata B Rao elem->cell.base_addr = cpu_to_be64(base_addr); 374a324d6f1SBharata B Rao elem->cell.drc_index = cpu_to_be32(drc_index); 375a324d6f1SBharata B Rao elem->cell.aa_index = cpu_to_be32(aa_index); 376a324d6f1SBharata B Rao elem->cell.flags = cpu_to_be32(flags); 377a324d6f1SBharata B Rao 378a324d6f1SBharata B Rao return elem; 379a324d6f1SBharata B Rao } 380a324d6f1SBharata B Rao 38191335a5eSDavid Gibson static int spapr_dt_dynamic_memory_v2(SpaprMachineState *spapr, void *fdt, 382a324d6f1SBharata B Rao int offset, MemoryDeviceInfoList *dimms) 3832a6593cbSAlexey Kardashevskiy { 3842a6593cbSAlexey Kardashevskiy MachineState *machine = MACHINE(spapr); 385cc941111SFabiano Rosas uint8_t *int_buf, *cur_index; 386a324d6f1SBharata B Rao int ret; 38703d196b7SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 388a324d6f1SBharata B Rao uint64_t addr, cur_addr, size; 389b0c14ec4SDavid Hildenbrand uint32_t nr_boot_lmbs = (machine->device_memory->base / lmb_size); 390b0c14ec4SDavid Hildenbrand uint64_t mem_end = machine->device_memory->base + 391b0c14ec4SDavid Hildenbrand memory_region_size(&machine->device_memory->mr); 392cc941111SFabiano Rosas uint32_t node, buf_len, nr_entries = 0; 393ce2918cbSDavid Gibson SpaprDrc *drc; 394a324d6f1SBharata B Rao DrconfCellQueue *elem, *next; 395a324d6f1SBharata B Rao MemoryDeviceInfoList *info; 396a324d6f1SBharata B Rao QSIMPLEQ_HEAD(, DrconfCellQueue) drconf_queue 397a324d6f1SBharata B Rao = QSIMPLEQ_HEAD_INITIALIZER(drconf_queue); 398a324d6f1SBharata B Rao 399a324d6f1SBharata B Rao /* Entry to cover RAM and the gap area */ 400a324d6f1SBharata B Rao elem = spapr_get_drconf_cell(nr_boot_lmbs, 0, 0, -1, 401a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_RESERVED | 402a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 403a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 404a324d6f1SBharata B Rao nr_entries++; 405a324d6f1SBharata B Rao 406b0c14ec4SDavid Hildenbrand cur_addr = machine->device_memory->base; 407a324d6f1SBharata B Rao for (info = dimms; info; info = info->next) { 408a324d6f1SBharata B Rao PCDIMMDeviceInfo *di = info->value->u.dimm.data; 409a324d6f1SBharata B Rao 410a324d6f1SBharata B Rao addr = di->addr; 411a324d6f1SBharata B Rao size = di->size; 412a324d6f1SBharata B Rao node = di->node; 413a324d6f1SBharata B Rao 414ee3a71e3SShivaprasad G Bhat /* 415ee3a71e3SShivaprasad G Bhat * The NVDIMM area is hotpluggable after the NVDIMM is unplugged. The 416ee3a71e3SShivaprasad G Bhat * area is marked hotpluggable in the next iteration for the bigger 417ee3a71e3SShivaprasad G Bhat * chunk including the NVDIMM occupied area. 418ee3a71e3SShivaprasad G Bhat */ 419ee3a71e3SShivaprasad G Bhat if (info->value->type == MEMORY_DEVICE_INFO_KIND_NVDIMM) 420ee3a71e3SShivaprasad G Bhat continue; 421ee3a71e3SShivaprasad G Bhat 422a324d6f1SBharata B Rao /* Entry for hot-pluggable area */ 423a324d6f1SBharata B Rao if (cur_addr < addr) { 424a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size); 425a324d6f1SBharata B Rao g_assert(drc); 426a324d6f1SBharata B Rao elem = spapr_get_drconf_cell((addr - cur_addr) / lmb_size, 427a324d6f1SBharata B Rao cur_addr, spapr_drc_index(drc), -1, 0); 428a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 429a324d6f1SBharata B Rao nr_entries++; 430a324d6f1SBharata B Rao } 431a324d6f1SBharata B Rao 432a324d6f1SBharata B Rao /* Entry for DIMM */ 433a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr / lmb_size); 434a324d6f1SBharata B Rao g_assert(drc); 435a324d6f1SBharata B Rao elem = spapr_get_drconf_cell(size / lmb_size, addr, 436a324d6f1SBharata B Rao spapr_drc_index(drc), node, 4370911a60cSLeonardo Bras (SPAPR_LMB_FLAGS_ASSIGNED | 4380911a60cSLeonardo Bras SPAPR_LMB_FLAGS_HOTREMOVABLE)); 439a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 440a324d6f1SBharata B Rao nr_entries++; 441a324d6f1SBharata B Rao cur_addr = addr + size; 442a324d6f1SBharata B Rao } 443a324d6f1SBharata B Rao 444a324d6f1SBharata B Rao /* Entry for remaining hotpluggable area */ 445a324d6f1SBharata B Rao if (cur_addr < mem_end) { 446a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size); 447a324d6f1SBharata B Rao g_assert(drc); 448a324d6f1SBharata B Rao elem = spapr_get_drconf_cell((mem_end - cur_addr) / lmb_size, 449a324d6f1SBharata B Rao cur_addr, spapr_drc_index(drc), -1, 0); 450a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 451a324d6f1SBharata B Rao nr_entries++; 452a324d6f1SBharata B Rao } 453a324d6f1SBharata B Rao 454a324d6f1SBharata B Rao buf_len = nr_entries * sizeof(struct sPAPRDrconfCellV2) + sizeof(uint32_t); 455a324d6f1SBharata B Rao int_buf = cur_index = g_malloc0(buf_len); 456a324d6f1SBharata B Rao *(uint32_t *)int_buf = cpu_to_be32(nr_entries); 457a324d6f1SBharata B Rao cur_index += sizeof(nr_entries); 458a324d6f1SBharata B Rao 459a324d6f1SBharata B Rao QSIMPLEQ_FOREACH_SAFE(elem, &drconf_queue, entry, next) { 460a324d6f1SBharata B Rao memcpy(cur_index, &elem->cell, sizeof(elem->cell)); 461a324d6f1SBharata B Rao cur_index += sizeof(elem->cell); 462a324d6f1SBharata B Rao QSIMPLEQ_REMOVE(&drconf_queue, elem, DrconfCellQueue, entry); 463a324d6f1SBharata B Rao g_free(elem); 464a324d6f1SBharata B Rao } 465a324d6f1SBharata B Rao 466a324d6f1SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory-v2", int_buf, buf_len); 467a324d6f1SBharata B Rao g_free(int_buf); 468a324d6f1SBharata B Rao if (ret < 0) { 469a324d6f1SBharata B Rao return -1; 470a324d6f1SBharata B Rao } 471a324d6f1SBharata B Rao return 0; 472a324d6f1SBharata B Rao } 473a324d6f1SBharata B Rao 47491335a5eSDavid Gibson static int spapr_dt_dynamic_memory(SpaprMachineState *spapr, void *fdt, 475a324d6f1SBharata B Rao int offset, MemoryDeviceInfoList *dimms) 476a324d6f1SBharata B Rao { 477b0c14ec4SDavid Hildenbrand MachineState *machine = MACHINE(spapr); 478a324d6f1SBharata B Rao int i, ret; 479a324d6f1SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 4800c9269a5SDavid Hildenbrand uint32_t device_lmb_start = machine->device_memory->base / lmb_size; 481b0c14ec4SDavid Hildenbrand uint32_t nr_lmbs = (machine->device_memory->base + 482b0c14ec4SDavid Hildenbrand memory_region_size(&machine->device_memory->mr)) / 483d0e5a8f2SBharata B Rao lmb_size; 48403d196b7SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 48516c25aefSBharata B Rao 48616c25aefSBharata B Rao /* 487ef001f06SThomas Huth * Allocate enough buffer size to fit in ibm,dynamic-memory 488ef001f06SThomas Huth */ 489a324d6f1SBharata B Rao buf_len = (nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1) * sizeof(uint32_t); 49003d196b7SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 49103d196b7SBharata B Rao int_buf[0] = cpu_to_be32(nr_lmbs); 49203d196b7SBharata B Rao cur_index++; 49303d196b7SBharata B Rao for (i = 0; i < nr_lmbs; i++) { 494d0e5a8f2SBharata B Rao uint64_t addr = i * lmb_size; 49503d196b7SBharata B Rao uint32_t *dynamic_memory = cur_index; 49603d196b7SBharata B Rao 4970c9269a5SDavid Hildenbrand if (i >= device_lmb_start) { 498ce2918cbSDavid Gibson SpaprDrc *drc; 499d0e5a8f2SBharata B Rao 500fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, i); 50103d196b7SBharata B Rao g_assert(drc); 50203d196b7SBharata B Rao 50303d196b7SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 50403d196b7SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 5050b55aa91SDavid Gibson dynamic_memory[2] = cpu_to_be32(spapr_drc_index(drc)); 50603d196b7SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 507f47bd1c8SIgor Mammedov dynamic_memory[4] = cpu_to_be32(spapr_pc_dimm_node(dimms, addr)); 508d0e5a8f2SBharata B Rao if (memory_region_present(get_system_memory(), addr)) { 50903d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); 51003d196b7SBharata B Rao } else { 51103d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(0); 51203d196b7SBharata B Rao } 513d0e5a8f2SBharata B Rao } else { 514d0e5a8f2SBharata B Rao /* 515d0e5a8f2SBharata B Rao * LMB information for RMA, boot time RAM and gap b/n RAM and 5160c9269a5SDavid Hildenbrand * device memory region -- all these are marked as reserved 517d0e5a8f2SBharata B Rao * and as having no valid DRC. 518d0e5a8f2SBharata B Rao */ 519d0e5a8f2SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 520d0e5a8f2SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 521d0e5a8f2SBharata B Rao dynamic_memory[2] = cpu_to_be32(0); 522d0e5a8f2SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 523d0e5a8f2SBharata B Rao dynamic_memory[4] = cpu_to_be32(-1); 524d0e5a8f2SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED | 525d0e5a8f2SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 526d0e5a8f2SBharata B Rao } 52703d196b7SBharata B Rao 52803d196b7SBharata B Rao cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; 52903d196b7SBharata B Rao } 53003d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len); 531a324d6f1SBharata B Rao g_free(int_buf); 53203d196b7SBharata B Rao if (ret < 0) { 533a324d6f1SBharata B Rao return -1; 534a324d6f1SBharata B Rao } 535a324d6f1SBharata B Rao return 0; 536a324d6f1SBharata B Rao } 537a324d6f1SBharata B Rao 538a324d6f1SBharata B Rao /* 539a324d6f1SBharata B Rao * Adds ibm,dynamic-reconfiguration-memory node. 540a324d6f1SBharata B Rao * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation 541a324d6f1SBharata B Rao * of this device tree node. 542a324d6f1SBharata B Rao */ 54391335a5eSDavid Gibson static int spapr_dt_dynamic_reconfiguration_memory(SpaprMachineState *spapr, 54491335a5eSDavid Gibson void *fdt) 545a324d6f1SBharata B Rao { 546a324d6f1SBharata B Rao MachineState *machine = MACHINE(spapr); 5470ee52012SDaniel Henrique Barboza int ret, offset; 548a324d6f1SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 5497abf9797SAnton Blanchard uint32_t prop_lmb_size[] = {cpu_to_be32(lmb_size >> 32), 5507abf9797SAnton Blanchard cpu_to_be32(lmb_size & 0xffffffff)}; 551a324d6f1SBharata B Rao MemoryDeviceInfoList *dimms = NULL; 552a324d6f1SBharata B Rao 553a324d6f1SBharata B Rao /* 5540c9269a5SDavid Hildenbrand * Don't create the node if there is no device memory 555a324d6f1SBharata B Rao */ 556a324d6f1SBharata B Rao if (machine->ram_size == machine->maxram_size) { 557a324d6f1SBharata B Rao return 0; 558a324d6f1SBharata B Rao } 559a324d6f1SBharata B Rao 560a324d6f1SBharata B Rao offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory"); 561a324d6f1SBharata B Rao 562a324d6f1SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size, 563a324d6f1SBharata B Rao sizeof(prop_lmb_size)); 564a324d6f1SBharata B Rao if (ret < 0) { 565a324d6f1SBharata B Rao return ret; 566a324d6f1SBharata B Rao } 567a324d6f1SBharata B Rao 568a324d6f1SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff); 569a324d6f1SBharata B Rao if (ret < 0) { 570a324d6f1SBharata B Rao return ret; 571a324d6f1SBharata B Rao } 572a324d6f1SBharata B Rao 573a324d6f1SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0); 574a324d6f1SBharata B Rao if (ret < 0) { 575a324d6f1SBharata B Rao return ret; 576a324d6f1SBharata B Rao } 577a324d6f1SBharata B Rao 578a324d6f1SBharata B Rao /* ibm,dynamic-memory or ibm,dynamic-memory-v2 */ 5792cc0e2e8SDavid Hildenbrand dimms = qmp_memory_device_list(); 580a324d6f1SBharata B Rao if (spapr_ovec_test(spapr->ov5_cas, OV5_DRMEM_V2)) { 58191335a5eSDavid Gibson ret = spapr_dt_dynamic_memory_v2(spapr, fdt, offset, dimms); 582a324d6f1SBharata B Rao } else { 58391335a5eSDavid Gibson ret = spapr_dt_dynamic_memory(spapr, fdt, offset, dimms); 584a324d6f1SBharata B Rao } 585a324d6f1SBharata B Rao qapi_free_MemoryDeviceInfoList(dimms); 586a324d6f1SBharata B Rao 587a324d6f1SBharata B Rao if (ret < 0) { 588a324d6f1SBharata B Rao return ret; 58903d196b7SBharata B Rao } 59003d196b7SBharata B Rao 5910ee52012SDaniel Henrique Barboza ret = spapr_numa_write_assoc_lookup_arrays(spapr, fdt, offset); 592a324d6f1SBharata B Rao 59303d196b7SBharata B Rao return ret; 59403d196b7SBharata B Rao } 59503d196b7SBharata B Rao 59691335a5eSDavid Gibson static int spapr_dt_memory(SpaprMachineState *spapr, void *fdt) 5976787d27bSMichael Roth { 598fa523f0dSDavid Gibson MachineState *machine = MACHINE(spapr); 599ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 60053018216SPaolo Bonzini hwaddr mem_start, node_size; 60153018216SPaolo Bonzini int i, nb_nodes = machine->numa_state->num_nodes; 60253018216SPaolo Bonzini NodeInfo *nodes = machine->numa_state->nodes; 60353018216SPaolo Bonzini 60453018216SPaolo Bonzini for (i = 0, mem_start = 0; i < nb_nodes; ++i) { 60553018216SPaolo Bonzini if (!nodes[i].node_mem) { 60653018216SPaolo Bonzini continue; 60753018216SPaolo Bonzini } 60853018216SPaolo Bonzini if (mem_start >= machine->ram_size) { 60953018216SPaolo Bonzini node_size = 0; 61053018216SPaolo Bonzini } else { 61153018216SPaolo Bonzini node_size = nodes[i].node_mem; 61253018216SPaolo Bonzini if (node_size > machine->ram_size - mem_start) { 61353018216SPaolo Bonzini node_size = machine->ram_size - mem_start; 61453018216SPaolo Bonzini } 61553018216SPaolo Bonzini } 61653018216SPaolo Bonzini if (!mem_start) { 61753018216SPaolo Bonzini /* spapr_machine_init() checks for rma_size <= node0_size 61853018216SPaolo Bonzini * already */ 619f1aa45ffSDaniel Henrique Barboza spapr_dt_memory_node(spapr, fdt, i, 0, spapr->rma_size); 62053018216SPaolo Bonzini mem_start += spapr->rma_size; 62153018216SPaolo Bonzini node_size -= spapr->rma_size; 62253018216SPaolo Bonzini } 62353018216SPaolo Bonzini for ( ; node_size; ) { 62453018216SPaolo Bonzini hwaddr sizetmp = pow2floor(node_size); 62553018216SPaolo Bonzini 62653018216SPaolo Bonzini /* mem_start != 0 here */ 62753018216SPaolo Bonzini if (ctzl(mem_start) < ctzl(sizetmp)) { 62853018216SPaolo Bonzini sizetmp = 1ULL << ctzl(mem_start); 62953018216SPaolo Bonzini } 63053018216SPaolo Bonzini 631f1aa45ffSDaniel Henrique Barboza spapr_dt_memory_node(spapr, fdt, i, mem_start, sizetmp); 63253018216SPaolo Bonzini node_size -= sizetmp; 63353018216SPaolo Bonzini mem_start += sizetmp; 63453018216SPaolo Bonzini } 63553018216SPaolo Bonzini } 63653018216SPaolo Bonzini 6376787d27bSMichael Roth /* Generate ibm,dynamic-reconfiguration-memory node if required */ 638fa523f0dSDavid Gibson if (spapr_ovec_test(spapr->ov5_cas, OV5_DRCONF_MEMORY)) { 639fa523f0dSDavid Gibson int ret; 640fa523f0dSDavid Gibson 6416787d27bSMichael Roth g_assert(smc->dr_lmb_enabled); 64291335a5eSDavid Gibson ret = spapr_dt_dynamic_reconfiguration_memory(spapr, fdt); 643417ece33SMichael Roth if (ret) { 6449b6c1da5SDaniel Henrique Barboza return ret; 645417ece33SMichael Roth } 6466787d27bSMichael Roth } 6476787d27bSMichael Roth 64853018216SPaolo Bonzini return 0; 64953018216SPaolo Bonzini } 65053018216SPaolo Bonzini 65191335a5eSDavid Gibson static void spapr_dt_cpu(CPUState *cs, void *fdt, int offset, 65253018216SPaolo Bonzini SpaprMachineState *spapr) 65353018216SPaolo Bonzini { 65453018216SPaolo Bonzini MachineState *ms = MACHINE(spapr); 65553018216SPaolo Bonzini PowerPCCPU *cpu = POWERPC_CPU(cs); 65653018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 65753018216SPaolo Bonzini PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 65853018216SPaolo Bonzini int index = spapr_get_vcpu_id(cpu); 65953018216SPaolo Bonzini uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 66053018216SPaolo Bonzini 0xffffffff, 0xffffffff}; 66153018216SPaolo Bonzini uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() 66253018216SPaolo Bonzini : SPAPR_TIMEBASE_FREQ; 66353018216SPaolo Bonzini uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; 66453018216SPaolo Bonzini uint32_t page_sizes_prop[64]; 66553018216SPaolo Bonzini size_t page_sizes_prop_size; 66653018216SPaolo Bonzini unsigned int smp_threads = ms->smp.threads; 66753018216SPaolo Bonzini uint32_t vcpus_per_socket = smp_threads * ms->smp.cores; 66853018216SPaolo Bonzini uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 66953018216SPaolo Bonzini int compat_smt = MIN(smp_threads, ppc_compat_max_vthreads(cpu)); 67053018216SPaolo Bonzini SpaprDrc *drc; 67153018216SPaolo Bonzini int drc_index; 67253018216SPaolo Bonzini uint32_t radix_AP_encodings[PPC_PAGE_SIZES_MAX_SZ]; 67353018216SPaolo Bonzini int i; 67453018216SPaolo Bonzini 67553018216SPaolo Bonzini drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index); 67653018216SPaolo Bonzini if (drc) { 67753018216SPaolo Bonzini drc_index = spapr_drc_index(drc); 67853018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index))); 6792a6593cbSAlexey Kardashevskiy } 6802a6593cbSAlexey Kardashevskiy 6812a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); 6822a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 6832a6593cbSAlexey Kardashevskiy 6842a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 6852a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 6862a6593cbSAlexey Kardashevskiy env->dcache_line_size))); 6872a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 6882a6593cbSAlexey Kardashevskiy env->dcache_line_size))); 6892a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 6902a6593cbSAlexey Kardashevskiy env->icache_line_size))); 6912a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 6922a6593cbSAlexey Kardashevskiy env->icache_line_size))); 6932a6593cbSAlexey Kardashevskiy 6942a6593cbSAlexey Kardashevskiy if (pcc->l1_dcache_size) { 6952a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 6962a6593cbSAlexey Kardashevskiy pcc->l1_dcache_size))); 6972a6593cbSAlexey Kardashevskiy } else { 6982a6593cbSAlexey Kardashevskiy warn_report("Unknown L1 dcache size for cpu"); 6992a6593cbSAlexey Kardashevskiy } 7002a6593cbSAlexey Kardashevskiy if (pcc->l1_icache_size) { 7012a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 7022a6593cbSAlexey Kardashevskiy pcc->l1_icache_size))); 7032a6593cbSAlexey Kardashevskiy } else { 7042a6593cbSAlexey Kardashevskiy warn_report("Unknown L1 icache size for cpu"); 7052a6593cbSAlexey Kardashevskiy } 7062a6593cbSAlexey Kardashevskiy 7072a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 7082a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 7092a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "slb-size", cpu->hash64_opts->slb_size))); 7102a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", cpu->hash64_opts->slb_size))); 7112a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 7122a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 7132a6593cbSAlexey Kardashevskiy 71453018216SPaolo Bonzini if (env->spr_cb[SPR_PURR].oea_read) { 71553018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,purr", 1))); 71653018216SPaolo Bonzini } 71753018216SPaolo Bonzini if (env->spr_cb[SPR_SPURR].oea_read) { 71853018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,spurr", 1))); 71953018216SPaolo Bonzini } 7205fe269b1SPaul Mackerras 72153018216SPaolo Bonzini if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 72253018216SPaolo Bonzini _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 72353018216SPaolo Bonzini segs, sizeof(segs)))); 72453018216SPaolo Bonzini } 7255fe269b1SPaul Mackerras 7265fe269b1SPaul Mackerras /* Advertise VSX (vector extensions) if available 7275fe269b1SPaul Mackerras * 1 == VMX / Altivec available 7285fe269b1SPaul Mackerras * 2 == VSX available 7295fe269b1SPaul Mackerras * 73053018216SPaolo Bonzini * Only CPUs for which we create core types in spapr_cpu_core.c 73153018216SPaolo Bonzini * are possible, and all of those have VMX */ 73253018216SPaolo Bonzini if (spapr_get_cap(spapr, SPAPR_CAP_VSX) != 0) { 73353018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2))); 73453018216SPaolo Bonzini } else { 73553018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1))); 73628e02042SDavid Gibson } 73753018216SPaolo Bonzini 738fb164994SDavid Gibson /* Advertise DFP (Decimal Floating Point) if available 7397db8a127SAlexey Kardashevskiy * 0 / no property == no DFP 7407db8a127SAlexey Kardashevskiy * 1 == DFP available */ 7417db8a127SAlexey Kardashevskiy if (spapr_get_cap(spapr, SPAPR_CAP_DFP) != 0) { 7427db8a127SAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 74353018216SPaolo Bonzini } 7447db8a127SAlexey Kardashevskiy 7457db8a127SAlexey Kardashevskiy page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 7467db8a127SAlexey Kardashevskiy sizeof(page_sizes_prop)); 747fb164994SDavid Gibson if (page_sizes_prop_size) { 7487db8a127SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 74953018216SPaolo Bonzini page_sizes_prop, page_sizes_prop_size))); 75053018216SPaolo Bonzini } 7517db8a127SAlexey Kardashevskiy 75291335a5eSDavid Gibson spapr_dt_pa_features(spapr, cpu, fdt, offset); 75353018216SPaolo Bonzini 7547db8a127SAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", 7557db8a127SAlexey Kardashevskiy cs->cpu_index / vcpus_per_socket))); 7567db8a127SAlexey Kardashevskiy 75753018216SPaolo Bonzini _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", 758fb164994SDavid Gibson pft_size_prop, sizeof(pft_size_prop)))); 7595fe269b1SPaul Mackerras 7605fe269b1SPaul Mackerras if (ms->numa_state->num_nodes > 1) { 7618f86a408SDaniel Henrique Barboza _FDT(spapr_numa_fixup_cpu_dt(spapr, fdt, offset, cpu)); 7625fe269b1SPaul Mackerras } 7635fe269b1SPaul Mackerras 7647db8a127SAlexey Kardashevskiy _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt)); 7657db8a127SAlexey Kardashevskiy 7667db8a127SAlexey Kardashevskiy if (pcc->radix_page_info) { 7677db8a127SAlexey Kardashevskiy for (i = 0; i < pcc->radix_page_info->count; i++) { 7687db8a127SAlexey Kardashevskiy radix_AP_encodings[i] = 7697db8a127SAlexey Kardashevskiy cpu_to_be32(pcc->radix_page_info->entries[i]); 7706010818cSAlexey Kardashevskiy } 7716010818cSAlexey Kardashevskiy _FDT((fdt_setprop(fdt, offset, "ibm,processor-radix-AP-encodings", 7726010818cSAlexey Kardashevskiy radix_AP_encodings, 7736010818cSAlexey Kardashevskiy pcc->radix_page_info->count * 7746010818cSAlexey Kardashevskiy sizeof(radix_AP_encodings[0])))); 7756010818cSAlexey Kardashevskiy } 7766010818cSAlexey Kardashevskiy 7776010818cSAlexey Kardashevskiy /* 7786010818cSAlexey Kardashevskiy * We set this property to let the guest know that it can use the large 7796010818cSAlexey Kardashevskiy * decrementer and its width in bits. 7806010818cSAlexey Kardashevskiy */ 7816010818cSAlexey Kardashevskiy if (spapr_get_cap(spapr, SPAPR_CAP_LARGE_DECREMENTER) != SPAPR_CAP_OFF) 78253018216SPaolo Bonzini _FDT((fdt_setprop_u32(fdt, offset, "ibm,dec-bits", 78353018216SPaolo Bonzini pcc->lrg_decr_bits))); 78453018216SPaolo Bonzini } 78553018216SPaolo Bonzini 78691335a5eSDavid Gibson static void spapr_dt_cpus(void *fdt, SpaprMachineState *spapr) 78753018216SPaolo Bonzini { 78853018216SPaolo Bonzini CPUState **rev; 78953018216SPaolo Bonzini CPUState *cs; 79053018216SPaolo Bonzini int n_cpus; 79153018216SPaolo Bonzini int cpus_offset; 79253018216SPaolo Bonzini char *nodename; 79353018216SPaolo Bonzini int i; 79453018216SPaolo Bonzini 79553018216SPaolo Bonzini cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 79653018216SPaolo Bonzini _FDT(cpus_offset); 79753018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 79853018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 79953018216SPaolo Bonzini 80053018216SPaolo Bonzini /* 80153018216SPaolo Bonzini * We walk the CPUs in reverse order to ensure that CPU DT nodes 80253018216SPaolo Bonzini * created by fdt_add_subnode() end up in the right order in FDT 80353018216SPaolo Bonzini * for the guest kernel the enumerate the CPUs correctly. 80453018216SPaolo Bonzini * 80553018216SPaolo Bonzini * The CPU list cannot be traversed in reverse order, so we need 80653018216SPaolo Bonzini * to do extra work. 80753018216SPaolo Bonzini */ 80853018216SPaolo Bonzini n_cpus = 0; 80953018216SPaolo Bonzini rev = NULL; 8100da6f3feSBharata B Rao CPU_FOREACH(cs) { 8110da6f3feSBharata B Rao rev = g_renew(CPUState *, rev, n_cpus + 1); 8120da6f3feSBharata B Rao rev[n_cpus++] = cs; 8130da6f3feSBharata B Rao } 8140da6f3feSBharata B Rao 8150da6f3feSBharata B Rao for (i = n_cpus - 1; i >= 0; i--) { 8160da6f3feSBharata B Rao CPUState *cs = rev[i]; 8170da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 8180da6f3feSBharata B Rao int index = spapr_get_vcpu_id(cpu); 8190da6f3feSBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 8200da6f3feSBharata B Rao int offset; 8210da6f3feSBharata B Rao 8220da6f3feSBharata B Rao if (!spapr_is_thread0_in_vcore(spapr, cpu)) { 82322419c2aSDavid Gibson continue; 8240da6f3feSBharata B Rao } 8250da6f3feSBharata B Rao 8260da6f3feSBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, index); 8270da6f3feSBharata B Rao offset = fdt_add_subnode(fdt, cpus_offset, nodename); 8280da6f3feSBharata B Rao g_free(nodename); 8290da6f3feSBharata B Rao _FDT(offset); 83091335a5eSDavid Gibson spapr_dt_cpu(cs, fdt, offset, spapr); 8310da6f3feSBharata B Rao } 8320da6f3feSBharata B Rao 8330da6f3feSBharata B Rao g_free(rev); 8340da6f3feSBharata B Rao } 8350da6f3feSBharata B Rao 83691335a5eSDavid Gibson static int spapr_dt_rng(void *fdt) 8370da6f3feSBharata B Rao { 8380da6f3feSBharata B Rao int node; 8390da6f3feSBharata B Rao int ret; 8400da6f3feSBharata B Rao 8410da6f3feSBharata B Rao node = qemu_fdt_add_subnode(fdt, "/ibm,platform-facilities"); 8420da6f3feSBharata B Rao if (node <= 0) { 8430da6f3feSBharata B Rao return -1; 8440da6f3feSBharata B Rao } 8450da6f3feSBharata B Rao ret = fdt_setprop_string(fdt, node, "device_type", 8460da6f3feSBharata B Rao "ibm,platform-facilities"); 8470da6f3feSBharata B Rao ret |= fdt_setprop_cell(fdt, node, "#address-cells", 0x1); 8480da6f3feSBharata B Rao ret |= fdt_setprop_cell(fdt, node, "#size-cells", 0x0); 8490da6f3feSBharata B Rao 8500da6f3feSBharata B Rao node = fdt_add_subnode(fdt, node, "ibm,random-v1"); 8510da6f3feSBharata B Rao if (node <= 0) { 8520da6f3feSBharata B Rao return -1; 8530da6f3feSBharata B Rao } 8540da6f3feSBharata B Rao ret |= fdt_setprop_string(fdt, node, "compatible", "ibm,random"); 8550da6f3feSBharata B Rao 8560da6f3feSBharata B Rao return ret ? -1 : 0; 8570da6f3feSBharata B Rao } 8580da6f3feSBharata B Rao 859ce2918cbSDavid Gibson static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt) 8603f5dabceSDavid Gibson { 861fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 8623f5dabceSDavid Gibson int rtas; 8633f5dabceSDavid Gibson GString *hypertas = g_string_sized_new(256); 8643f5dabceSDavid Gibson GString *qemu_hypertas = g_string_sized_new(256); 8650c9269a5SDavid Hildenbrand uint64_t max_device_addr = MACHINE(spapr)->device_memory->base + 866b0c14ec4SDavid Hildenbrand memory_region_size(&MACHINE(spapr)->device_memory->mr); 8673f5dabceSDavid Gibson uint32_t lrdr_capacity[] = { 8680c9269a5SDavid Hildenbrand cpu_to_be32(max_device_addr >> 32), 8690c9269a5SDavid Hildenbrand cpu_to_be32(max_device_addr & 0xffffffff), 8707abf9797SAnton Blanchard cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE >> 32), 8717abf9797SAnton Blanchard cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE & 0xffffffff), 872fe6b6346SLike Xu cpu_to_be32(ms->smp.max_cpus / ms->smp.threads), 8733f5dabceSDavid Gibson }; 8743f5dabceSDavid Gibson 8753f5dabceSDavid Gibson _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas")); 8763f5dabceSDavid Gibson 8773f5dabceSDavid Gibson /* hypertas */ 8783f5dabceSDavid Gibson add_str(hypertas, "hcall-pft"); 8793f5dabceSDavid Gibson add_str(hypertas, "hcall-term"); 8803f5dabceSDavid Gibson add_str(hypertas, "hcall-dabr"); 8813f5dabceSDavid Gibson add_str(hypertas, "hcall-interrupt"); 8823f5dabceSDavid Gibson add_str(hypertas, "hcall-tce"); 8833f5dabceSDavid Gibson add_str(hypertas, "hcall-vio"); 8843f5dabceSDavid Gibson add_str(hypertas, "hcall-splpar"); 88510741314SNicholas Piggin add_str(hypertas, "hcall-join"); 8863f5dabceSDavid Gibson add_str(hypertas, "hcall-bulk"); 8873f5dabceSDavid Gibson add_str(hypertas, "hcall-set-mode"); 8883f5dabceSDavid Gibson add_str(hypertas, "hcall-sprg0"); 8893f5dabceSDavid Gibson add_str(hypertas, "hcall-copy"); 8903f5dabceSDavid Gibson add_str(hypertas, "hcall-debug"); 891c24ba3d0SLaurent Vivier add_str(hypertas, "hcall-vphn"); 8923f5dabceSDavid Gibson add_str(qemu_hypertas, "hcall-memop1"); 8933f5dabceSDavid Gibson 8943f5dabceSDavid Gibson if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { 8953f5dabceSDavid Gibson add_str(hypertas, "hcall-multi-tce"); 8963f5dabceSDavid Gibson } 89730f4b05bSDavid Gibson 89830f4b05bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { 89930f4b05bSDavid Gibson add_str(hypertas, "hcall-hpt-resize"); 90030f4b05bSDavid Gibson } 90130f4b05bSDavid Gibson 9023f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions", 9033f5dabceSDavid Gibson hypertas->str, hypertas->len)); 9043f5dabceSDavid Gibson g_string_free(hypertas, TRUE); 9053f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "qemu,hypertas-functions", 9063f5dabceSDavid Gibson qemu_hypertas->str, qemu_hypertas->len)); 9073f5dabceSDavid Gibson g_string_free(qemu_hypertas, TRUE); 9083f5dabceSDavid Gibson 9091eee9950SDaniel Henrique Barboza spapr_numa_write_rtas_dt(spapr, fdt, rtas); 910da9f80fbSSerhii Popovych 9110e236d34SNicholas Piggin /* 9120e236d34SNicholas Piggin * FWNMI reserves RTAS_ERROR_LOG_MAX for the machine check error log, 9130e236d34SNicholas Piggin * and 16 bytes per CPU for system reset error log plus an extra 8 bytes. 9140e236d34SNicholas Piggin * 9150e236d34SNicholas Piggin * The system reset requirements are driven by existing Linux and PowerVM 9160e236d34SNicholas Piggin * implementation which (contrary to PAPR) saves r3 in the error log 9170e236d34SNicholas Piggin * structure like machine check, so Linux expects to find the saved r3 9180e236d34SNicholas Piggin * value at the address in r3 upon FWNMI-enabled sreset interrupt (and 9190e236d34SNicholas Piggin * does not look at the error value). 9200e236d34SNicholas Piggin * 9210e236d34SNicholas Piggin * System reset interrupts are not subject to interlock like machine 9220e236d34SNicholas Piggin * check, so this memory area could be corrupted if the sreset is 9230e236d34SNicholas Piggin * interrupted by a machine check (or vice versa) if it was shared. To 9240e236d34SNicholas Piggin * prevent this, system reset uses per-CPU areas for the sreset save 9250e236d34SNicholas Piggin * area. A system reset that interrupts a system reset handler could 9260e236d34SNicholas Piggin * still overwrite this area, but Linux doesn't try to recover in that 9270e236d34SNicholas Piggin * case anyway. 9280e236d34SNicholas Piggin * 9290e236d34SNicholas Piggin * The extra 8 bytes is required because Linux's FWNMI error log check 9300e236d34SNicholas Piggin * is off-by-one. 9310e236d34SNicholas Piggin */ 9320e236d34SNicholas Piggin _FDT(fdt_setprop_cell(fdt, rtas, "rtas-size", RTAS_ERROR_LOG_MAX + 9330e236d34SNicholas Piggin ms->smp.max_cpus * sizeof(uint64_t)*2 + sizeof(uint64_t))); 9343f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-error-log-max", 9353f5dabceSDavid Gibson RTAS_ERROR_LOG_MAX)); 9363f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-event-scan-rate", 9373f5dabceSDavid Gibson RTAS_EVENT_SCAN_RATE)); 9383f5dabceSDavid Gibson 9394f441474SDavid Gibson g_assert(msi_nonbroken); 9403f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,change-msix-capable", NULL, 0)); 9413f5dabceSDavid Gibson 9423f5dabceSDavid Gibson /* 9433f5dabceSDavid Gibson * According to PAPR, rtas ibm,os-term does not guarantee a return 9443f5dabceSDavid Gibson * back to the guest cpu. 9453f5dabceSDavid Gibson * 9463f5dabceSDavid Gibson * While an additional ibm,extended-os-term property indicates 9473f5dabceSDavid Gibson * that rtas call return will always occur. Set this property. 9483f5dabceSDavid Gibson */ 9493f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,extended-os-term", NULL, 0)); 9503f5dabceSDavid Gibson 9513f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,lrdr-capacity", 9523f5dabceSDavid Gibson lrdr_capacity, sizeof(lrdr_capacity))); 9533f5dabceSDavid Gibson 9543f5dabceSDavid Gibson spapr_dt_rtas_tokens(fdt, rtas); 9553f5dabceSDavid Gibson } 9563f5dabceSDavid Gibson 957db592b5bSCédric Le Goater /* 958db592b5bSCédric Le Goater * Prepare ibm,arch-vec-5-platform-support, which indicates the MMU 959db592b5bSCédric Le Goater * and the XIVE features that the guest may request and thus the valid 960db592b5bSCédric Le Goater * values for bytes 23..26 of option vector 5: 961db592b5bSCédric Le Goater */ 962ce2918cbSDavid Gibson static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt, 963db592b5bSCédric Le Goater int chosen) 9649fb4541fSSam Bobroff { 965545d6e2bSSuraj Jitindar Singh PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); 966545d6e2bSSuraj Jitindar Singh 967f2b14e3aSCédric Le Goater char val[2 * 4] = { 968ca62823bSDavid Gibson 23, 0x00, /* XICS / XIVE mode */ 9699fb4541fSSam Bobroff 24, 0x00, /* Hash/Radix, filled in below. */ 9709fb4541fSSam Bobroff 25, 0x00, /* Hash options: Segment Tables == no, GTSE == no. */ 9719fb4541fSSam Bobroff 26, 0x40, /* Radix options: GTSE == yes. */ 9729fb4541fSSam Bobroff }; 9739fb4541fSSam Bobroff 974ca62823bSDavid Gibson if (spapr->irq->xics && spapr->irq->xive) { 975ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_BOTH; 976ca62823bSDavid Gibson } else if (spapr->irq->xive) { 977ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_EXPLOIT; 978ca62823bSDavid Gibson } else { 979ca62823bSDavid Gibson assert(spapr->irq->xics); 980ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_LEGACY; 981ca62823bSDavid Gibson } 982ca62823bSDavid Gibson 9837abd43baSSuraj Jitindar Singh if (!ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0, 9847abd43baSSuraj Jitindar Singh first_ppc_cpu->compat_pvr)) { 985db592b5bSCédric Le Goater /* 986db592b5bSCédric Le Goater * If we're in a pre POWER9 compat mode then the guest should 987db592b5bSCédric Le Goater * do hash and use the legacy interrupt mode 988db592b5bSCédric Le Goater */ 989ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_LEGACY; /* XICS */ 9907abd43baSSuraj Jitindar Singh val[3] = 0x00; /* Hash */ 9917abd43baSSuraj Jitindar Singh } else if (kvm_enabled()) { 9929fb4541fSSam Bobroff if (kvmppc_has_cap_mmu_radix() && kvmppc_has_cap_mmu_hash_v3()) { 993f2b14e3aSCédric Le Goater val[3] = 0x80; /* OV5_MMU_BOTH */ 9949fb4541fSSam Bobroff } else if (kvmppc_has_cap_mmu_radix()) { 995f2b14e3aSCédric Le Goater val[3] = 0x40; /* OV5_MMU_RADIX_300 */ 9969fb4541fSSam Bobroff } else { 997f2b14e3aSCédric Le Goater val[3] = 0x00; /* Hash */ 9989fb4541fSSam Bobroff } 9999fb4541fSSam Bobroff } else { 10007abd43baSSuraj Jitindar Singh /* V3 MMU supports both hash and radix in tcg (with dynamic switching) */ 1001f2b14e3aSCédric Le Goater val[3] = 0xC0; 1002545d6e2bSSuraj Jitindar Singh } 10039fb4541fSSam Bobroff _FDT(fdt_setprop(fdt, chosen, "ibm,arch-vec-5-platform-support", 10049fb4541fSSam Bobroff val, sizeof(val))); 10059fb4541fSSam Bobroff } 10069fb4541fSSam Bobroff 10071e0e1108SDavid Gibson static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt, bool reset) 10087c866c6aSDavid Gibson { 10097c866c6aSDavid Gibson MachineState *machine = MACHINE(spapr); 10106c3829a2SAlexey Kardashevskiy SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 10117c866c6aSDavid Gibson int chosen; 10121e0e1108SDavid Gibson 10131e0e1108SDavid Gibson _FDT(chosen = fdt_add_subnode(fdt, 0, "chosen")); 10141e0e1108SDavid Gibson 10151e0e1108SDavid Gibson if (reset) { 10167c866c6aSDavid Gibson const char *boot_device = machine->boot_order; 10177c866c6aSDavid Gibson char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus); 10187c866c6aSDavid Gibson size_t cb = 0; 1019907aac2fSMark Cave-Ayland char *bootlist = get_boot_devices_list(&cb); 10207c866c6aSDavid Gibson 10215ced7895SAlexey Kardashevskiy if (machine->kernel_cmdline && machine->kernel_cmdline[0]) { 10225ced7895SAlexey Kardashevskiy _FDT(fdt_setprop_string(fdt, chosen, "bootargs", 10235ced7895SAlexey Kardashevskiy machine->kernel_cmdline)); 10245ced7895SAlexey Kardashevskiy } 10251e0e1108SDavid Gibson 10265ced7895SAlexey Kardashevskiy if (spapr->initrd_size) { 10277c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-start", 10287c866c6aSDavid Gibson spapr->initrd_base)); 10297c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-end", 10307c866c6aSDavid Gibson spapr->initrd_base + spapr->initrd_size)); 10315ced7895SAlexey Kardashevskiy } 10327c866c6aSDavid Gibson 10337c866c6aSDavid Gibson if (spapr->kernel_size) { 103487262806SAlexey Kardashevskiy uint64_t kprop[2] = { cpu_to_be64(spapr->kernel_addr), 10357c866c6aSDavid Gibson cpu_to_be64(spapr->kernel_size) }; 10367c866c6aSDavid Gibson 10377c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel", 10387c866c6aSDavid Gibson &kprop, sizeof(kprop))); 10397c866c6aSDavid Gibson if (spapr->kernel_le) { 10407c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel-le", NULL, 0)); 10417c866c6aSDavid Gibson } 10427c866c6aSDavid Gibson } 10437c866c6aSDavid Gibson if (boot_menu) { 10447c866c6aSDavid Gibson _FDT((fdt_setprop_cell(fdt, chosen, "qemu,boot-menu", boot_menu))); 10457c866c6aSDavid Gibson } 10467c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-width", graphic_width)); 10477c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-height", graphic_height)); 10487c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-depth", graphic_depth)); 10497c866c6aSDavid Gibson 10507c866c6aSDavid Gibson if (cb && bootlist) { 10517c866c6aSDavid Gibson int i; 10527c866c6aSDavid Gibson 10537c866c6aSDavid Gibson for (i = 0; i < cb; i++) { 10547c866c6aSDavid Gibson if (bootlist[i] == '\n') { 10557c866c6aSDavid Gibson bootlist[i] = ' '; 10567c866c6aSDavid Gibson } 10577c866c6aSDavid Gibson } 10587c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-list", bootlist)); 10597c866c6aSDavid Gibson } 10607c866c6aSDavid Gibson 10617c866c6aSDavid Gibson if (boot_device && strlen(boot_device)) { 10627c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-device", boot_device)); 10637c866c6aSDavid Gibson } 10647c866c6aSDavid Gibson 10657c866c6aSDavid Gibson if (!spapr->has_graphics && stdout_path) { 106690ee4e01SNikunj A Dadhania /* 10671e0e1108SDavid Gibson * "linux,stdout-path" and "stdout" properties are 10681e0e1108SDavid Gibson * deprecated by linux kernel. New platforms should only 10691e0e1108SDavid Gibson * use the "stdout-path" property. Set the new property 10701e0e1108SDavid Gibson * and continue using older property to remain compatible 10711e0e1108SDavid Gibson * with the existing firmware. 107290ee4e01SNikunj A Dadhania */ 10737c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "linux,stdout-path", stdout_path)); 107490ee4e01SNikunj A Dadhania _FDT(fdt_setprop_string(fdt, chosen, "stdout-path", stdout_path)); 10757c866c6aSDavid Gibson } 10767c866c6aSDavid Gibson 10771e0e1108SDavid Gibson /* 10781e0e1108SDavid Gibson * We can deal with BAR reallocation just fine, advertise it 10791e0e1108SDavid Gibson * to the guest 10801e0e1108SDavid Gibson */ 10816c3829a2SAlexey Kardashevskiy if (smc->linux_pci_probe) { 10826c3829a2SAlexey Kardashevskiy _FDT(fdt_setprop_cell(fdt, chosen, "linux,pci-probe-only", 0)); 10836c3829a2SAlexey Kardashevskiy } 10846c3829a2SAlexey Kardashevskiy 1085db592b5bSCédric Le Goater spapr_dt_ov5_platform_support(spapr, fdt, chosen); 10869fb4541fSSam Bobroff 10877c866c6aSDavid Gibson g_free(stdout_path); 10887c866c6aSDavid Gibson g_free(bootlist); 10897c866c6aSDavid Gibson } 10907c866c6aSDavid Gibson 109191335a5eSDavid Gibson _FDT(spapr_dt_ovec(fdt, chosen, spapr->ov5_cas, "ibm,architecture-vec-5")); 10921e0e1108SDavid Gibson } 10931e0e1108SDavid Gibson 1094ce2918cbSDavid Gibson static void spapr_dt_hypervisor(SpaprMachineState *spapr, void *fdt) 1095fca5f2dcSDavid Gibson { 1096fca5f2dcSDavid Gibson /* The /hypervisor node isn't in PAPR - this is a hack to allow PR 1097fca5f2dcSDavid Gibson * KVM to work under pHyp with some guest co-operation */ 1098fca5f2dcSDavid Gibson int hypervisor; 1099fca5f2dcSDavid Gibson uint8_t hypercall[16]; 1100fca5f2dcSDavid Gibson 1101fca5f2dcSDavid Gibson _FDT(hypervisor = fdt_add_subnode(fdt, 0, "hypervisor")); 1102fca5f2dcSDavid Gibson /* indicate KVM hypercall interface */ 1103fca5f2dcSDavid Gibson _FDT(fdt_setprop_string(fdt, hypervisor, "compatible", "linux,kvm")); 1104fca5f2dcSDavid Gibson if (kvmppc_has_cap_fixup_hcalls()) { 1105fca5f2dcSDavid Gibson /* 1106fca5f2dcSDavid Gibson * Older KVM versions with older guest kernels were broken 1107fca5f2dcSDavid Gibson * with the magic page, don't allow the guest to map it. 1108fca5f2dcSDavid Gibson */ 1109fca5f2dcSDavid Gibson if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall, 1110fca5f2dcSDavid Gibson sizeof(hypercall))) { 1111fca5f2dcSDavid Gibson _FDT(fdt_setprop(fdt, hypervisor, "hcall-instructions", 1112fca5f2dcSDavid Gibson hypercall, sizeof(hypercall))); 1113fca5f2dcSDavid Gibson } 1114fca5f2dcSDavid Gibson } 1115fca5f2dcSDavid Gibson } 1116fca5f2dcSDavid Gibson 11170c21e073SDavid Gibson void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space) 111853018216SPaolo Bonzini { 1119c86c1affSDaniel Henrique Barboza MachineState *machine = MACHINE(spapr); 11203c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 1121ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 11227c866c6aSDavid Gibson int ret; 112353018216SPaolo Bonzini void *fdt; 1124ce2918cbSDavid Gibson SpaprPhbState *phb; 1125398a0bd5SDavid Gibson char *buf; 112653018216SPaolo Bonzini 112797b32a6aSDavid Gibson fdt = g_malloc0(space); 112897b32a6aSDavid Gibson _FDT((fdt_create_empty_tree(fdt, space))); 112953018216SPaolo Bonzini 1130398a0bd5SDavid Gibson /* Root node */ 1131398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "device_type", "chrp")); 1132398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "model", "IBM pSeries (emulated by qemu)")); 1133398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "compatible", "qemu,pseries")); 1134398a0bd5SDavid Gibson 11350a794529SDavid Gibson /* Guest UUID & Name*/ 1136398a0bd5SDavid Gibson buf = qemu_uuid_unparse_strdup(&qemu_uuid); 1137398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "vm,uuid", buf)); 1138398a0bd5SDavid Gibson if (qemu_uuid_set) { 1139398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "system-id", buf)); 1140398a0bd5SDavid Gibson } 1141398a0bd5SDavid Gibson g_free(buf); 1142398a0bd5SDavid Gibson 1143398a0bd5SDavid Gibson if (qemu_get_vm_name()) { 1144398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "ibm,partition-name", 1145398a0bd5SDavid Gibson qemu_get_vm_name())); 1146398a0bd5SDavid Gibson } 1147398a0bd5SDavid Gibson 11480a794529SDavid Gibson /* Host Model & Serial Number */ 11490a794529SDavid Gibson if (spapr->host_model) { 11500a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model)); 11510a794529SDavid Gibson } else if (smc->broken_host_serial_model && kvmppc_get_host_model(&buf)) { 11520a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-model", buf)); 11530a794529SDavid Gibson g_free(buf); 11540a794529SDavid Gibson } 11550a794529SDavid Gibson 11560a794529SDavid Gibson if (spapr->host_serial) { 11570a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial)); 11580a794529SDavid Gibson } else if (smc->broken_host_serial_model && kvmppc_get_host_serial(&buf)) { 11590a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf)); 11600a794529SDavid Gibson g_free(buf); 11610a794529SDavid Gibson } 11620a794529SDavid Gibson 1163398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#address-cells", 2)); 1164398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2)); 116553018216SPaolo Bonzini 1166fc7e0765SDavid Gibson /* /interrupt controller */ 116705289273SDavid Gibson spapr_irq_dt(spapr, spapr_max_server_number(spapr), fdt, PHANDLE_INTC); 1168fc7e0765SDavid Gibson 116991335a5eSDavid Gibson ret = spapr_dt_memory(spapr, fdt); 1170e8f986fcSBharata B Rao if (ret < 0) { 1171ce9863b7SCédric Le Goater error_report("couldn't setup memory nodes in fdt"); 1172e8f986fcSBharata B Rao exit(1); 117353018216SPaolo Bonzini } 117453018216SPaolo Bonzini 1175bf5a6696SDavid Gibson /* /vdevice */ 1176bf5a6696SDavid Gibson spapr_dt_vdevice(spapr->vio_bus, fdt); 117753018216SPaolo Bonzini 11784d9392beSThomas Huth if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) { 117991335a5eSDavid Gibson ret = spapr_dt_rng(fdt); 11804d9392beSThomas Huth if (ret < 0) { 1181ce9863b7SCédric Le Goater error_report("could not set up rng device in the fdt"); 11824d9392beSThomas Huth exit(1); 11834d9392beSThomas Huth } 11844d9392beSThomas Huth } 11854d9392beSThomas Huth 118653018216SPaolo Bonzini QLIST_FOREACH(phb, &spapr->phbs, list) { 11878cbe71ecSDavid Gibson ret = spapr_dt_phb(spapr, phb, PHANDLE_INTC, fdt, NULL); 118853018216SPaolo Bonzini if (ret < 0) { 1189da34fed7SThomas Huth error_report("couldn't setup PCI devices in fdt"); 119053018216SPaolo Bonzini exit(1); 119153018216SPaolo Bonzini } 1192da34fed7SThomas Huth } 119353018216SPaolo Bonzini 119491335a5eSDavid Gibson spapr_dt_cpus(fdt, spapr); 119553018216SPaolo Bonzini 1196c20d332aSBharata B Rao if (smc->dr_lmb_enabled) { 11979e7d38e8SDavid Gibson _FDT(spapr_dt_drc(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB)); 1198c20d332aSBharata B Rao } 1199c20d332aSBharata B Rao 1200c5514d0eSIgor Mammedov if (mc->has_hotpluggable_cpus) { 1201af81cf32SBharata B Rao int offset = fdt_path_offset(fdt, "/cpus"); 12029e7d38e8SDavid Gibson ret = spapr_dt_drc(fdt, offset, NULL, SPAPR_DR_CONNECTOR_TYPE_CPU); 1203af81cf32SBharata B Rao if (ret < 0) { 1204af81cf32SBharata B Rao error_report("Couldn't set up CPU DR device tree properties"); 1205af81cf32SBharata B Rao exit(1); 1206af81cf32SBharata B Rao } 1207af81cf32SBharata B Rao } 1208af81cf32SBharata B Rao 1209ffb1e275SDavid Gibson /* /event-sources */ 1210ffbb1705SMichael Roth spapr_dt_events(spapr, fdt); 1211ffb1e275SDavid Gibson 12123f5dabceSDavid Gibson /* /rtas */ 12133f5dabceSDavid Gibson spapr_dt_rtas(spapr, fdt); 12143f5dabceSDavid Gibson 12157c866c6aSDavid Gibson /* /chosen */ 12161e0e1108SDavid Gibson spapr_dt_chosen(spapr, fdt, reset); 1217cf6e5223SDavid Gibson 1218fca5f2dcSDavid Gibson /* /hypervisor */ 1219fca5f2dcSDavid Gibson if (kvm_enabled()) { 1220fca5f2dcSDavid Gibson spapr_dt_hypervisor(spapr, fdt); 1221fca5f2dcSDavid Gibson } 1222fca5f2dcSDavid Gibson 1223cf6e5223SDavid Gibson /* Build memory reserve map */ 1224a49f62b9SAlexey Kardashevskiy if (reset) { 1225cf6e5223SDavid Gibson if (spapr->kernel_size) { 122687262806SAlexey Kardashevskiy _FDT((fdt_add_mem_rsv(fdt, spapr->kernel_addr, 122787262806SAlexey Kardashevskiy spapr->kernel_size))); 1228cf6e5223SDavid Gibson } 1229cf6e5223SDavid Gibson if (spapr->initrd_size) { 1230a49f62b9SAlexey Kardashevskiy _FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base, 1231a49f62b9SAlexey Kardashevskiy spapr->initrd_size))); 1232a49f62b9SAlexey Kardashevskiy } 1233cf6e5223SDavid Gibson } 1234cf6e5223SDavid Gibson 12353998ccd0SNathan Fontenot if (smc->dr_phb_enabled) { 12369e7d38e8SDavid Gibson ret = spapr_dt_drc(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_PHB); 12373998ccd0SNathan Fontenot if (ret < 0) { 12383998ccd0SNathan Fontenot error_report("Couldn't set up PHB DR device tree properties"); 12393998ccd0SNathan Fontenot exit(1); 12403998ccd0SNathan Fontenot } 12413998ccd0SNathan Fontenot } 12423998ccd0SNathan Fontenot 1243ee3a71e3SShivaprasad G Bhat /* NVDIMM devices */ 1244ee3a71e3SShivaprasad G Bhat if (mc->nvdimm_supported) { 1245f1aa45ffSDaniel Henrique Barboza spapr_dt_persistent_memory(spapr, fdt); 1246ee3a71e3SShivaprasad G Bhat } 1247ee3a71e3SShivaprasad G Bhat 1248997b6cfcSDavid Gibson return fdt; 124953018216SPaolo Bonzini } 125053018216SPaolo Bonzini 125153018216SPaolo Bonzini static uint64_t translate_kernel_address(void *opaque, uint64_t addr) 125253018216SPaolo Bonzini { 125387262806SAlexey Kardashevskiy SpaprMachineState *spapr = opaque; 125487262806SAlexey Kardashevskiy 125587262806SAlexey Kardashevskiy return (addr & 0x0fffffff) + spapr->kernel_addr; 125653018216SPaolo Bonzini } 125753018216SPaolo Bonzini 12581d1be34dSDavid Gibson static void emulate_spapr_hypercall(PPCVirtualHypervisor *vhyp, 12591d1be34dSDavid Gibson PowerPCCPU *cpu) 126053018216SPaolo Bonzini { 126153018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 126253018216SPaolo Bonzini 12638d04fb55SJan Kiszka /* The TCG path should also be holding the BQL at this point */ 12648d04fb55SJan Kiszka g_assert(qemu_mutex_iothread_locked()); 12658d04fb55SJan Kiszka 126653018216SPaolo Bonzini if (msr_pr) { 126753018216SPaolo Bonzini hcall_dprintf("Hypercall made with MSR[PR]=1\n"); 126853018216SPaolo Bonzini env->gpr[3] = H_PRIVILEGE; 126953018216SPaolo Bonzini } else { 127053018216SPaolo Bonzini env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]); 127153018216SPaolo Bonzini } 127253018216SPaolo Bonzini } 127353018216SPaolo Bonzini 127400fd075eSBenjamin Herrenschmidt struct LPCRSyncState { 127500fd075eSBenjamin Herrenschmidt target_ulong value; 127600fd075eSBenjamin Herrenschmidt target_ulong mask; 127700fd075eSBenjamin Herrenschmidt }; 127800fd075eSBenjamin Herrenschmidt 127900fd075eSBenjamin Herrenschmidt static void do_lpcr_sync(CPUState *cs, run_on_cpu_data arg) 128000fd075eSBenjamin Herrenschmidt { 128100fd075eSBenjamin Herrenschmidt struct LPCRSyncState *s = arg.host_ptr; 128200fd075eSBenjamin Herrenschmidt PowerPCCPU *cpu = POWERPC_CPU(cs); 128300fd075eSBenjamin Herrenschmidt CPUPPCState *env = &cpu->env; 128400fd075eSBenjamin Herrenschmidt target_ulong lpcr; 128500fd075eSBenjamin Herrenschmidt 128600fd075eSBenjamin Herrenschmidt cpu_synchronize_state(cs); 128700fd075eSBenjamin Herrenschmidt lpcr = env->spr[SPR_LPCR]; 128800fd075eSBenjamin Herrenschmidt lpcr &= ~s->mask; 128900fd075eSBenjamin Herrenschmidt lpcr |= s->value; 129000fd075eSBenjamin Herrenschmidt ppc_store_lpcr(cpu, lpcr); 129100fd075eSBenjamin Herrenschmidt } 129200fd075eSBenjamin Herrenschmidt 129300fd075eSBenjamin Herrenschmidt void spapr_set_all_lpcrs(target_ulong value, target_ulong mask) 129400fd075eSBenjamin Herrenschmidt { 129500fd075eSBenjamin Herrenschmidt CPUState *cs; 129600fd075eSBenjamin Herrenschmidt struct LPCRSyncState s = { 129700fd075eSBenjamin Herrenschmidt .value = value, 129800fd075eSBenjamin Herrenschmidt .mask = mask 129900fd075eSBenjamin Herrenschmidt }; 130000fd075eSBenjamin Herrenschmidt CPU_FOREACH(cs) { 130100fd075eSBenjamin Herrenschmidt run_on_cpu(cs, do_lpcr_sync, RUN_ON_CPU_HOST_PTR(&s)); 130200fd075eSBenjamin Herrenschmidt } 130300fd075eSBenjamin Herrenschmidt } 130400fd075eSBenjamin Herrenschmidt 130579825f4dSBenjamin Herrenschmidt static void spapr_get_pate(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry) 13069861bb3eSSuraj Jitindar Singh { 1307ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 13089861bb3eSSuraj Jitindar Singh 130979825f4dSBenjamin Herrenschmidt /* Copy PATE1:GR into PATE0:HR */ 131079825f4dSBenjamin Herrenschmidt entry->dw0 = spapr->patb_entry & PATE0_HR; 131179825f4dSBenjamin Herrenschmidt entry->dw1 = spapr->patb_entry; 13129861bb3eSSuraj Jitindar Singh } 13139861bb3eSSuraj Jitindar Singh 1314e6b8fd24SSamuel Mendoza-Jonas #define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2)) 1315e6b8fd24SSamuel Mendoza-Jonas #define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID) 1316e6b8fd24SSamuel Mendoza-Jonas #define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY) 1317e6b8fd24SSamuel Mendoza-Jonas #define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY)) 1318e6b8fd24SSamuel Mendoza-Jonas #define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY)) 1319e6b8fd24SSamuel Mendoza-Jonas 1320715c5407SDavid Gibson /* 1321715c5407SDavid Gibson * Get the fd to access the kernel htab, re-opening it if necessary 1322715c5407SDavid Gibson */ 1323ce2918cbSDavid Gibson static int get_htab_fd(SpaprMachineState *spapr) 1324715c5407SDavid Gibson { 132514b0d748SGreg Kurz Error *local_err = NULL; 132614b0d748SGreg Kurz 1327715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1328715c5407SDavid Gibson return spapr->htab_fd; 1329715c5407SDavid Gibson } 1330715c5407SDavid Gibson 133114b0d748SGreg Kurz spapr->htab_fd = kvmppc_get_htab_fd(false, 0, &local_err); 1332715c5407SDavid Gibson if (spapr->htab_fd < 0) { 133314b0d748SGreg Kurz error_report_err(local_err); 1334715c5407SDavid Gibson } 1335715c5407SDavid Gibson 1336715c5407SDavid Gibson return spapr->htab_fd; 1337715c5407SDavid Gibson } 1338715c5407SDavid Gibson 1339ce2918cbSDavid Gibson void close_htab_fd(SpaprMachineState *spapr) 1340715c5407SDavid Gibson { 1341715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1342715c5407SDavid Gibson close(spapr->htab_fd); 1343715c5407SDavid Gibson } 1344715c5407SDavid Gibson spapr->htab_fd = -1; 1345715c5407SDavid Gibson } 1346715c5407SDavid Gibson 1347e57ca75cSDavid Gibson static hwaddr spapr_hpt_mask(PPCVirtualHypervisor *vhyp) 1348e57ca75cSDavid Gibson { 1349ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1350e57ca75cSDavid Gibson 1351e57ca75cSDavid Gibson return HTAB_SIZE(spapr) / HASH_PTEG_SIZE_64 - 1; 1352e57ca75cSDavid Gibson } 1353e57ca75cSDavid Gibson 13541ec26c75SGreg Kurz static target_ulong spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp) 13551ec26c75SGreg Kurz { 1356ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 13571ec26c75SGreg Kurz 13581ec26c75SGreg Kurz assert(kvm_enabled()); 13591ec26c75SGreg Kurz 13601ec26c75SGreg Kurz if (!spapr->htab) { 13611ec26c75SGreg Kurz return 0; 13621ec26c75SGreg Kurz } 13631ec26c75SGreg Kurz 13641ec26c75SGreg Kurz return (target_ulong)(uintptr_t)spapr->htab | (spapr->htab_shift - 18); 13651ec26c75SGreg Kurz } 13661ec26c75SGreg Kurz 1367e57ca75cSDavid Gibson static const ppc_hash_pte64_t *spapr_map_hptes(PPCVirtualHypervisor *vhyp, 1368e57ca75cSDavid Gibson hwaddr ptex, int n) 1369e57ca75cSDavid Gibson { 1370ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1371e57ca75cSDavid Gibson hwaddr pte_offset = ptex * HASH_PTE_SIZE_64; 1372e57ca75cSDavid Gibson 1373e57ca75cSDavid Gibson if (!spapr->htab) { 1374e57ca75cSDavid Gibson /* 1375e57ca75cSDavid Gibson * HTAB is controlled by KVM. Fetch into temporary buffer 1376e57ca75cSDavid Gibson */ 1377e57ca75cSDavid Gibson ppc_hash_pte64_t *hptes = g_malloc(n * HASH_PTE_SIZE_64); 1378e57ca75cSDavid Gibson kvmppc_read_hptes(hptes, ptex, n); 1379e57ca75cSDavid Gibson return hptes; 1380e57ca75cSDavid Gibson } 1381e57ca75cSDavid Gibson 1382e57ca75cSDavid Gibson /* 1383e57ca75cSDavid Gibson * HTAB is controlled by QEMU. Just point to the internally 1384e57ca75cSDavid Gibson * accessible PTEG. 1385e57ca75cSDavid Gibson */ 1386e57ca75cSDavid Gibson return (const ppc_hash_pte64_t *)(spapr->htab + pte_offset); 1387e57ca75cSDavid Gibson } 1388e57ca75cSDavid Gibson 1389e57ca75cSDavid Gibson static void spapr_unmap_hptes(PPCVirtualHypervisor *vhyp, 1390e57ca75cSDavid Gibson const ppc_hash_pte64_t *hptes, 1391e57ca75cSDavid Gibson hwaddr ptex, int n) 1392e57ca75cSDavid Gibson { 1393ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1394e57ca75cSDavid Gibson 1395e57ca75cSDavid Gibson if (!spapr->htab) { 1396e57ca75cSDavid Gibson g_free((void *)hptes); 1397e57ca75cSDavid Gibson } 1398e57ca75cSDavid Gibson 1399e57ca75cSDavid Gibson /* Nothing to do for qemu managed HPT */ 1400e57ca75cSDavid Gibson } 1401e57ca75cSDavid Gibson 1402a2dd4e83SBenjamin Herrenschmidt void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex, 1403e57ca75cSDavid Gibson uint64_t pte0, uint64_t pte1) 1404e57ca75cSDavid Gibson { 1405a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(cpu->vhyp); 1406e57ca75cSDavid Gibson hwaddr offset = ptex * HASH_PTE_SIZE_64; 1407e57ca75cSDavid Gibson 1408e57ca75cSDavid Gibson if (!spapr->htab) { 1409e57ca75cSDavid Gibson kvmppc_write_hpte(ptex, pte0, pte1); 1410e57ca75cSDavid Gibson } else { 14113054b0caSBenjamin Herrenschmidt if (pte0 & HPTE64_V_VALID) { 1412e57ca75cSDavid Gibson stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); 14133054b0caSBenjamin Herrenschmidt /* 14143054b0caSBenjamin Herrenschmidt * When setting valid, we write PTE1 first. This ensures 14153054b0caSBenjamin Herrenschmidt * proper synchronization with the reading code in 14163054b0caSBenjamin Herrenschmidt * ppc_hash64_pteg_search() 14173054b0caSBenjamin Herrenschmidt */ 14183054b0caSBenjamin Herrenschmidt smp_wmb(); 14193054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset, pte0); 14203054b0caSBenjamin Herrenschmidt } else { 14213054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset, pte0); 14223054b0caSBenjamin Herrenschmidt /* 14233054b0caSBenjamin Herrenschmidt * When clearing it we set PTE0 first. This ensures proper 14243054b0caSBenjamin Herrenschmidt * synchronization with the reading code in 14253054b0caSBenjamin Herrenschmidt * ppc_hash64_pteg_search() 14263054b0caSBenjamin Herrenschmidt */ 14273054b0caSBenjamin Herrenschmidt smp_wmb(); 14283054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); 14293054b0caSBenjamin Herrenschmidt } 1430e57ca75cSDavid Gibson } 1431e57ca75cSDavid Gibson } 1432e57ca75cSDavid Gibson 1433a2dd4e83SBenjamin Herrenschmidt static void spapr_hpte_set_c(PPCVirtualHypervisor *vhyp, hwaddr ptex, 1434a2dd4e83SBenjamin Herrenschmidt uint64_t pte1) 1435a2dd4e83SBenjamin Herrenschmidt { 1436a2dd4e83SBenjamin Herrenschmidt hwaddr offset = ptex * HASH_PTE_SIZE_64 + 15; 1437a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1438a2dd4e83SBenjamin Herrenschmidt 1439a2dd4e83SBenjamin Herrenschmidt if (!spapr->htab) { 1440a2dd4e83SBenjamin Herrenschmidt /* There should always be a hash table when this is called */ 1441a2dd4e83SBenjamin Herrenschmidt error_report("spapr_hpte_set_c called with no hash table !"); 1442a2dd4e83SBenjamin Herrenschmidt return; 1443a2dd4e83SBenjamin Herrenschmidt } 1444a2dd4e83SBenjamin Herrenschmidt 1445a2dd4e83SBenjamin Herrenschmidt /* The HW performs a non-atomic byte update */ 1446a2dd4e83SBenjamin Herrenschmidt stb_p(spapr->htab + offset, (pte1 & 0xff) | 0x80); 1447a2dd4e83SBenjamin Herrenschmidt } 1448a2dd4e83SBenjamin Herrenschmidt 1449a2dd4e83SBenjamin Herrenschmidt static void spapr_hpte_set_r(PPCVirtualHypervisor *vhyp, hwaddr ptex, 1450a2dd4e83SBenjamin Herrenschmidt uint64_t pte1) 1451a2dd4e83SBenjamin Herrenschmidt { 1452a2dd4e83SBenjamin Herrenschmidt hwaddr offset = ptex * HASH_PTE_SIZE_64 + 14; 1453a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1454a2dd4e83SBenjamin Herrenschmidt 1455a2dd4e83SBenjamin Herrenschmidt if (!spapr->htab) { 1456a2dd4e83SBenjamin Herrenschmidt /* There should always be a hash table when this is called */ 1457a2dd4e83SBenjamin Herrenschmidt error_report("spapr_hpte_set_r called with no hash table !"); 1458a2dd4e83SBenjamin Herrenschmidt return; 1459a2dd4e83SBenjamin Herrenschmidt } 1460a2dd4e83SBenjamin Herrenschmidt 1461a2dd4e83SBenjamin Herrenschmidt /* The HW performs a non-atomic byte update */ 1462a2dd4e83SBenjamin Herrenschmidt stb_p(spapr->htab + offset, ((pte1 >> 8) & 0xff) | 0x01); 1463a2dd4e83SBenjamin Herrenschmidt } 1464a2dd4e83SBenjamin Herrenschmidt 14650b0b8310SDavid Gibson int spapr_hpt_shift_for_ramsize(uint64_t ramsize) 14668dfe8e7fSDavid Gibson { 14678dfe8e7fSDavid Gibson int shift; 14688dfe8e7fSDavid Gibson 14698dfe8e7fSDavid Gibson /* We aim for a hash table of size 1/128 the size of RAM (rounded 14708dfe8e7fSDavid Gibson * up). The PAPR recommendation is actually 1/64 of RAM size, but 14718dfe8e7fSDavid Gibson * that's much more than is needed for Linux guests */ 14728dfe8e7fSDavid Gibson shift = ctz64(pow2ceil(ramsize)) - 7; 14738dfe8e7fSDavid Gibson shift = MAX(shift, 18); /* Minimum architected size */ 14748dfe8e7fSDavid Gibson shift = MIN(shift, 46); /* Maximum architected size */ 14758dfe8e7fSDavid Gibson return shift; 14768dfe8e7fSDavid Gibson } 14778dfe8e7fSDavid Gibson 1478ce2918cbSDavid Gibson void spapr_free_hpt(SpaprMachineState *spapr) 147906ec79e8SBharata B Rao { 148006ec79e8SBharata B Rao g_free(spapr->htab); 148106ec79e8SBharata B Rao spapr->htab = NULL; 148206ec79e8SBharata B Rao spapr->htab_shift = 0; 148306ec79e8SBharata B Rao close_htab_fd(spapr); 148406ec79e8SBharata B Rao } 148506ec79e8SBharata B Rao 1486a4e3a7c0SGreg Kurz int spapr_reallocate_hpt(SpaprMachineState *spapr, int shift, Error **errp) 148753018216SPaolo Bonzini { 1488c3e051edSGreg Kurz ERRP_GUARD(); 1489c5f54f3eSDavid Gibson long rc; 149053018216SPaolo Bonzini 1491c5f54f3eSDavid Gibson /* Clean up any HPT info from a previous boot */ 149206ec79e8SBharata B Rao spapr_free_hpt(spapr); 149353018216SPaolo Bonzini 1494c5f54f3eSDavid Gibson rc = kvmppc_reset_htab(shift); 1495f0638a0bSFabiano Rosas 1496f0638a0bSFabiano Rosas if (rc == -EOPNOTSUPP) { 1497f0638a0bSFabiano Rosas error_setg(errp, "HPT not supported in nested guests"); 1498a4e3a7c0SGreg Kurz return -EOPNOTSUPP; 1499f0638a0bSFabiano Rosas } 1500f0638a0bSFabiano Rosas 1501c5f54f3eSDavid Gibson if (rc < 0) { 1502c5f54f3eSDavid Gibson /* kernel-side HPT needed, but couldn't allocate one */ 1503c3e051edSGreg Kurz error_setg_errno(errp, errno, "Failed to allocate KVM HPT of order %d", 1504c5f54f3eSDavid Gibson shift); 1505c3e051edSGreg Kurz error_append_hint(errp, "Try smaller maxmem?\n"); 1506a4e3a7c0SGreg Kurz return -errno; 1507c5f54f3eSDavid Gibson } else if (rc > 0) { 1508c5f54f3eSDavid Gibson /* kernel-side HPT allocated */ 1509c5f54f3eSDavid Gibson if (rc != shift) { 1510c5f54f3eSDavid Gibson error_setg(errp, 1511c3e051edSGreg Kurz "Requested order %d HPT, but kernel allocated order %ld", 1512c5f54f3eSDavid Gibson shift, rc); 1513c3e051edSGreg Kurz error_append_hint(errp, "Try smaller maxmem?\n"); 1514a4e3a7c0SGreg Kurz return -ENOSPC; 15157735fedaSBharata B Rao } 15167735fedaSBharata B Rao 151753018216SPaolo Bonzini spapr->htab_shift = shift; 1518c18ad9a5SDavid Gibson spapr->htab = NULL; 1519b817772aSBharata B Rao } else { 1520c5f54f3eSDavid Gibson /* kernel-side HPT not needed, allocate in userspace instead */ 1521c5f54f3eSDavid Gibson size_t size = 1ULL << shift; 1522c5f54f3eSDavid Gibson int i; 152301a57972SSamuel Mendoza-Jonas 1524c5f54f3eSDavid Gibson spapr->htab = qemu_memalign(size, size); 1525c5f54f3eSDavid Gibson memset(spapr->htab, 0, size); 1526c5f54f3eSDavid Gibson spapr->htab_shift = shift; 1527b817772aSBharata B Rao 1528c5f54f3eSDavid Gibson for (i = 0; i < size / HASH_PTE_SIZE_64; i++) { 1529c5f54f3eSDavid Gibson DIRTY_HPTE(HPTE(spapr->htab, i)); 15307735fedaSBharata B Rao } 153153018216SPaolo Bonzini } 1532ee4d9eccSSuraj Jitindar Singh /* We're setting up a hash table, so that means we're not radix */ 1533176dcceeSSuraj Jitindar Singh spapr->patb_entry = 0; 153400fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(0, LPCR_HR | LPCR_UPRT); 1535a4e3a7c0SGreg Kurz return 0; 153653018216SPaolo Bonzini } 153753018216SPaolo Bonzini 15388897ea5aSDavid Gibson void spapr_setup_hpt(SpaprMachineState *spapr) 1539b4db5413SSuraj Jitindar Singh { 15402772cf6bSDavid Gibson int hpt_shift; 15412772cf6bSDavid Gibson 1542087820e3SGreg Kurz if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DISABLED) { 15432772cf6bSDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(MACHINE(spapr)->maxram_size); 15442772cf6bSDavid Gibson } else { 1545768a20f3SDavid Gibson uint64_t current_ram_size; 1546768a20f3SDavid Gibson 1547768a20f3SDavid Gibson current_ram_size = MACHINE(spapr)->ram_size + get_plugged_memory_size(); 1548768a20f3SDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(current_ram_size); 15492772cf6bSDavid Gibson } 15502772cf6bSDavid Gibson spapr_reallocate_hpt(spapr, hpt_shift, &error_fatal); 15512772cf6bSDavid Gibson 15528897ea5aSDavid Gibson if (kvm_enabled()) { 15536a84737cSDavid Gibson hwaddr vrma_limit = kvmppc_vrma_limit(spapr->htab_shift); 15546a84737cSDavid Gibson 15558897ea5aSDavid Gibson /* Check our RMA fits in the possible VRMA */ 15568897ea5aSDavid Gibson if (vrma_limit < spapr->rma_size) { 15578897ea5aSDavid Gibson error_report("Unable to create %" HWADDR_PRIu 15588897ea5aSDavid Gibson "MiB RMA (VRMA only allows %" HWADDR_PRIu "MiB", 15598897ea5aSDavid Gibson spapr->rma_size / MiB, vrma_limit / MiB); 15608897ea5aSDavid Gibson exit(EXIT_FAILURE); 15618897ea5aSDavid Gibson } 1562b4db5413SSuraj Jitindar Singh } 1563b4db5413SSuraj Jitindar Singh } 1564b4db5413SSuraj Jitindar Singh 156582512483SGreg Kurz static int spapr_reset_drcs(Object *child, void *opaque) 156682512483SGreg Kurz { 1567ce2918cbSDavid Gibson SpaprDrc *drc = 1568ce2918cbSDavid Gibson (SpaprDrc *) object_dynamic_cast(child, 156982512483SGreg Kurz TYPE_SPAPR_DR_CONNECTOR); 157082512483SGreg Kurz 157182512483SGreg Kurz if (drc) { 157282512483SGreg Kurz spapr_drc_reset(drc); 157382512483SGreg Kurz } 157482512483SGreg Kurz 157582512483SGreg Kurz return 0; 157682512483SGreg Kurz } 157782512483SGreg Kurz 1578a0628599SLike Xu static void spapr_machine_reset(MachineState *machine) 157953018216SPaolo Bonzini { 1580ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(machine); 1581182735efSAndreas Färber PowerPCCPU *first_ppc_cpu; 1582744a928cSAlexey Kardashevskiy hwaddr fdt_addr; 1583997b6cfcSDavid Gibson void *fdt; 1584997b6cfcSDavid Gibson int rc; 1585259186a7SAndreas Färber 1586905db916SBharata B Rao kvmppc_svm_off(&error_fatal); 15879f6edd06SDavid Gibson spapr_caps_apply(spapr); 158833face6bSDavid Gibson 15891481fe5fSLaurent Vivier first_ppc_cpu = POWERPC_CPU(first_cpu); 15901481fe5fSLaurent Vivier if (kvm_enabled() && kvmppc_has_cap_mmu_radix() && 1591ad99d04cSDavid Gibson ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, 15921481fe5fSLaurent Vivier spapr->max_compat_pvr)) { 159379825f4dSBenjamin Herrenschmidt /* 159479825f4dSBenjamin Herrenschmidt * If using KVM with radix mode available, VCPUs can be started 1595b4db5413SSuraj Jitindar Singh * without a HPT because KVM will start them in radix mode. 159679825f4dSBenjamin Herrenschmidt * Set the GR bit in PATE so that we know there is no HPT. 159779825f4dSBenjamin Herrenschmidt */ 159879825f4dSBenjamin Herrenschmidt spapr->patb_entry = PATE1_GR; 159900fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(LPCR_HR | LPCR_UPRT, LPCR_HR | LPCR_UPRT); 1600b4db5413SSuraj Jitindar Singh } else { 16018897ea5aSDavid Gibson spapr_setup_hpt(spapr); 1602c5f54f3eSDavid Gibson } 160353018216SPaolo Bonzini 160425c9780dSDavid Gibson qemu_devices_reset(); 160525c9780dSDavid Gibson 16069012a53fSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas); 16079012a53fSGreg Kurz spapr->ov5_cas = spapr_ovec_new(); 16089012a53fSGreg Kurz 1609ce03a193SLaurent Vivier ppc_set_compat_all(spapr->max_compat_pvr, &error_fatal); 16109012a53fSGreg Kurz 1611ec132efaSAlexey Kardashevskiy /* 1612b2e22477SCédric Le Goater * This is fixing some of the default configuration of the XIVE 1613b2e22477SCédric Le Goater * devices. To be called after the reset of the machine devices. 1614b2e22477SCédric Le Goater */ 1615b2e22477SCédric Le Goater spapr_irq_reset(spapr, &error_fatal); 1616b2e22477SCédric Le Goater 161723ff81bdSGreg Kurz /* 161823ff81bdSGreg Kurz * There is no CAS under qtest. Simulate one to please the code that 161923ff81bdSGreg Kurz * depends on spapr->ov5_cas. This is especially needed to test device 162023ff81bdSGreg Kurz * unplug, so we do that before resetting the DRCs. 162123ff81bdSGreg Kurz */ 162223ff81bdSGreg Kurz if (qtest_enabled()) { 162323ff81bdSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas); 162423ff81bdSGreg Kurz spapr->ov5_cas = spapr_ovec_clone(spapr->ov5); 162523ff81bdSGreg Kurz } 162623ff81bdSGreg Kurz 162782512483SGreg Kurz /* DRC reset may cause a device to be unplugged. This will cause troubles 162882512483SGreg Kurz * if this device is used by another device (eg, a running vhost backend 162982512483SGreg Kurz * will crash QEMU if the DIMM holding the vring goes away). To avoid such 163082512483SGreg Kurz * situations, we reset DRCs after all devices have been reset. 163182512483SGreg Kurz */ 163282512483SGreg Kurz object_child_foreach_recursive(object_get_root(), spapr_reset_drcs, NULL); 163382512483SGreg Kurz 163456258174SDaniel Henrique Barboza spapr_clear_pending_events(spapr); 163553018216SPaolo Bonzini 1636b7d1f77aSBenjamin Herrenschmidt /* 1637b7d1f77aSBenjamin Herrenschmidt * We place the device tree and RTAS just below either the top of the RMA, 1638df269271SAlexey Kardashevskiy * or just below 2GB, whichever is lower, so that it can be 1639b7d1f77aSBenjamin Herrenschmidt * processed with 32-bit real mode code if necessary 1640b7d1f77aSBenjamin Herrenschmidt */ 1641744a928cSAlexey Kardashevskiy fdt_addr = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FDT_MAX_SIZE; 1642b7d1f77aSBenjamin Herrenschmidt 164397b32a6aSDavid Gibson fdt = spapr_build_fdt(spapr, true, FDT_MAX_SIZE); 164453018216SPaolo Bonzini 1645997b6cfcSDavid Gibson rc = fdt_pack(fdt); 1646997b6cfcSDavid Gibson 1647997b6cfcSDavid Gibson /* Should only fail if we've built a corrupted tree */ 1648997b6cfcSDavid Gibson assert(rc == 0); 1649997b6cfcSDavid Gibson 1650997b6cfcSDavid Gibson /* Load the fdt */ 1651997b6cfcSDavid Gibson qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 1652cae172abSDavid Gibson cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); 1653fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob); 1654fea35ca4SAlexey Kardashevskiy spapr->fdt_size = fdt_totalsize(fdt); 1655fea35ca4SAlexey Kardashevskiy spapr->fdt_initial_size = spapr->fdt_size; 1656fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = fdt; 1657997b6cfcSDavid Gibson 165853018216SPaolo Bonzini /* Set up the entry state */ 1659395a20d3SAlexey Kardashevskiy spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT, 0, fdt_addr, 0); 1660182735efSAndreas Färber first_ppc_cpu->env.gpr[5] = 0; 166153018216SPaolo Bonzini 1662edfdbf9cSNicholas Piggin spapr->fwnmi_system_reset_addr = -1; 16638af7e1feSNicholas Piggin spapr->fwnmi_machine_check_addr = -1; 16648af7e1feSNicholas Piggin spapr->fwnmi_machine_check_interlock = -1; 16659ac703acSAravinda Prasad 16669ac703acSAravinda Prasad /* Signal all vCPUs waiting on this condition */ 16678af7e1feSNicholas Piggin qemu_cond_broadcast(&spapr->fwnmi_machine_check_interlock_cond); 16682500fb42SAravinda Prasad 16692500fb42SAravinda Prasad migrate_del_blocker(spapr->fwnmi_migration_blocker); 167053018216SPaolo Bonzini } 167153018216SPaolo Bonzini 1672ce2918cbSDavid Gibson static void spapr_create_nvram(SpaprMachineState *spapr) 167353018216SPaolo Bonzini { 16743e80f690SMarkus Armbruster DeviceState *dev = qdev_new("spapr-nvram"); 16753978b863SPaolo Bonzini DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); 167653018216SPaolo Bonzini 16773978b863SPaolo Bonzini if (dinfo) { 1678934df912SMarkus Armbruster qdev_prop_set_drive_err(dev, "drive", blk_by_legacy_dinfo(dinfo), 16796231a6daSMarkus Armbruster &error_fatal); 168053018216SPaolo Bonzini } 168153018216SPaolo Bonzini 16823e80f690SMarkus Armbruster qdev_realize_and_unref(dev, &spapr->vio_bus->bus, &error_fatal); 168353018216SPaolo Bonzini 1684ce2918cbSDavid Gibson spapr->nvram = (struct SpaprNvram *)dev; 168553018216SPaolo Bonzini } 168653018216SPaolo Bonzini 1687ce2918cbSDavid Gibson static void spapr_rtc_create(SpaprMachineState *spapr) 168828df36a1SDavid Gibson { 16899fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(spapr), "rtc", &spapr->rtc, 16909fc7fc4dSMarkus Armbruster sizeof(spapr->rtc), TYPE_SPAPR_RTC, 1691f6d4dca8SThomas Huth &error_fatal, NULL); 1692ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&spapr->rtc), NULL, &error_fatal); 1693147ff807SCédric Le Goater object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc), 1694d2623129SMarkus Armbruster "date"); 169528df36a1SDavid Gibson } 169628df36a1SDavid Gibson 169753018216SPaolo Bonzini /* Returns whether we want to use VGA or not */ 169814c6a894SDavid Gibson static bool spapr_vga_init(PCIBus *pci_bus, Error **errp) 169953018216SPaolo Bonzini { 170053018216SPaolo Bonzini switch (vga_interface_type) { 170153018216SPaolo Bonzini case VGA_NONE: 17027effdaa3SMark Wu return false; 17037effdaa3SMark Wu case VGA_DEVICE: 17047effdaa3SMark Wu return true; 170553018216SPaolo Bonzini case VGA_STD: 1706b798c190SBenjamin Herrenschmidt case VGA_VIRTIO: 17076e66d0c6SThomas Huth case VGA_CIRRUS: 170853018216SPaolo Bonzini return pci_vga_init(pci_bus) != NULL; 170953018216SPaolo Bonzini default: 171014c6a894SDavid Gibson error_setg(errp, 171114c6a894SDavid Gibson "Unsupported VGA mode, only -vga std or -vga virtio is supported"); 171214c6a894SDavid Gibson return false; 171353018216SPaolo Bonzini } 171453018216SPaolo Bonzini } 171553018216SPaolo Bonzini 17164e5fe368SSuraj Jitindar Singh static int spapr_pre_load(void *opaque) 17174e5fe368SSuraj Jitindar Singh { 17184e5fe368SSuraj Jitindar Singh int rc; 17194e5fe368SSuraj Jitindar Singh 17204e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_load(opaque); 17214e5fe368SSuraj Jitindar Singh if (rc) { 17224e5fe368SSuraj Jitindar Singh return rc; 17234e5fe368SSuraj Jitindar Singh } 17244e5fe368SSuraj Jitindar Singh 17254e5fe368SSuraj Jitindar Singh return 0; 17264e5fe368SSuraj Jitindar Singh } 17274e5fe368SSuraj Jitindar Singh 1728880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id) 1729880ae7deSDavid Gibson { 1730ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 1731880ae7deSDavid Gibson int err = 0; 1732880ae7deSDavid Gibson 1733be85537dSDavid Gibson err = spapr_caps_post_migration(spapr); 1734be85537dSDavid Gibson if (err) { 1735be85537dSDavid Gibson return err; 1736be85537dSDavid Gibson } 1737be85537dSDavid Gibson 1738e502202cSCédric Le Goater /* 1739e502202cSCédric Le Goater * In earlier versions, there was no separate qdev for the PAPR 1740880ae7deSDavid Gibson * RTC, so the RTC offset was stored directly in sPAPREnvironment. 1741880ae7deSDavid Gibson * So when migrating from those versions, poke the incoming offset 1742e502202cSCédric Le Goater * value into the RTC device 1743e502202cSCédric Le Goater */ 1744880ae7deSDavid Gibson if (version_id < 3) { 1745147ff807SCédric Le Goater err = spapr_rtc_import_offset(&spapr->rtc, spapr->rtc_offset); 1746e502202cSCédric Le Goater if (err) { 1747e502202cSCédric Le Goater return err; 1748e502202cSCédric Le Goater } 1749880ae7deSDavid Gibson } 1750880ae7deSDavid Gibson 17510c86b2dfSLaurent Vivier if (kvm_enabled() && spapr->patb_entry) { 1752d39c90f5SBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(first_cpu); 175379825f4dSBenjamin Herrenschmidt bool radix = !!(spapr->patb_entry & PATE1_GR); 1754d39c90f5SBharata B Rao bool gtse = !!(cpu->env.spr[SPR_LPCR] & LPCR_GTSE); 1755d39c90f5SBharata B Rao 175600fd075eSBenjamin Herrenschmidt /* 175700fd075eSBenjamin Herrenschmidt * Update LPCR:HR and UPRT as they may not be set properly in 175800fd075eSBenjamin Herrenschmidt * the stream 175900fd075eSBenjamin Herrenschmidt */ 176000fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(radix ? (LPCR_HR | LPCR_UPRT) : 0, 176100fd075eSBenjamin Herrenschmidt LPCR_HR | LPCR_UPRT); 176200fd075eSBenjamin Herrenschmidt 1763d39c90f5SBharata B Rao err = kvmppc_configure_v3_mmu(cpu, radix, gtse, spapr->patb_entry); 1764d39c90f5SBharata B Rao if (err) { 1765d39c90f5SBharata B Rao error_report("Process table config unsupported by the host"); 1766d39c90f5SBharata B Rao return -EINVAL; 1767d39c90f5SBharata B Rao } 1768d39c90f5SBharata B Rao } 1769d39c90f5SBharata B Rao 17701c53b06cSCédric Le Goater err = spapr_irq_post_load(spapr, version_id); 17711c53b06cSCédric Le Goater if (err) { 17721c53b06cSCédric Le Goater return err; 17731c53b06cSCédric Le Goater } 17741c53b06cSCédric Le Goater 1775880ae7deSDavid Gibson return err; 1776880ae7deSDavid Gibson } 1777880ae7deSDavid Gibson 17784e5fe368SSuraj Jitindar Singh static int spapr_pre_save(void *opaque) 17794e5fe368SSuraj Jitindar Singh { 17804e5fe368SSuraj Jitindar Singh int rc; 17814e5fe368SSuraj Jitindar Singh 17824e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_save(opaque); 17834e5fe368SSuraj Jitindar Singh if (rc) { 17844e5fe368SSuraj Jitindar Singh return rc; 17854e5fe368SSuraj Jitindar Singh } 17864e5fe368SSuraj Jitindar Singh 17874e5fe368SSuraj Jitindar Singh return 0; 17884e5fe368SSuraj Jitindar Singh } 17894e5fe368SSuraj Jitindar Singh 1790880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id) 1791880ae7deSDavid Gibson { 1792880ae7deSDavid Gibson return version_id < 3; 1793880ae7deSDavid Gibson } 1794880ae7deSDavid Gibson 1795fd38804bSDaniel Henrique Barboza static bool spapr_pending_events_needed(void *opaque) 1796fd38804bSDaniel Henrique Barboza { 1797ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 1798fd38804bSDaniel Henrique Barboza return !QTAILQ_EMPTY(&spapr->pending_events); 1799fd38804bSDaniel Henrique Barboza } 1800fd38804bSDaniel Henrique Barboza 1801fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_event_entry = { 1802fd38804bSDaniel Henrique Barboza .name = "spapr_event_log_entry", 1803fd38804bSDaniel Henrique Barboza .version_id = 1, 1804fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1805fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 1806ce2918cbSDavid Gibson VMSTATE_UINT32(summary, SpaprEventLogEntry), 1807ce2918cbSDavid Gibson VMSTATE_UINT32(extended_length, SpaprEventLogEntry), 1808ce2918cbSDavid Gibson VMSTATE_VBUFFER_ALLOC_UINT32(extended_log, SpaprEventLogEntry, 0, 18095341258eSDavid Gibson NULL, extended_length), 1810fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1811fd38804bSDaniel Henrique Barboza }, 1812fd38804bSDaniel Henrique Barboza }; 1813fd38804bSDaniel Henrique Barboza 1814fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_pending_events = { 1815fd38804bSDaniel Henrique Barboza .name = "spapr_pending_events", 1816fd38804bSDaniel Henrique Barboza .version_id = 1, 1817fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1818fd38804bSDaniel Henrique Barboza .needed = spapr_pending_events_needed, 1819fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 1820ce2918cbSDavid Gibson VMSTATE_QTAILQ_V(pending_events, SpaprMachineState, 1, 1821ce2918cbSDavid Gibson vmstate_spapr_event_entry, SpaprEventLogEntry, next), 1822fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1823fd38804bSDaniel Henrique Barboza }, 1824fd38804bSDaniel Henrique Barboza }; 1825fd38804bSDaniel Henrique Barboza 182662ef3760SMichael Roth static bool spapr_ov5_cas_needed(void *opaque) 182762ef3760SMichael Roth { 1828ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 1829ce2918cbSDavid Gibson SpaprOptionVector *ov5_mask = spapr_ovec_new(); 183062ef3760SMichael Roth bool cas_needed; 183162ef3760SMichael Roth 1832ce2918cbSDavid Gibson /* Prior to the introduction of SpaprOptionVector, we had two option 183362ef3760SMichael Roth * vectors we dealt with: OV5_FORM1_AFFINITY, and OV5_DRCONF_MEMORY. 183462ef3760SMichael Roth * Both of these options encode machine topology into the device-tree 183562ef3760SMichael Roth * in such a way that the now-booted OS should still be able to interact 183662ef3760SMichael Roth * appropriately with QEMU regardless of what options were actually 183762ef3760SMichael Roth * negotiatied on the source side. 183862ef3760SMichael Roth * 183962ef3760SMichael Roth * As such, we can avoid migrating the CAS-negotiated options if these 184062ef3760SMichael Roth * are the only options available on the current machine/platform. 184162ef3760SMichael Roth * Since these are the only options available for pseries-2.7 and 184262ef3760SMichael Roth * earlier, this allows us to maintain old->new/new->old migration 184362ef3760SMichael Roth * compatibility. 184462ef3760SMichael Roth * 184562ef3760SMichael Roth * For QEMU 2.8+, there are additional CAS-negotiatable options available 184662ef3760SMichael Roth * via default pseries-2.8 machines and explicit command-line parameters. 184762ef3760SMichael Roth * Some of these options, like OV5_HP_EVT, *do* require QEMU to be aware 184862ef3760SMichael Roth * of the actual CAS-negotiated values to continue working properly. For 184962ef3760SMichael Roth * example, availability of memory unplug depends on knowing whether 185062ef3760SMichael Roth * OV5_HP_EVT was negotiated via CAS. 185162ef3760SMichael Roth * 185262ef3760SMichael Roth * Thus, for any cases where the set of available CAS-negotiatable 185362ef3760SMichael Roth * options extends beyond OV5_FORM1_AFFINITY and OV5_DRCONF_MEMORY, we 1854aef19c04SGreg Kurz * include the CAS-negotiated options in the migration stream, unless 1855aef19c04SGreg Kurz * if they affect boot time behaviour only. 185662ef3760SMichael Roth */ 185762ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_FORM1_AFFINITY); 185862ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_DRCONF_MEMORY); 1859aef19c04SGreg Kurz spapr_ovec_set(ov5_mask, OV5_DRMEM_V2); 186062ef3760SMichael Roth 1861d1d32d62SDavid Gibson /* We need extra information if we have any bits outside the mask 1862d1d32d62SDavid Gibson * defined above */ 1863d1d32d62SDavid Gibson cas_needed = !spapr_ovec_subset(spapr->ov5, ov5_mask); 186462ef3760SMichael Roth 186562ef3760SMichael Roth spapr_ovec_cleanup(ov5_mask); 186662ef3760SMichael Roth 186762ef3760SMichael Roth return cas_needed; 186862ef3760SMichael Roth } 186962ef3760SMichael Roth 187062ef3760SMichael Roth static const VMStateDescription vmstate_spapr_ov5_cas = { 187162ef3760SMichael Roth .name = "spapr_option_vector_ov5_cas", 187262ef3760SMichael Roth .version_id = 1, 187362ef3760SMichael Roth .minimum_version_id = 1, 187462ef3760SMichael Roth .needed = spapr_ov5_cas_needed, 187562ef3760SMichael Roth .fields = (VMStateField[]) { 1876ce2918cbSDavid Gibson VMSTATE_STRUCT_POINTER_V(ov5_cas, SpaprMachineState, 1, 1877ce2918cbSDavid Gibson vmstate_spapr_ovec, SpaprOptionVector), 187862ef3760SMichael Roth VMSTATE_END_OF_LIST() 187962ef3760SMichael Roth }, 188062ef3760SMichael Roth }; 188162ef3760SMichael Roth 18829861bb3eSSuraj Jitindar Singh static bool spapr_patb_entry_needed(void *opaque) 18839861bb3eSSuraj Jitindar Singh { 1884ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 18859861bb3eSSuraj Jitindar Singh 18869861bb3eSSuraj Jitindar Singh return !!spapr->patb_entry; 18879861bb3eSSuraj Jitindar Singh } 18889861bb3eSSuraj Jitindar Singh 18899861bb3eSSuraj Jitindar Singh static const VMStateDescription vmstate_spapr_patb_entry = { 18909861bb3eSSuraj Jitindar Singh .name = "spapr_patb_entry", 18919861bb3eSSuraj Jitindar Singh .version_id = 1, 18929861bb3eSSuraj Jitindar Singh .minimum_version_id = 1, 18939861bb3eSSuraj Jitindar Singh .needed = spapr_patb_entry_needed, 18949861bb3eSSuraj Jitindar Singh .fields = (VMStateField[]) { 1895ce2918cbSDavid Gibson VMSTATE_UINT64(patb_entry, SpaprMachineState), 18969861bb3eSSuraj Jitindar Singh VMSTATE_END_OF_LIST() 18979861bb3eSSuraj Jitindar Singh }, 18989861bb3eSSuraj Jitindar Singh }; 18999861bb3eSSuraj Jitindar Singh 190082cffa2eSCédric Le Goater static bool spapr_irq_map_needed(void *opaque) 190182cffa2eSCédric Le Goater { 1902ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 190382cffa2eSCédric Le Goater 190482cffa2eSCédric Le Goater return spapr->irq_map && !bitmap_empty(spapr->irq_map, spapr->irq_map_nr); 190582cffa2eSCédric Le Goater } 190682cffa2eSCédric Le Goater 190782cffa2eSCédric Le Goater static const VMStateDescription vmstate_spapr_irq_map = { 190882cffa2eSCédric Le Goater .name = "spapr_irq_map", 190982cffa2eSCédric Le Goater .version_id = 1, 191082cffa2eSCédric Le Goater .minimum_version_id = 1, 191182cffa2eSCédric Le Goater .needed = spapr_irq_map_needed, 191282cffa2eSCédric Le Goater .fields = (VMStateField[]) { 1913ce2918cbSDavid Gibson VMSTATE_BITMAP(irq_map, SpaprMachineState, 0, irq_map_nr), 191482cffa2eSCédric Le Goater VMSTATE_END_OF_LIST() 191582cffa2eSCédric Le Goater }, 191682cffa2eSCédric Le Goater }; 191782cffa2eSCédric Le Goater 1918fea35ca4SAlexey Kardashevskiy static bool spapr_dtb_needed(void *opaque) 1919fea35ca4SAlexey Kardashevskiy { 1920ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(opaque); 1921fea35ca4SAlexey Kardashevskiy 1922fea35ca4SAlexey Kardashevskiy return smc->update_dt_enabled; 1923fea35ca4SAlexey Kardashevskiy } 1924fea35ca4SAlexey Kardashevskiy 1925fea35ca4SAlexey Kardashevskiy static int spapr_dtb_pre_load(void *opaque) 1926fea35ca4SAlexey Kardashevskiy { 1927ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 1928fea35ca4SAlexey Kardashevskiy 1929fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob); 1930fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = NULL; 1931fea35ca4SAlexey Kardashevskiy spapr->fdt_size = 0; 1932fea35ca4SAlexey Kardashevskiy 1933fea35ca4SAlexey Kardashevskiy return 0; 1934fea35ca4SAlexey Kardashevskiy } 1935fea35ca4SAlexey Kardashevskiy 1936fea35ca4SAlexey Kardashevskiy static const VMStateDescription vmstate_spapr_dtb = { 1937fea35ca4SAlexey Kardashevskiy .name = "spapr_dtb", 1938fea35ca4SAlexey Kardashevskiy .version_id = 1, 1939fea35ca4SAlexey Kardashevskiy .minimum_version_id = 1, 1940fea35ca4SAlexey Kardashevskiy .needed = spapr_dtb_needed, 1941fea35ca4SAlexey Kardashevskiy .pre_load = spapr_dtb_pre_load, 1942fea35ca4SAlexey Kardashevskiy .fields = (VMStateField[]) { 1943ce2918cbSDavid Gibson VMSTATE_UINT32(fdt_initial_size, SpaprMachineState), 1944ce2918cbSDavid Gibson VMSTATE_UINT32(fdt_size, SpaprMachineState), 1945ce2918cbSDavid Gibson VMSTATE_VBUFFER_ALLOC_UINT32(fdt_blob, SpaprMachineState, 0, NULL, 1946fea35ca4SAlexey Kardashevskiy fdt_size), 1947fea35ca4SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 1948fea35ca4SAlexey Kardashevskiy }, 1949fea35ca4SAlexey Kardashevskiy }; 1950fea35ca4SAlexey Kardashevskiy 19512500fb42SAravinda Prasad static bool spapr_fwnmi_needed(void *opaque) 19522500fb42SAravinda Prasad { 19532500fb42SAravinda Prasad SpaprMachineState *spapr = (SpaprMachineState *)opaque; 19542500fb42SAravinda Prasad 19558af7e1feSNicholas Piggin return spapr->fwnmi_machine_check_addr != -1; 19562500fb42SAravinda Prasad } 19572500fb42SAravinda Prasad 19582500fb42SAravinda Prasad static int spapr_fwnmi_pre_save(void *opaque) 19592500fb42SAravinda Prasad { 19602500fb42SAravinda Prasad SpaprMachineState *spapr = (SpaprMachineState *)opaque; 19612500fb42SAravinda Prasad 19622500fb42SAravinda Prasad /* 19632500fb42SAravinda Prasad * Check if machine check handling is in progress and print a 19642500fb42SAravinda Prasad * warning message. 19652500fb42SAravinda Prasad */ 19668af7e1feSNicholas Piggin if (spapr->fwnmi_machine_check_interlock != -1) { 19672500fb42SAravinda Prasad warn_report("A machine check is being handled during migration. The" 19682500fb42SAravinda Prasad "handler may run and log hardware error on the destination"); 19692500fb42SAravinda Prasad } 19702500fb42SAravinda Prasad 19712500fb42SAravinda Prasad return 0; 19722500fb42SAravinda Prasad } 19732500fb42SAravinda Prasad 19748af7e1feSNicholas Piggin static const VMStateDescription vmstate_spapr_fwnmi = { 19758af7e1feSNicholas Piggin .name = "spapr_fwnmi", 19762500fb42SAravinda Prasad .version_id = 1, 19772500fb42SAravinda Prasad .minimum_version_id = 1, 19782500fb42SAravinda Prasad .needed = spapr_fwnmi_needed, 19792500fb42SAravinda Prasad .pre_save = spapr_fwnmi_pre_save, 19802500fb42SAravinda Prasad .fields = (VMStateField[]) { 1981edfdbf9cSNicholas Piggin VMSTATE_UINT64(fwnmi_system_reset_addr, SpaprMachineState), 19828af7e1feSNicholas Piggin VMSTATE_UINT64(fwnmi_machine_check_addr, SpaprMachineState), 19838af7e1feSNicholas Piggin VMSTATE_INT32(fwnmi_machine_check_interlock, SpaprMachineState), 19842500fb42SAravinda Prasad VMSTATE_END_OF_LIST() 19852500fb42SAravinda Prasad }, 19862500fb42SAravinda Prasad }; 19872500fb42SAravinda Prasad 19884be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = { 19894be21d56SDavid Gibson .name = "spapr", 1990880ae7deSDavid Gibson .version_id = 3, 19914be21d56SDavid Gibson .minimum_version_id = 1, 19924e5fe368SSuraj Jitindar Singh .pre_load = spapr_pre_load, 1993880ae7deSDavid Gibson .post_load = spapr_post_load, 19944e5fe368SSuraj Jitindar Singh .pre_save = spapr_pre_save, 19954be21d56SDavid Gibson .fields = (VMStateField[]) { 1996880ae7deSDavid Gibson /* used to be @next_irq */ 1997880ae7deSDavid Gibson VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4), 19984be21d56SDavid Gibson 19994be21d56SDavid Gibson /* RTC offset */ 2000ce2918cbSDavid Gibson VMSTATE_UINT64_TEST(rtc_offset, SpaprMachineState, version_before_3), 2001880ae7deSDavid Gibson 2002ce2918cbSDavid Gibson VMSTATE_PPC_TIMEBASE_V(tb, SpaprMachineState, 2), 20034be21d56SDavid Gibson VMSTATE_END_OF_LIST() 20044be21d56SDavid Gibson }, 200562ef3760SMichael Roth .subsections = (const VMStateDescription*[]) { 200662ef3760SMichael Roth &vmstate_spapr_ov5_cas, 20079861bb3eSSuraj Jitindar Singh &vmstate_spapr_patb_entry, 2008fd38804bSDaniel Henrique Barboza &vmstate_spapr_pending_events, 20094e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_htm, 20104e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_vsx, 20114e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_dfp, 20128f38eaf8SSuraj Jitindar Singh &vmstate_spapr_cap_cfpc, 201309114fd8SSuraj Jitindar Singh &vmstate_spapr_cap_sbbc, 20144be8d4e7SSuraj Jitindar Singh &vmstate_spapr_cap_ibs, 201564d4a534SDavid Gibson &vmstate_spapr_cap_hpt_maxpagesize, 201682cffa2eSCédric Le Goater &vmstate_spapr_irq_map, 2017b9a477b7SSuraj Jitindar Singh &vmstate_spapr_cap_nested_kvm_hv, 2018fea35ca4SAlexey Kardashevskiy &vmstate_spapr_dtb, 2019c982f5cfSSuraj Jitindar Singh &vmstate_spapr_cap_large_decr, 20208ff43ee4SSuraj Jitindar Singh &vmstate_spapr_cap_ccf_assist, 20219d953ce4SAravinda Prasad &vmstate_spapr_cap_fwnmi, 20228af7e1feSNicholas Piggin &vmstate_spapr_fwnmi, 202362ef3760SMichael Roth NULL 202462ef3760SMichael Roth } 20254be21d56SDavid Gibson }; 20264be21d56SDavid Gibson 20274be21d56SDavid Gibson static int htab_save_setup(QEMUFile *f, void *opaque) 20284be21d56SDavid Gibson { 2029ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 20304be21d56SDavid Gibson 20314be21d56SDavid Gibson /* "Iteration" header */ 20323a384297SBharata B Rao if (!spapr->htab_shift) { 20333a384297SBharata B Rao qemu_put_be32(f, -1); 20343a384297SBharata B Rao } else { 20354be21d56SDavid Gibson qemu_put_be32(f, spapr->htab_shift); 20363a384297SBharata B Rao } 20374be21d56SDavid Gibson 2038e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 2039e68cb8b4SAlexey Kardashevskiy spapr->htab_save_index = 0; 2040e68cb8b4SAlexey Kardashevskiy spapr->htab_first_pass = true; 2041e68cb8b4SAlexey Kardashevskiy } else { 20423a384297SBharata B Rao if (spapr->htab_shift) { 2043e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 20444be21d56SDavid Gibson } 20453a384297SBharata B Rao } 20464be21d56SDavid Gibson 2047e68cb8b4SAlexey Kardashevskiy 2048e68cb8b4SAlexey Kardashevskiy return 0; 2049e68cb8b4SAlexey Kardashevskiy } 20504be21d56SDavid Gibson 2051ce2918cbSDavid Gibson static void htab_save_chunk(QEMUFile *f, SpaprMachineState *spapr, 2052332f7721SGreg Kurz int chunkstart, int n_valid, int n_invalid) 2053332f7721SGreg Kurz { 2054332f7721SGreg Kurz qemu_put_be32(f, chunkstart); 2055332f7721SGreg Kurz qemu_put_be16(f, n_valid); 2056332f7721SGreg Kurz qemu_put_be16(f, n_invalid); 2057332f7721SGreg Kurz qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 2058332f7721SGreg Kurz HASH_PTE_SIZE_64 * n_valid); 2059332f7721SGreg Kurz } 2060332f7721SGreg Kurz 2061332f7721SGreg Kurz static void htab_save_end_marker(QEMUFile *f) 2062332f7721SGreg Kurz { 2063332f7721SGreg Kurz qemu_put_be32(f, 0); 2064332f7721SGreg Kurz qemu_put_be16(f, 0); 2065332f7721SGreg Kurz qemu_put_be16(f, 0); 2066332f7721SGreg Kurz } 2067332f7721SGreg Kurz 2068ce2918cbSDavid Gibson static void htab_save_first_pass(QEMUFile *f, SpaprMachineState *spapr, 20694be21d56SDavid Gibson int64_t max_ns) 20704be21d56SDavid Gibson { 2071378bc217SDavid Gibson bool has_timeout = max_ns != -1; 20724be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 20734be21d56SDavid Gibson int index = spapr->htab_save_index; 2074bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 20754be21d56SDavid Gibson 20764be21d56SDavid Gibson assert(spapr->htab_first_pass); 20774be21d56SDavid Gibson 20784be21d56SDavid Gibson do { 20794be21d56SDavid Gibson int chunkstart; 20804be21d56SDavid Gibson 20814be21d56SDavid Gibson /* Consume invalid HPTEs */ 20824be21d56SDavid Gibson while ((index < htabslots) 20834be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 20844be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 208524ec2863SMarc-André Lureau index++; 20864be21d56SDavid Gibson } 20874be21d56SDavid Gibson 20884be21d56SDavid Gibson /* Consume valid HPTEs */ 20894be21d56SDavid Gibson chunkstart = index; 2090338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 20914be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 20924be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 209324ec2863SMarc-André Lureau index++; 20944be21d56SDavid Gibson } 20954be21d56SDavid Gibson 20964be21d56SDavid Gibson if (index > chunkstart) { 20974be21d56SDavid Gibson int n_valid = index - chunkstart; 20984be21d56SDavid Gibson 2099332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, 0); 21004be21d56SDavid Gibson 2101378bc217SDavid Gibson if (has_timeout && 2102378bc217SDavid Gibson (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 21034be21d56SDavid Gibson break; 21044be21d56SDavid Gibson } 21054be21d56SDavid Gibson } 21064be21d56SDavid Gibson } while ((index < htabslots) && !qemu_file_rate_limit(f)); 21074be21d56SDavid Gibson 21084be21d56SDavid Gibson if (index >= htabslots) { 21094be21d56SDavid Gibson assert(index == htabslots); 21104be21d56SDavid Gibson index = 0; 21114be21d56SDavid Gibson spapr->htab_first_pass = false; 21124be21d56SDavid Gibson } 21134be21d56SDavid Gibson spapr->htab_save_index = index; 21144be21d56SDavid Gibson } 21154be21d56SDavid Gibson 2116ce2918cbSDavid Gibson static int htab_save_later_pass(QEMUFile *f, SpaprMachineState *spapr, 21174be21d56SDavid Gibson int64_t max_ns) 21184be21d56SDavid Gibson { 21194be21d56SDavid Gibson bool final = max_ns < 0; 21204be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 21214be21d56SDavid Gibson int examined = 0, sent = 0; 21224be21d56SDavid Gibson int index = spapr->htab_save_index; 2123bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 21244be21d56SDavid Gibson 21254be21d56SDavid Gibson assert(!spapr->htab_first_pass); 21264be21d56SDavid Gibson 21274be21d56SDavid Gibson do { 21284be21d56SDavid Gibson int chunkstart, invalidstart; 21294be21d56SDavid Gibson 21304be21d56SDavid Gibson /* Consume non-dirty HPTEs */ 21314be21d56SDavid Gibson while ((index < htabslots) 21324be21d56SDavid Gibson && !HPTE_DIRTY(HPTE(spapr->htab, index))) { 21334be21d56SDavid Gibson index++; 21344be21d56SDavid Gibson examined++; 21354be21d56SDavid Gibson } 21364be21d56SDavid Gibson 21374be21d56SDavid Gibson chunkstart = index; 21384be21d56SDavid Gibson /* Consume valid dirty HPTEs */ 2139338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 21404be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 21414be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 21424be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 21434be21d56SDavid Gibson index++; 21444be21d56SDavid Gibson examined++; 21454be21d56SDavid Gibson } 21464be21d56SDavid Gibson 21474be21d56SDavid Gibson invalidstart = index; 21484be21d56SDavid Gibson /* Consume invalid dirty HPTEs */ 2149338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - invalidstart < USHRT_MAX) 21504be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 21514be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 21524be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 21534be21d56SDavid Gibson index++; 21544be21d56SDavid Gibson examined++; 21554be21d56SDavid Gibson } 21564be21d56SDavid Gibson 21574be21d56SDavid Gibson if (index > chunkstart) { 21584be21d56SDavid Gibson int n_valid = invalidstart - chunkstart; 21594be21d56SDavid Gibson int n_invalid = index - invalidstart; 21604be21d56SDavid Gibson 2161332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, n_invalid); 21624be21d56SDavid Gibson sent += index - chunkstart; 21634be21d56SDavid Gibson 2164bc72ad67SAlex Bligh if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 21654be21d56SDavid Gibson break; 21664be21d56SDavid Gibson } 21674be21d56SDavid Gibson } 21684be21d56SDavid Gibson 21694be21d56SDavid Gibson if (examined >= htabslots) { 21704be21d56SDavid Gibson break; 21714be21d56SDavid Gibson } 21724be21d56SDavid Gibson 21734be21d56SDavid Gibson if (index >= htabslots) { 21744be21d56SDavid Gibson assert(index == htabslots); 21754be21d56SDavid Gibson index = 0; 21764be21d56SDavid Gibson } 21774be21d56SDavid Gibson } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final)); 21784be21d56SDavid Gibson 21794be21d56SDavid Gibson if (index >= htabslots) { 21804be21d56SDavid Gibson assert(index == htabslots); 21814be21d56SDavid Gibson index = 0; 21824be21d56SDavid Gibson } 21834be21d56SDavid Gibson 21844be21d56SDavid Gibson spapr->htab_save_index = index; 21854be21d56SDavid Gibson 2186e68cb8b4SAlexey Kardashevskiy return (examined >= htabslots) && (sent == 0) ? 1 : 0; 21874be21d56SDavid Gibson } 21884be21d56SDavid Gibson 2189e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS 5000000 /* 5 ms */ 2190e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE 2048 2191e68cb8b4SAlexey Kardashevskiy 21924be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque) 21934be21d56SDavid Gibson { 2194ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2195715c5407SDavid Gibson int fd; 2196e68cb8b4SAlexey Kardashevskiy int rc = 0; 21974be21d56SDavid Gibson 21984be21d56SDavid Gibson /* Iteration header */ 21993a384297SBharata B Rao if (!spapr->htab_shift) { 22003a384297SBharata B Rao qemu_put_be32(f, -1); 2201e8cd4247SLaurent Vivier return 1; 22023a384297SBharata B Rao } else { 22034be21d56SDavid Gibson qemu_put_be32(f, 0); 22043a384297SBharata B Rao } 22054be21d56SDavid Gibson 2206e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2207e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2208e68cb8b4SAlexey Kardashevskiy 2209715c5407SDavid Gibson fd = get_htab_fd(spapr); 2210715c5407SDavid Gibson if (fd < 0) { 2211715c5407SDavid Gibson return fd; 221201a57972SSamuel Mendoza-Jonas } 221301a57972SSamuel Mendoza-Jonas 2214715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); 2215e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2216e68cb8b4SAlexey Kardashevskiy return rc; 2217e68cb8b4SAlexey Kardashevskiy } 2218e68cb8b4SAlexey Kardashevskiy } else if (spapr->htab_first_pass) { 22194be21d56SDavid Gibson htab_save_first_pass(f, spapr, MAX_ITERATION_NS); 22204be21d56SDavid Gibson } else { 2221e68cb8b4SAlexey Kardashevskiy rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS); 22224be21d56SDavid Gibson } 22234be21d56SDavid Gibson 2224332f7721SGreg Kurz htab_save_end_marker(f); 22254be21d56SDavid Gibson 2226e68cb8b4SAlexey Kardashevskiy return rc; 22274be21d56SDavid Gibson } 22284be21d56SDavid Gibson 22294be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque) 22304be21d56SDavid Gibson { 2231ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2232715c5407SDavid Gibson int fd; 22334be21d56SDavid Gibson 22344be21d56SDavid Gibson /* Iteration header */ 22353a384297SBharata B Rao if (!spapr->htab_shift) { 22363a384297SBharata B Rao qemu_put_be32(f, -1); 22373a384297SBharata B Rao return 0; 22383a384297SBharata B Rao } else { 22394be21d56SDavid Gibson qemu_put_be32(f, 0); 22403a384297SBharata B Rao } 22414be21d56SDavid Gibson 2242e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2243e68cb8b4SAlexey Kardashevskiy int rc; 2244e68cb8b4SAlexey Kardashevskiy 2245e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2246e68cb8b4SAlexey Kardashevskiy 2247715c5407SDavid Gibson fd = get_htab_fd(spapr); 2248715c5407SDavid Gibson if (fd < 0) { 2249715c5407SDavid Gibson return fd; 225001a57972SSamuel Mendoza-Jonas } 225101a57972SSamuel Mendoza-Jonas 2252715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1); 2253e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2254e68cb8b4SAlexey Kardashevskiy return rc; 2255e68cb8b4SAlexey Kardashevskiy } 2256e68cb8b4SAlexey Kardashevskiy } else { 2257378bc217SDavid Gibson if (spapr->htab_first_pass) { 2258378bc217SDavid Gibson htab_save_first_pass(f, spapr, -1); 2259378bc217SDavid Gibson } 22604be21d56SDavid Gibson htab_save_later_pass(f, spapr, -1); 2261e68cb8b4SAlexey Kardashevskiy } 22624be21d56SDavid Gibson 22634be21d56SDavid Gibson /* End marker */ 2264332f7721SGreg Kurz htab_save_end_marker(f); 22654be21d56SDavid Gibson 22664be21d56SDavid Gibson return 0; 22674be21d56SDavid Gibson } 22684be21d56SDavid Gibson 22694be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id) 22704be21d56SDavid Gibson { 2271ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 22724be21d56SDavid Gibson uint32_t section_hdr; 2273e68cb8b4SAlexey Kardashevskiy int fd = -1; 227414b0d748SGreg Kurz Error *local_err = NULL; 22754be21d56SDavid Gibson 22764be21d56SDavid Gibson if (version_id < 1 || version_id > 1) { 227798a5d100SDavid Gibson error_report("htab_load() bad version"); 22784be21d56SDavid Gibson return -EINVAL; 22794be21d56SDavid Gibson } 22804be21d56SDavid Gibson 22814be21d56SDavid Gibson section_hdr = qemu_get_be32(f); 22824be21d56SDavid Gibson 22833a384297SBharata B Rao if (section_hdr == -1) { 22843a384297SBharata B Rao spapr_free_hpt(spapr); 22853a384297SBharata B Rao return 0; 22863a384297SBharata B Rao } 22873a384297SBharata B Rao 22884be21d56SDavid Gibson if (section_hdr) { 2289a4e3a7c0SGreg Kurz int ret; 2290a4e3a7c0SGreg Kurz 2291c5f54f3eSDavid Gibson /* First section gives the htab size */ 2292a4e3a7c0SGreg Kurz ret = spapr_reallocate_hpt(spapr, section_hdr, &local_err); 2293a4e3a7c0SGreg Kurz if (ret < 0) { 2294c5f54f3eSDavid Gibson error_report_err(local_err); 2295a4e3a7c0SGreg Kurz return ret; 22964be21d56SDavid Gibson } 22974be21d56SDavid Gibson return 0; 22984be21d56SDavid Gibson } 22994be21d56SDavid Gibson 2300e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2301e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2302e68cb8b4SAlexey Kardashevskiy 230314b0d748SGreg Kurz fd = kvmppc_get_htab_fd(true, 0, &local_err); 2304e68cb8b4SAlexey Kardashevskiy if (fd < 0) { 230514b0d748SGreg Kurz error_report_err(local_err); 230682be8e73SGreg Kurz return fd; 2307e68cb8b4SAlexey Kardashevskiy } 2308e68cb8b4SAlexey Kardashevskiy } 2309e68cb8b4SAlexey Kardashevskiy 23104be21d56SDavid Gibson while (true) { 23114be21d56SDavid Gibson uint32_t index; 23124be21d56SDavid Gibson uint16_t n_valid, n_invalid; 23134be21d56SDavid Gibson 23144be21d56SDavid Gibson index = qemu_get_be32(f); 23154be21d56SDavid Gibson n_valid = qemu_get_be16(f); 23164be21d56SDavid Gibson n_invalid = qemu_get_be16(f); 23174be21d56SDavid Gibson 23184be21d56SDavid Gibson if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) { 23194be21d56SDavid Gibson /* End of Stream */ 23204be21d56SDavid Gibson break; 23214be21d56SDavid Gibson } 23224be21d56SDavid Gibson 2323e68cb8b4SAlexey Kardashevskiy if ((index + n_valid + n_invalid) > 23244be21d56SDavid Gibson (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) { 23254be21d56SDavid Gibson /* Bad index in stream */ 232698a5d100SDavid Gibson error_report( 232798a5d100SDavid Gibson "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)", 232898a5d100SDavid Gibson index, n_valid, n_invalid, spapr->htab_shift); 23294be21d56SDavid Gibson return -EINVAL; 23304be21d56SDavid Gibson } 23314be21d56SDavid Gibson 2332e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 23334be21d56SDavid Gibson if (n_valid) { 23344be21d56SDavid Gibson qemu_get_buffer(f, HPTE(spapr->htab, index), 23354be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 23364be21d56SDavid Gibson } 23374be21d56SDavid Gibson if (n_invalid) { 23384be21d56SDavid Gibson memset(HPTE(spapr->htab, index + n_valid), 0, 23394be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_invalid); 23404be21d56SDavid Gibson } 2341e68cb8b4SAlexey Kardashevskiy } else { 2342e68cb8b4SAlexey Kardashevskiy int rc; 2343e68cb8b4SAlexey Kardashevskiy 2344e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2345e68cb8b4SAlexey Kardashevskiy 23460a06e4d6SGreg Kurz rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid, 23470a06e4d6SGreg Kurz &local_err); 2348e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 23490a06e4d6SGreg Kurz error_report_err(local_err); 2350e68cb8b4SAlexey Kardashevskiy return rc; 2351e68cb8b4SAlexey Kardashevskiy } 2352e68cb8b4SAlexey Kardashevskiy } 2353e68cb8b4SAlexey Kardashevskiy } 2354e68cb8b4SAlexey Kardashevskiy 2355e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2356e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2357e68cb8b4SAlexey Kardashevskiy close(fd); 23584be21d56SDavid Gibson } 23594be21d56SDavid Gibson 23604be21d56SDavid Gibson return 0; 23614be21d56SDavid Gibson } 23624be21d56SDavid Gibson 236370f794fcSJuan Quintela static void htab_save_cleanup(void *opaque) 2364c573fc03SThomas Huth { 2365ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2366c573fc03SThomas Huth 2367c573fc03SThomas Huth close_htab_fd(spapr); 2368c573fc03SThomas Huth } 2369c573fc03SThomas Huth 23704be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = { 23719907e842SJuan Quintela .save_setup = htab_save_setup, 23724be21d56SDavid Gibson .save_live_iterate = htab_save_iterate, 2373a3e06c3dSDr. David Alan Gilbert .save_live_complete_precopy = htab_save_complete, 237470f794fcSJuan Quintela .save_cleanup = htab_save_cleanup, 23754be21d56SDavid Gibson .load_state = htab_load, 23764be21d56SDavid Gibson }; 23774be21d56SDavid Gibson 23785b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device, 23795b2128d2SAlexander Graf Error **errp) 23805b2128d2SAlexander Graf { 2381c86c1affSDaniel Henrique Barboza MachineState *machine = MACHINE(opaque); 23825b2128d2SAlexander Graf machine->boot_order = g_strdup(boot_device); 23835b2128d2SAlexander Graf } 23845b2128d2SAlexander Graf 2385ce2918cbSDavid Gibson static void spapr_create_lmb_dr_connectors(SpaprMachineState *spapr) 2386224245bfSDavid Gibson { 2387224245bfSDavid Gibson MachineState *machine = MACHINE(spapr); 2388224245bfSDavid Gibson uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 2389e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 2390224245bfSDavid Gibson int i; 2391224245bfSDavid Gibson 2392224245bfSDavid Gibson for (i = 0; i < nr_lmbs; i++) { 2393224245bfSDavid Gibson uint64_t addr; 2394224245bfSDavid Gibson 2395b0c14ec4SDavid Hildenbrand addr = i * lmb_size + machine->device_memory->base; 23966caf3ac6SDavid Gibson spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_LMB, 2397224245bfSDavid Gibson addr / lmb_size); 2398224245bfSDavid Gibson } 2399224245bfSDavid Gibson } 2400224245bfSDavid Gibson 2401224245bfSDavid Gibson /* 2402224245bfSDavid Gibson * If RAM size, maxmem size and individual node mem sizes aren't aligned 2403224245bfSDavid Gibson * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest 2404224245bfSDavid Gibson * since we can't support such unaligned sizes with DRCONF_MEMORY. 2405224245bfSDavid Gibson */ 24067c150d6fSDavid Gibson static void spapr_validate_node_memory(MachineState *machine, Error **errp) 2407224245bfSDavid Gibson { 2408224245bfSDavid Gibson int i; 2409224245bfSDavid Gibson 24107c150d6fSDavid Gibson if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) { 24117c150d6fSDavid Gibson error_setg(errp, "Memory size 0x" RAM_ADDR_FMT 2412ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 24137c150d6fSDavid Gibson machine->ram_size, 2414d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 24157c150d6fSDavid Gibson return; 24167c150d6fSDavid Gibson } 24177c150d6fSDavid Gibson 24187c150d6fSDavid Gibson if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) { 24197c150d6fSDavid Gibson error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT 2420ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 24217c150d6fSDavid Gibson machine->ram_size, 2422d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 24237c150d6fSDavid Gibson return; 2424224245bfSDavid Gibson } 2425224245bfSDavid Gibson 2426aa570207STao Xu for (i = 0; i < machine->numa_state->num_nodes; i++) { 24277e721e7bSTao Xu if (machine->numa_state->nodes[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) { 24287c150d6fSDavid Gibson error_setg(errp, 24297c150d6fSDavid Gibson "Node %d memory size 0x%" PRIx64 2430ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 24317e721e7bSTao Xu i, machine->numa_state->nodes[i].node_mem, 2432d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 24337c150d6fSDavid Gibson return; 2434224245bfSDavid Gibson } 2435224245bfSDavid Gibson } 2436224245bfSDavid Gibson } 2437224245bfSDavid Gibson 2438535455fdSIgor Mammedov /* find cpu slot in machine->possible_cpus by core_id */ 2439535455fdSIgor Mammedov static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx) 2440535455fdSIgor Mammedov { 2441fe6b6346SLike Xu int index = id / ms->smp.threads; 2442535455fdSIgor Mammedov 2443535455fdSIgor Mammedov if (index >= ms->possible_cpus->len) { 2444535455fdSIgor Mammedov return NULL; 2445535455fdSIgor Mammedov } 2446535455fdSIgor Mammedov if (idx) { 2447535455fdSIgor Mammedov *idx = index; 2448535455fdSIgor Mammedov } 2449535455fdSIgor Mammedov return &ms->possible_cpus->cpus[index]; 2450535455fdSIgor Mammedov } 2451535455fdSIgor Mammedov 2452ce2918cbSDavid Gibson static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp) 2453fa98fbfcSSam Bobroff { 2454fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 245529cb4187SGreg Kurz SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 2456fa98fbfcSSam Bobroff Error *local_err = NULL; 2457fa98fbfcSSam Bobroff bool vsmt_user = !!spapr->vsmt; 2458fa98fbfcSSam Bobroff int kvm_smt = kvmppc_smt_threads(); 2459fa98fbfcSSam Bobroff int ret; 2460fe6b6346SLike Xu unsigned int smp_threads = ms->smp.threads; 2461fa98fbfcSSam Bobroff 2462fa98fbfcSSam Bobroff if (!kvm_enabled() && (smp_threads > 1)) { 2463dcfe4805SMarkus Armbruster error_setg(errp, "TCG cannot support more than 1 thread/core " 2464fa98fbfcSSam Bobroff "on a pseries machine"); 2465dcfe4805SMarkus Armbruster return; 2466fa98fbfcSSam Bobroff } 2467fa98fbfcSSam Bobroff if (!is_power_of_2(smp_threads)) { 2468dcfe4805SMarkus Armbruster error_setg(errp, "Cannot support %d threads/core on a pseries " 2469fa98fbfcSSam Bobroff "machine because it must be a power of 2", smp_threads); 2470dcfe4805SMarkus Armbruster return; 2471fa98fbfcSSam Bobroff } 2472fa98fbfcSSam Bobroff 2473fa98fbfcSSam Bobroff /* Detemine the VSMT mode to use: */ 2474fa98fbfcSSam Bobroff if (vsmt_user) { 2475fa98fbfcSSam Bobroff if (spapr->vsmt < smp_threads) { 2476dcfe4805SMarkus Armbruster error_setg(errp, "Cannot support VSMT mode %d" 2477fa98fbfcSSam Bobroff " because it must be >= threads/core (%d)", 2478fa98fbfcSSam Bobroff spapr->vsmt, smp_threads); 2479dcfe4805SMarkus Armbruster return; 2480fa98fbfcSSam Bobroff } 2481fa98fbfcSSam Bobroff /* In this case, spapr->vsmt has been set by the command line */ 248229cb4187SGreg Kurz } else if (!smc->smp_threads_vsmt) { 24838904e5a7SDavid Gibson /* 24848904e5a7SDavid Gibson * Default VSMT value is tricky, because we need it to be as 24858904e5a7SDavid Gibson * consistent as possible (for migration), but this requires 24868904e5a7SDavid Gibson * changing it for at least some existing cases. We pick 8 as 24878904e5a7SDavid Gibson * the value that we'd get with KVM on POWER8, the 24888904e5a7SDavid Gibson * overwhelmingly common case in production systems. 24898904e5a7SDavid Gibson */ 24904ad64cbdSLaurent Vivier spapr->vsmt = MAX(8, smp_threads); 249129cb4187SGreg Kurz } else { 249229cb4187SGreg Kurz spapr->vsmt = smp_threads; 2493fa98fbfcSSam Bobroff } 2494fa98fbfcSSam Bobroff 2495fa98fbfcSSam Bobroff /* KVM: If necessary, set the SMT mode: */ 2496fa98fbfcSSam Bobroff if (kvm_enabled() && (spapr->vsmt != kvm_smt)) { 2497fa98fbfcSSam Bobroff ret = kvmppc_set_smt_threads(spapr->vsmt); 2498fa98fbfcSSam Bobroff if (ret) { 24991f20f2e0SDavid Gibson /* Looks like KVM isn't able to change VSMT mode */ 2500fa98fbfcSSam Bobroff error_setg(&local_err, 2501fa98fbfcSSam Bobroff "Failed to set KVM's VSMT mode to %d (errno %d)", 2502fa98fbfcSSam Bobroff spapr->vsmt, ret); 25031f20f2e0SDavid Gibson /* We can live with that if the default one is big enough 25041f20f2e0SDavid Gibson * for the number of threads, and a submultiple of the one 25051f20f2e0SDavid Gibson * we want. In this case we'll waste some vcpu ids, but 25061f20f2e0SDavid Gibson * behaviour will be correct */ 25071f20f2e0SDavid Gibson if ((kvm_smt >= smp_threads) && ((spapr->vsmt % kvm_smt) == 0)) { 25081f20f2e0SDavid Gibson warn_report_err(local_err); 25091f20f2e0SDavid Gibson } else { 2510fa98fbfcSSam Bobroff if (!vsmt_user) { 25111f20f2e0SDavid Gibson error_append_hint(&local_err, 25121f20f2e0SDavid Gibson "On PPC, a VM with %d threads/core" 25131f20f2e0SDavid Gibson " on a host with %d threads/core" 25141f20f2e0SDavid Gibson " requires the use of VSMT mode %d.\n", 2515fa98fbfcSSam Bobroff smp_threads, kvm_smt, spapr->vsmt); 2516fa98fbfcSSam Bobroff } 2517cdcca22aSVladimir Sementsov-Ogievskiy kvmppc_error_append_smt_possible_hint(&local_err); 2518dcfe4805SMarkus Armbruster error_propagate(errp, local_err); 2519fa98fbfcSSam Bobroff } 2520fa98fbfcSSam Bobroff } 25211f20f2e0SDavid Gibson } 2522fa98fbfcSSam Bobroff /* else TCG: nothing to do currently */ 2523fa98fbfcSSam Bobroff } 2524fa98fbfcSSam Bobroff 2525ce2918cbSDavid Gibson static void spapr_init_cpus(SpaprMachineState *spapr) 25261a5008fcSGreg Kurz { 25271a5008fcSGreg Kurz MachineState *machine = MACHINE(spapr); 25281a5008fcSGreg Kurz MachineClass *mc = MACHINE_GET_CLASS(machine); 2529ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 25301a5008fcSGreg Kurz const char *type = spapr_get_cpu_core_type(machine->cpu_type); 25311a5008fcSGreg Kurz const CPUArchIdList *possible_cpus; 2532fe6b6346SLike Xu unsigned int smp_cpus = machine->smp.cpus; 2533fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 2534fe6b6346SLike Xu unsigned int max_cpus = machine->smp.max_cpus; 25351a5008fcSGreg Kurz int boot_cores_nr = smp_cpus / smp_threads; 25361a5008fcSGreg Kurz int i; 25371a5008fcSGreg Kurz 25381a5008fcSGreg Kurz possible_cpus = mc->possible_cpu_arch_ids(machine); 25391a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 25401a5008fcSGreg Kurz if (smp_cpus % smp_threads) { 25411a5008fcSGreg Kurz error_report("smp_cpus (%u) must be multiple of threads (%u)", 25421a5008fcSGreg Kurz smp_cpus, smp_threads); 25431a5008fcSGreg Kurz exit(1); 25441a5008fcSGreg Kurz } 25451a5008fcSGreg Kurz if (max_cpus % smp_threads) { 25461a5008fcSGreg Kurz error_report("max_cpus (%u) must be multiple of threads (%u)", 25471a5008fcSGreg Kurz max_cpus, smp_threads); 25481a5008fcSGreg Kurz exit(1); 25491a5008fcSGreg Kurz } 25501a5008fcSGreg Kurz } else { 25511a5008fcSGreg Kurz if (max_cpus != smp_cpus) { 25521a5008fcSGreg Kurz error_report("This machine version does not support CPU hotplug"); 25531a5008fcSGreg Kurz exit(1); 25541a5008fcSGreg Kurz } 25551a5008fcSGreg Kurz boot_cores_nr = possible_cpus->len; 25561a5008fcSGreg Kurz } 25571a5008fcSGreg Kurz 25581a5008fcSGreg Kurz if (smc->pre_2_10_has_unused_icps) { 25591a5008fcSGreg Kurz int i; 25601a5008fcSGreg Kurz 25611a518e76SCédric Le Goater for (i = 0; i < spapr_max_server_number(spapr); i++) { 25621a5008fcSGreg Kurz /* Dummy entries get deregistered when real ICPState objects 25631a5008fcSGreg Kurz * are registered during CPU core hotplug. 25641a5008fcSGreg Kurz */ 25651a5008fcSGreg Kurz pre_2_10_vmstate_register_dummy_icp(i); 25661a5008fcSGreg Kurz } 25671a5008fcSGreg Kurz } 25681a5008fcSGreg Kurz 25691a5008fcSGreg Kurz for (i = 0; i < possible_cpus->len; i++) { 25701a5008fcSGreg Kurz int core_id = i * smp_threads; 25711a5008fcSGreg Kurz 25721a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 25731a5008fcSGreg Kurz spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU, 25741a5008fcSGreg Kurz spapr_vcpu_id(spapr, core_id)); 25751a5008fcSGreg Kurz } 25761a5008fcSGreg Kurz 25771a5008fcSGreg Kurz if (i < boot_cores_nr) { 25781a5008fcSGreg Kurz Object *core = object_new(type); 25791a5008fcSGreg Kurz int nr_threads = smp_threads; 25801a5008fcSGreg Kurz 25811a5008fcSGreg Kurz /* Handle the partially filled core for older machine types */ 25821a5008fcSGreg Kurz if ((i + 1) * smp_threads >= smp_cpus) { 25831a5008fcSGreg Kurz nr_threads = smp_cpus - i * smp_threads; 25841a5008fcSGreg Kurz } 25851a5008fcSGreg Kurz 25865325cc34SMarkus Armbruster object_property_set_int(core, "nr-threads", nr_threads, 25871a5008fcSGreg Kurz &error_fatal); 25885325cc34SMarkus Armbruster object_property_set_int(core, CPU_CORE_PROP_CORE_ID, core_id, 25891a5008fcSGreg Kurz &error_fatal); 2590ce189ab2SMarkus Armbruster qdev_realize(DEVICE(core), NULL, &error_fatal); 2591ecda255eSSam Bobroff 2592ecda255eSSam Bobroff object_unref(core); 25931a5008fcSGreg Kurz } 25941a5008fcSGreg Kurz } 25951a5008fcSGreg Kurz } 25961a5008fcSGreg Kurz 2597999c9cafSGreg Kurz static PCIHostState *spapr_create_default_phb(void) 2598999c9cafSGreg Kurz { 2599999c9cafSGreg Kurz DeviceState *dev; 2600999c9cafSGreg Kurz 26013e80f690SMarkus Armbruster dev = qdev_new(TYPE_SPAPR_PCI_HOST_BRIDGE); 2602999c9cafSGreg Kurz qdev_prop_set_uint32(dev, "index", 0); 26033c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); 2604999c9cafSGreg Kurz 2605999c9cafSGreg Kurz return PCI_HOST_BRIDGE(dev); 2606999c9cafSGreg Kurz } 2607999c9cafSGreg Kurz 2608425f0b7aSDavid Gibson static hwaddr spapr_rma_size(SpaprMachineState *spapr, Error **errp) 2609425f0b7aSDavid Gibson { 2610425f0b7aSDavid Gibson MachineState *machine = MACHINE(spapr); 2611425f0b7aSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 2612425f0b7aSDavid Gibson hwaddr rma_size = machine->ram_size; 2613425f0b7aSDavid Gibson hwaddr node0_size = spapr_node0_size(machine); 2614425f0b7aSDavid Gibson 2615425f0b7aSDavid Gibson /* RMA has to fit in the first NUMA node */ 2616425f0b7aSDavid Gibson rma_size = MIN(rma_size, node0_size); 2617425f0b7aSDavid Gibson 2618425f0b7aSDavid Gibson /* 2619425f0b7aSDavid Gibson * VRMA access is via a special 1TiB SLB mapping, so the RMA can 2620425f0b7aSDavid Gibson * never exceed that 2621425f0b7aSDavid Gibson */ 2622425f0b7aSDavid Gibson rma_size = MIN(rma_size, 1 * TiB); 2623425f0b7aSDavid Gibson 2624425f0b7aSDavid Gibson /* 2625425f0b7aSDavid Gibson * Clamp the RMA size based on machine type. This is for 2626425f0b7aSDavid Gibson * migration compatibility with older qemu versions, which limited 2627425f0b7aSDavid Gibson * the RMA size for complicated and mostly bad reasons. 2628425f0b7aSDavid Gibson */ 2629425f0b7aSDavid Gibson if (smc->rma_limit) { 2630425f0b7aSDavid Gibson rma_size = MIN(rma_size, smc->rma_limit); 2631425f0b7aSDavid Gibson } 2632425f0b7aSDavid Gibson 2633425f0b7aSDavid Gibson if (rma_size < MIN_RMA_SLOF) { 2634425f0b7aSDavid Gibson error_setg(errp, 2635425f0b7aSDavid Gibson "pSeries SLOF firmware requires >= %" HWADDR_PRIx 2636425f0b7aSDavid Gibson "ldMiB guest RMA (Real Mode Area memory)", 2637425f0b7aSDavid Gibson MIN_RMA_SLOF / MiB); 2638425f0b7aSDavid Gibson return 0; 2639425f0b7aSDavid Gibson } 2640425f0b7aSDavid Gibson 2641425f0b7aSDavid Gibson return rma_size; 2642425f0b7aSDavid Gibson } 2643425f0b7aSDavid Gibson 2644ce316b51SGreg Kurz static void spapr_create_nvdimm_dr_connectors(SpaprMachineState *spapr) 2645ce316b51SGreg Kurz { 2646ce316b51SGreg Kurz MachineState *machine = MACHINE(spapr); 2647ce316b51SGreg Kurz int i; 2648ce316b51SGreg Kurz 2649ce316b51SGreg Kurz for (i = 0; i < machine->ram_slots; i++) { 2650ce316b51SGreg Kurz spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_PMEM, i); 2651ce316b51SGreg Kurz } 2652ce316b51SGreg Kurz } 2653ce316b51SGreg Kurz 265453018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */ 2655bcb5ce08SDavid Gibson static void spapr_machine_init(MachineState *machine) 265653018216SPaolo Bonzini { 2657ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(machine); 2658ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 2659ee3a71e3SShivaprasad G Bhat MachineClass *mc = MACHINE_GET_CLASS(machine); 2660*cd7b9498SPaolo Bonzini const char *bios_name = machine->firmware ?: FW_FILE_NAME; 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(); 2666b7d1f77aSBenjamin Herrenschmidt long load_limit, fw_size; 266753018216SPaolo Bonzini char *filename; 266830f4b05bSDavid Gibson Error *resize_hpt_err = NULL; 266953018216SPaolo Bonzini 2670226419d6SMichael S. Tsirkin msi_nonbroken = true; 267153018216SPaolo Bonzini 267253018216SPaolo Bonzini QLIST_INIT(&spapr->phbs); 26730cffce56SDavid Gibson QTAILQ_INIT(&spapr->pending_dimm_unplugs); 267453018216SPaolo Bonzini 26759f6edd06SDavid Gibson /* Determine capabilities to run with */ 26769f6edd06SDavid Gibson spapr_caps_init(spapr); 26779f6edd06SDavid Gibson 267830f4b05bSDavid Gibson kvmppc_check_papr_resize_hpt(&resize_hpt_err); 267930f4b05bSDavid Gibson if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) { 268030f4b05bSDavid Gibson /* 268130f4b05bSDavid Gibson * If the user explicitly requested a mode we should either 268230f4b05bSDavid Gibson * supply it, or fail completely (which we do below). But if 268330f4b05bSDavid Gibson * it's not set explicitly, we reset our mode to something 268430f4b05bSDavid Gibson * that works 268530f4b05bSDavid Gibson */ 268630f4b05bSDavid Gibson if (resize_hpt_err) { 268730f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 268830f4b05bSDavid Gibson error_free(resize_hpt_err); 268930f4b05bSDavid Gibson resize_hpt_err = NULL; 269030f4b05bSDavid Gibson } else { 269130f4b05bSDavid Gibson spapr->resize_hpt = smc->resize_hpt_default; 269230f4b05bSDavid Gibson } 269330f4b05bSDavid Gibson } 269430f4b05bSDavid Gibson 269530f4b05bSDavid Gibson assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT); 269630f4b05bSDavid Gibson 269730f4b05bSDavid Gibson if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && resize_hpt_err) { 269830f4b05bSDavid Gibson /* 269930f4b05bSDavid Gibson * User requested HPT resize, but this host can't supply it. Bail out 270030f4b05bSDavid Gibson */ 270130f4b05bSDavid Gibson error_report_err(resize_hpt_err); 270230f4b05bSDavid Gibson exit(1); 270330f4b05bSDavid Gibson } 270414963c34SMarkus Armbruster error_free(resize_hpt_err); 270530f4b05bSDavid Gibson 2706425f0b7aSDavid Gibson spapr->rma_size = spapr_rma_size(spapr, &error_fatal); 2707c4177479SAlexey Kardashevskiy 2708b7d1f77aSBenjamin Herrenschmidt /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */ 2709b7d1f77aSBenjamin Herrenschmidt load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; 271053018216SPaolo Bonzini 2711482969d6SCédric Le Goater /* 2712482969d6SCédric Le Goater * VSMT must be set in order to be able to compute VCPU ids, ie to 27131a518e76SCédric Le Goater * call spapr_max_server_number() or spapr_vcpu_id(). 2714482969d6SCédric Le Goater */ 2715482969d6SCédric Le Goater spapr_set_vsmt_mode(spapr, &error_fatal); 2716482969d6SCédric Le Goater 27177b565160SDavid Gibson /* Set up Interrupt Controller before we create the VCPUs */ 2718fab397d8SCédric Le Goater spapr_irq_init(spapr, &error_fatal); 27197b565160SDavid Gibson 2720dc1b5eeeSGreg Kurz /* Set up containers for ibm,client-architecture-support negotiated options 2721dc1b5eeeSGreg Kurz */ 2722facdb8b6SMichael Roth spapr->ov5 = spapr_ovec_new(); 2723facdb8b6SMichael Roth spapr->ov5_cas = spapr_ovec_new(); 2724facdb8b6SMichael Roth 2725224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2726facdb8b6SMichael Roth spapr_ovec_set(spapr->ov5, OV5_DRCONF_MEMORY); 27277c150d6fSDavid Gibson spapr_validate_node_memory(machine, &error_fatal); 2728224245bfSDavid Gibson } 2729224245bfSDavid Gibson 2730417ece33SMichael Roth spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY); 2731417ece33SMichael Roth 2732ffbb1705SMichael Roth /* advertise support for dedicated HP event source to guests */ 2733ffbb1705SMichael Roth if (spapr->use_hotplug_event_source) { 2734ffbb1705SMichael Roth spapr_ovec_set(spapr->ov5, OV5_HP_EVT); 2735ffbb1705SMichael Roth } 2736ffbb1705SMichael Roth 27372772cf6bSDavid Gibson /* advertise support for HPT resizing */ 27382772cf6bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { 27392772cf6bSDavid Gibson spapr_ovec_set(spapr->ov5, OV5_HPT_RESIZE); 27402772cf6bSDavid Gibson } 27412772cf6bSDavid Gibson 2742a324d6f1SBharata B Rao /* advertise support for ibm,dyamic-memory-v2 */ 2743a324d6f1SBharata B Rao spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2); 2744a324d6f1SBharata B Rao 2745db592b5bSCédric Le Goater /* advertise XIVE on POWER9 machines */ 2746ca62823bSDavid Gibson if (spapr->irq->xive) { 2747db592b5bSCédric Le Goater spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT); 2748db592b5bSCédric Le Goater } 2749db592b5bSCédric Le Goater 275053018216SPaolo Bonzini /* init CPUs */ 27510c86d0fdSDavid Gibson spapr_init_cpus(spapr); 275253018216SPaolo Bonzini 275358c46efaSLaurent Vivier /* 275458c46efaSLaurent Vivier * check we don't have a memory-less/cpu-less NUMA node 275558c46efaSLaurent Vivier * Firmware relies on the existing memory/cpu topology to provide the 275658c46efaSLaurent Vivier * NUMA topology to the kernel. 275758c46efaSLaurent Vivier * And the linux kernel needs to know the NUMA topology at start 275858c46efaSLaurent Vivier * to be able to hotplug CPUs later. 275958c46efaSLaurent Vivier */ 276058c46efaSLaurent Vivier if (machine->numa_state->num_nodes) { 276158c46efaSLaurent Vivier for (i = 0; i < machine->numa_state->num_nodes; ++i) { 276258c46efaSLaurent Vivier /* check for memory-less node */ 276358c46efaSLaurent Vivier if (machine->numa_state->nodes[i].node_mem == 0) { 276458c46efaSLaurent Vivier CPUState *cs; 276558c46efaSLaurent Vivier int found = 0; 276658c46efaSLaurent Vivier /* check for cpu-less node */ 276758c46efaSLaurent Vivier CPU_FOREACH(cs) { 276858c46efaSLaurent Vivier PowerPCCPU *cpu = POWERPC_CPU(cs); 276958c46efaSLaurent Vivier if (cpu->node_id == i) { 277058c46efaSLaurent Vivier found = 1; 277158c46efaSLaurent Vivier break; 277258c46efaSLaurent Vivier } 277358c46efaSLaurent Vivier } 277458c46efaSLaurent Vivier /* memory-less and cpu-less node */ 277558c46efaSLaurent Vivier if (!found) { 277658c46efaSLaurent Vivier error_report( 277758c46efaSLaurent Vivier "Memory-less/cpu-less nodes are not supported (node %d)", 277858c46efaSLaurent Vivier i); 277958c46efaSLaurent Vivier exit(1); 278058c46efaSLaurent Vivier } 278158c46efaSLaurent Vivier } 278258c46efaSLaurent Vivier } 278358c46efaSLaurent Vivier 278458c46efaSLaurent Vivier } 278558c46efaSLaurent Vivier 2786db5127b2SDavid Gibson /* 2787db5127b2SDavid Gibson * NVLink2-connected GPU RAM needs to be placed on a separate NUMA node. 2788db5127b2SDavid Gibson * We assign a new numa ID per GPU in spapr_pci_collect_nvgpu() which is 2789db5127b2SDavid Gibson * called from vPHB reset handler so we initialize the counter here. 2790db5127b2SDavid Gibson * If no NUMA is configured from the QEMU side, we start from 1 as GPU RAM 2791db5127b2SDavid Gibson * must be equally distant from any other node. 2792db5127b2SDavid Gibson * The final value of spapr->gpu_numa_id is going to be written to 2793db5127b2SDavid Gibson * max-associativity-domains in spapr_build_fdt(). 2794db5127b2SDavid Gibson */ 2795db5127b2SDavid Gibson spapr->gpu_numa_id = MAX(1, machine->numa_state->num_nodes); 2796db5127b2SDavid Gibson 2797f1aa45ffSDaniel Henrique Barboza /* Init numa_assoc_array */ 2798f1aa45ffSDaniel Henrique Barboza spapr_numa_associativity_init(spapr, machine); 2799f1aa45ffSDaniel Henrique Barboza 28000550b120SGreg Kurz if ((!kvm_enabled() || kvmppc_has_cap_mmu_radix()) && 2801ad99d04cSDavid Gibson ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, 28020550b120SGreg Kurz spapr->max_compat_pvr)) { 2803b4b83312SGreg Kurz spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_300); 28040550b120SGreg Kurz /* KVM and TCG always allow GTSE with radix... */ 28050550b120SGreg Kurz spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE); 28060550b120SGreg Kurz } 28070550b120SGreg Kurz /* ... but not with hash (currently). */ 28080550b120SGreg Kurz 2809026bfd89SDavid Gibson if (kvm_enabled()) { 2810026bfd89SDavid Gibson /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ 2811026bfd89SDavid Gibson kvmppc_enable_logical_ci_hcalls(); 2812ef9971ddSAlexey Kardashevskiy kvmppc_enable_set_mode_hcall(); 28135145ad4fSNathan Whitehorn 28145145ad4fSNathan Whitehorn /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */ 28155145ad4fSNathan Whitehorn kvmppc_enable_clear_ref_mod_hcalls(); 281668f9f708SSuraj Jitindar Singh 281768f9f708SSuraj Jitindar Singh /* Enable H_PAGE_INIT */ 281868f9f708SSuraj Jitindar Singh kvmppc_enable_h_page_init(); 2819026bfd89SDavid Gibson } 2820026bfd89SDavid Gibson 2821ab74e543SIgor Mammedov /* map RAM */ 2822ab74e543SIgor Mammedov memory_region_add_subregion(sysmem, 0, machine->ram); 282353018216SPaolo Bonzini 2824b0c14ec4SDavid Hildenbrand /* always allocate the device memory information */ 2825b0c14ec4SDavid Hildenbrand machine->device_memory = g_malloc0(sizeof(*machine->device_memory)); 2826b0c14ec4SDavid Hildenbrand 28274a1c9cf0SBharata B Rao /* initialize hotplug memory address space */ 28284a1c9cf0SBharata B Rao if (machine->ram_size < machine->maxram_size) { 28290c9269a5SDavid Hildenbrand ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size; 283071c9a3ddSBharata B Rao /* 283171c9a3ddSBharata B Rao * Limit the number of hotpluggable memory slots to half the number 283271c9a3ddSBharata B Rao * slots that KVM supports, leaving the other half for PCI and other 283371c9a3ddSBharata B Rao * devices. However ensure that number of slots doesn't drop below 32. 283471c9a3ddSBharata B Rao */ 283571c9a3ddSBharata B Rao int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 : 283671c9a3ddSBharata B Rao SPAPR_MAX_RAM_SLOTS; 28374a1c9cf0SBharata B Rao 283871c9a3ddSBharata B Rao if (max_memslots < SPAPR_MAX_RAM_SLOTS) { 283971c9a3ddSBharata B Rao max_memslots = SPAPR_MAX_RAM_SLOTS; 284071c9a3ddSBharata B Rao } 284171c9a3ddSBharata B Rao if (machine->ram_slots > max_memslots) { 2842d54e4d76SDavid Gibson error_report("Specified number of memory slots %" 2843d54e4d76SDavid Gibson PRIu64" exceeds max supported %d", 284471c9a3ddSBharata B Rao machine->ram_slots, max_memslots); 2845d54e4d76SDavid Gibson exit(1); 28464a1c9cf0SBharata B Rao } 28474a1c9cf0SBharata B Rao 2848b0c14ec4SDavid Hildenbrand machine->device_memory->base = ROUND_UP(machine->ram_size, 28490c9269a5SDavid Hildenbrand SPAPR_DEVICE_MEM_ALIGN); 2850b0c14ec4SDavid Hildenbrand memory_region_init(&machine->device_memory->mr, OBJECT(spapr), 28510c9269a5SDavid Hildenbrand "device-memory", device_mem_size); 2852b0c14ec4SDavid Hildenbrand memory_region_add_subregion(sysmem, machine->device_memory->base, 2853b0c14ec4SDavid Hildenbrand &machine->device_memory->mr); 28544a1c9cf0SBharata B Rao } 28554a1c9cf0SBharata B Rao 2856224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2857224245bfSDavid Gibson spapr_create_lmb_dr_connectors(spapr); 2858224245bfSDavid Gibson } 2859224245bfSDavid Gibson 28608af7e1feSNicholas Piggin if (spapr_get_cap(spapr, SPAPR_CAP_FWNMI) == SPAPR_CAP_ON) { 28612500fb42SAravinda Prasad /* Create the error string for live migration blocker */ 28622500fb42SAravinda Prasad error_setg(&spapr->fwnmi_migration_blocker, 28632500fb42SAravinda Prasad "A machine check is being handled during migration. The handler" 28642500fb42SAravinda Prasad "may run and log hardware error on the destination"); 28652500fb42SAravinda Prasad } 28662500fb42SAravinda Prasad 2867ee3a71e3SShivaprasad G Bhat if (mc->nvdimm_supported) { 2868ee3a71e3SShivaprasad G Bhat spapr_create_nvdimm_dr_connectors(spapr); 2869ee3a71e3SShivaprasad G Bhat } 2870ee3a71e3SShivaprasad G Bhat 2871ffbb1705SMichael Roth /* Set up RTAS event infrastructure */ 287253018216SPaolo Bonzini spapr_events_init(spapr); 287353018216SPaolo Bonzini 287412f42174SDavid Gibson /* Set up the RTC RTAS interfaces */ 287528df36a1SDavid Gibson spapr_rtc_create(spapr); 287612f42174SDavid Gibson 287753018216SPaolo Bonzini /* Set up VIO bus */ 287853018216SPaolo Bonzini spapr->vio_bus = spapr_vio_bus_init(); 287953018216SPaolo Bonzini 2880b8846a4dSPeter Maydell for (i = 0; i < serial_max_hds(); i++) { 28819bca0edbSPeter Maydell if (serial_hd(i)) { 28829bca0edbSPeter Maydell spapr_vty_create(spapr->vio_bus, serial_hd(i)); 288353018216SPaolo Bonzini } 288453018216SPaolo Bonzini } 288553018216SPaolo Bonzini 288653018216SPaolo Bonzini /* We always have at least the nvram device on VIO */ 288753018216SPaolo Bonzini spapr_create_nvram(spapr); 288853018216SPaolo Bonzini 2889962b6c36SMichael Roth /* 2890962b6c36SMichael Roth * Setup hotplug / dynamic-reconfiguration connectors. top-level 2891962b6c36SMichael Roth * connectors (described in root DT node's "ibm,drc-types" property) 2892962b6c36SMichael Roth * are pre-initialized here. additional child connectors (such as 2893962b6c36SMichael Roth * connectors for a PHBs PCI slots) are added as needed during their 2894962b6c36SMichael Roth * parent's realization. 2895962b6c36SMichael Roth */ 2896962b6c36SMichael Roth if (smc->dr_phb_enabled) { 2897962b6c36SMichael Roth for (i = 0; i < SPAPR_MAX_PHBS; i++) { 2898962b6c36SMichael Roth spapr_dr_connector_new(OBJECT(machine), TYPE_SPAPR_DRC_PHB, i); 2899962b6c36SMichael Roth } 2900962b6c36SMichael Roth } 2901962b6c36SMichael Roth 290253018216SPaolo Bonzini /* Set up PCI */ 290353018216SPaolo Bonzini spapr_pci_rtas_init(); 290453018216SPaolo Bonzini 2905999c9cafSGreg Kurz phb = spapr_create_default_phb(); 290653018216SPaolo Bonzini 290753018216SPaolo Bonzini for (i = 0; i < nb_nics; i++) { 290853018216SPaolo Bonzini NICInfo *nd = &nd_table[i]; 290953018216SPaolo Bonzini 291053018216SPaolo Bonzini if (!nd->model) { 29113c3a4e7aSThomas Huth nd->model = g_strdup("spapr-vlan"); 291253018216SPaolo Bonzini } 291353018216SPaolo Bonzini 29143c3a4e7aSThomas Huth if (g_str_equal(nd->model, "spapr-vlan") || 29153c3a4e7aSThomas Huth g_str_equal(nd->model, "ibmveth")) { 291653018216SPaolo Bonzini spapr_vlan_create(spapr->vio_bus, nd); 291753018216SPaolo Bonzini } else { 291829b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL); 291953018216SPaolo Bonzini } 292053018216SPaolo Bonzini } 292153018216SPaolo Bonzini 292253018216SPaolo Bonzini for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { 292353018216SPaolo Bonzini spapr_vscsi_create(spapr->vio_bus); 292453018216SPaolo Bonzini } 292553018216SPaolo Bonzini 292653018216SPaolo Bonzini /* Graphics */ 292714c6a894SDavid Gibson if (spapr_vga_init(phb->bus, &error_fatal)) { 292853018216SPaolo Bonzini spapr->has_graphics = true; 2929c6e76503SPaolo Bonzini machine->usb |= defaults_enabled() && !machine->usb_disabled; 293053018216SPaolo Bonzini } 293153018216SPaolo Bonzini 29324ee9ced9SMarcel Apfelbaum if (machine->usb) { 293357040d45SThomas Huth if (smc->use_ohci_by_default) { 293453018216SPaolo Bonzini pci_create_simple(phb->bus, -1, "pci-ohci"); 293557040d45SThomas Huth } else { 293657040d45SThomas Huth pci_create_simple(phb->bus, -1, "nec-usb-xhci"); 293757040d45SThomas Huth } 2938c86580b8SMarkus Armbruster 293953018216SPaolo Bonzini if (spapr->has_graphics) { 2940c86580b8SMarkus Armbruster USBBus *usb_bus = usb_bus_find(-1); 2941c86580b8SMarkus Armbruster 2942c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-kbd"); 2943c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-mouse"); 294453018216SPaolo Bonzini } 294553018216SPaolo Bonzini } 294653018216SPaolo Bonzini 294753018216SPaolo Bonzini if (kernel_filename) { 29484366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL, 294987262806SAlexey Kardashevskiy translate_kernel_address, spapr, 2950617160c9SBALATON Zoltan NULL, NULL, NULL, NULL, 1, 2951a19f7fb0SDavid Gibson PPC_ELF_MACHINE, 0, 0); 2952a19f7fb0SDavid Gibson if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) { 29534366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL, 2954617160c9SBALATON Zoltan translate_kernel_address, spapr, 2955617160c9SBALATON Zoltan NULL, NULL, NULL, NULL, 0, 2956617160c9SBALATON Zoltan PPC_ELF_MACHINE, 0, 0); 2957a19f7fb0SDavid Gibson spapr->kernel_le = spapr->kernel_size > 0; 295816457e7fSBenjamin Herrenschmidt } 2959a19f7fb0SDavid Gibson if (spapr->kernel_size < 0) { 2960a19f7fb0SDavid Gibson error_report("error loading %s: %s", kernel_filename, 2961a19f7fb0SDavid Gibson load_elf_strerror(spapr->kernel_size)); 296253018216SPaolo Bonzini exit(1); 296353018216SPaolo Bonzini } 296453018216SPaolo Bonzini 296553018216SPaolo Bonzini /* load initrd */ 296653018216SPaolo Bonzini if (initrd_filename) { 296753018216SPaolo Bonzini /* Try to locate the initrd in the gap between the kernel 296853018216SPaolo Bonzini * and the firmware. Add a bit of space just in case 296953018216SPaolo Bonzini */ 297087262806SAlexey Kardashevskiy spapr->initrd_base = (spapr->kernel_addr + spapr->kernel_size 2971a19f7fb0SDavid Gibson + 0x1ffff) & ~0xffff; 2972a19f7fb0SDavid Gibson spapr->initrd_size = load_image_targphys(initrd_filename, 2973a19f7fb0SDavid Gibson spapr->initrd_base, 2974a19f7fb0SDavid Gibson load_limit 2975a19f7fb0SDavid Gibson - spapr->initrd_base); 2976a19f7fb0SDavid Gibson if (spapr->initrd_size < 0) { 2977d54e4d76SDavid Gibson error_report("could not load initial ram disk '%s'", 297853018216SPaolo Bonzini initrd_filename); 297953018216SPaolo Bonzini exit(1); 298053018216SPaolo Bonzini } 298153018216SPaolo Bonzini } 298253018216SPaolo Bonzini } 298353018216SPaolo Bonzini 29848e7ea787SAndreas Färber filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 29854c56440dSStefan Weil if (!filename) { 298668fea5a0SThomas Huth error_report("Could not find LPAR firmware '%s'", bios_name); 29874c56440dSStefan Weil exit(1); 29884c56440dSStefan Weil } 298953018216SPaolo Bonzini fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); 299068fea5a0SThomas Huth if (fw_size <= 0) { 299168fea5a0SThomas Huth error_report("Could not load LPAR firmware '%s'", filename); 299253018216SPaolo Bonzini exit(1); 299353018216SPaolo Bonzini } 299453018216SPaolo Bonzini g_free(filename); 299553018216SPaolo Bonzini 299628e02042SDavid Gibson /* FIXME: Should register things through the MachineState's qdev 299728e02042SDavid Gibson * interface, this is a legacy from the sPAPREnvironment structure 299828e02042SDavid Gibson * which predated MachineState but had a similar function */ 29994be21d56SDavid Gibson vmstate_register(NULL, 0, &vmstate_spapr, spapr); 30001df2c9a2SPeter Xu register_savevm_live("spapr/htab", VMSTATE_INSTANCE_ID_ANY, 1, 30014be21d56SDavid Gibson &savevm_htab_handlers, spapr); 30024be21d56SDavid Gibson 30039bc6bfdfSMarkus Armbruster qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine)); 3004bb2bdd81SGreg Kurz 30055b2128d2SAlexander Graf qemu_register_boot_set(spapr_boot_set, spapr); 300642043e4fSLaurent Vivier 300793eac7b8SNicholas Piggin /* 300893eac7b8SNicholas Piggin * Nothing needs to be done to resume a suspended guest because 300993eac7b8SNicholas Piggin * suspending does not change the machine state, so no need for 301093eac7b8SNicholas Piggin * a ->wakeup method. 301193eac7b8SNicholas Piggin */ 301293eac7b8SNicholas Piggin qemu_register_wakeup_support(); 301393eac7b8SNicholas Piggin 301442043e4fSLaurent Vivier if (kvm_enabled()) { 30153dc410aeSAlexey Kardashevskiy /* to stop and start vmclock */ 301642043e4fSLaurent Vivier qemu_add_vm_change_state_handler(cpu_ppc_clock_vm_state_change, 301742043e4fSLaurent Vivier &spapr->tb); 30183dc410aeSAlexey Kardashevskiy 30193dc410aeSAlexey Kardashevskiy kvmppc_spapr_enable_inkernel_multitce(); 302042043e4fSLaurent Vivier } 30219ac703acSAravinda Prasad 30228af7e1feSNicholas Piggin qemu_cond_init(&spapr->fwnmi_machine_check_interlock_cond); 302353018216SPaolo Bonzini } 302453018216SPaolo Bonzini 3025dc0ca80eSEric Auger static int spapr_kvm_type(MachineState *machine, const char *vm_type) 3026135a129aSAneesh Kumar K.V { 3027135a129aSAneesh Kumar K.V if (!vm_type) { 3028135a129aSAneesh Kumar K.V return 0; 3029135a129aSAneesh Kumar K.V } 3030135a129aSAneesh Kumar K.V 3031135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "HV")) { 3032135a129aSAneesh Kumar K.V return 1; 3033135a129aSAneesh Kumar K.V } 3034135a129aSAneesh Kumar K.V 3035135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "PR")) { 3036135a129aSAneesh Kumar K.V return 2; 3037135a129aSAneesh Kumar K.V } 3038135a129aSAneesh Kumar K.V 3039135a129aSAneesh Kumar K.V error_report("Unknown kvm-type specified '%s'", vm_type); 3040135a129aSAneesh Kumar K.V exit(1); 3041135a129aSAneesh Kumar K.V } 3042135a129aSAneesh Kumar K.V 304371461b0fSAlexey Kardashevskiy /* 3044627b84f4SGonglei * Implementation of an interface to adjust firmware path 304571461b0fSAlexey Kardashevskiy * for the bootindex property handling. 304671461b0fSAlexey Kardashevskiy */ 304771461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, 304871461b0fSAlexey Kardashevskiy DeviceState *dev) 304971461b0fSAlexey Kardashevskiy { 305071461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \ 305171461b0fSAlexey Kardashevskiy ((type *)object_dynamic_cast(OBJECT(obj), (name))) 305271461b0fSAlexey Kardashevskiy SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); 3053ce2918cbSDavid Gibson SpaprPhbState *phb = CAST(SpaprPhbState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); 3054c4e13492SFelipe Franciosi VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON); 305571461b0fSAlexey Kardashevskiy 305671461b0fSAlexey Kardashevskiy if (d) { 305771461b0fSAlexey Kardashevskiy void *spapr = CAST(void, bus->parent, "spapr-vscsi"); 305871461b0fSAlexey Kardashevskiy VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); 305971461b0fSAlexey Kardashevskiy USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); 306071461b0fSAlexey Kardashevskiy 306171461b0fSAlexey Kardashevskiy if (spapr) { 306271461b0fSAlexey Kardashevskiy /* 306371461b0fSAlexey Kardashevskiy * Replace "channel@0/disk@0,0" with "disk@8000000000000000": 30641ac24c91SThomas Huth * In the top 16 bits of the 64-bit LUN, we use SRP luns of the form 30651ac24c91SThomas Huth * 0x8000 | (target << 8) | (bus << 5) | lun 30661ac24c91SThomas Huth * (see the "Logical unit addressing format" table in SAM5) 306771461b0fSAlexey Kardashevskiy */ 30681ac24c91SThomas Huth unsigned id = 0x8000 | (d->id << 8) | (d->channel << 5) | d->lun; 306971461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 307071461b0fSAlexey Kardashevskiy (uint64_t)id << 48); 307171461b0fSAlexey Kardashevskiy } else if (virtio) { 307271461b0fSAlexey Kardashevskiy /* 307371461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (target << 8) | lun 307471461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 307571461b0fSAlexey Kardashevskiy * Note: the quote above is from SLOF and it is wrong, 307671461b0fSAlexey Kardashevskiy * the actual binding is: 307771461b0fSAlexey Kardashevskiy * swap 0100 or 10 << or 20 << ( target lun-id -- srplun ) 307871461b0fSAlexey Kardashevskiy */ 307971461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (d->id << 16) | d->lun; 3080bac658d1SThomas Huth if (d->lun >= 256) { 3081bac658d1SThomas Huth /* Use the LUN "flat space addressing method" */ 3082bac658d1SThomas Huth id |= 0x4000; 3083bac658d1SThomas Huth } 308471461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 308571461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 308671461b0fSAlexey Kardashevskiy } else if (usb) { 308771461b0fSAlexey Kardashevskiy /* 308871461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (usb-port << 16) | lun 308971461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 309071461b0fSAlexey Kardashevskiy */ 309171461b0fSAlexey Kardashevskiy unsigned usb_port = atoi(usb->port->path); 309271461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (usb_port << 16) | d->lun; 309371461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 309471461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 309571461b0fSAlexey Kardashevskiy } 309671461b0fSAlexey Kardashevskiy } 309771461b0fSAlexey Kardashevskiy 3098b99260ebSThomas Huth /* 3099b99260ebSThomas Huth * SLOF probes the USB devices, and if it recognizes that the device is a 3100b99260ebSThomas Huth * storage device, it changes its name to "storage" instead of "usb-host", 3101b99260ebSThomas Huth * and additionally adds a child node for the SCSI LUN, so the correct 3102b99260ebSThomas Huth * boot path in SLOF is something like .../storage@1/disk@xxx" instead. 3103b99260ebSThomas Huth */ 3104b99260ebSThomas Huth if (strcmp("usb-host", qdev_fw_name(dev)) == 0) { 3105b99260ebSThomas Huth USBDevice *usbdev = CAST(USBDevice, dev, TYPE_USB_DEVICE); 3106b99260ebSThomas Huth if (usb_host_dev_is_scsi_storage(usbdev)) { 3107b99260ebSThomas Huth return g_strdup_printf("storage@%s/disk", usbdev->port->path); 3108b99260ebSThomas Huth } 3109b99260ebSThomas Huth } 3110b99260ebSThomas Huth 311171461b0fSAlexey Kardashevskiy if (phb) { 311271461b0fSAlexey Kardashevskiy /* Replace "pci" with "pci@800000020000000" */ 311371461b0fSAlexey Kardashevskiy return g_strdup_printf("pci@%"PRIX64, phb->buid); 311471461b0fSAlexey Kardashevskiy } 311571461b0fSAlexey Kardashevskiy 3116c4e13492SFelipe Franciosi if (vsc) { 3117c4e13492SFelipe Franciosi /* Same logic as virtio above */ 3118c4e13492SFelipe Franciosi unsigned id = 0x1000000 | (vsc->target << 16) | vsc->lun; 3119c4e13492SFelipe Franciosi return g_strdup_printf("disk@%"PRIX64, (uint64_t)id << 32); 3120c4e13492SFelipe Franciosi } 3121c4e13492SFelipe Franciosi 31224871dd4cSThomas Huth if (g_str_equal("pci-bridge", qdev_fw_name(dev))) { 31234871dd4cSThomas Huth /* SLOF uses "pci" instead of "pci-bridge" for PCI bridges */ 31244871dd4cSThomas Huth PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); 31254871dd4cSThomas Huth return g_strdup_printf("pci@%x", PCI_SLOT(pcidev->devfn)); 31264871dd4cSThomas Huth } 31274871dd4cSThomas Huth 312871461b0fSAlexey Kardashevskiy return NULL; 312971461b0fSAlexey Kardashevskiy } 313071461b0fSAlexey Kardashevskiy 313123825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp) 313223825581SEduardo Habkost { 3133ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 313423825581SEduardo Habkost 313528e02042SDavid Gibson return g_strdup(spapr->kvm_type); 313623825581SEduardo Habkost } 313723825581SEduardo Habkost 313823825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp) 313923825581SEduardo Habkost { 3140ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 314123825581SEduardo Habkost 314228e02042SDavid Gibson g_free(spapr->kvm_type); 314328e02042SDavid Gibson spapr->kvm_type = g_strdup(value); 314423825581SEduardo Habkost } 314523825581SEduardo Habkost 3146f6229214SMichael Roth static bool spapr_get_modern_hotplug_events(Object *obj, Error **errp) 3147f6229214SMichael Roth { 3148ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3149f6229214SMichael Roth 3150f6229214SMichael Roth return spapr->use_hotplug_event_source; 3151f6229214SMichael Roth } 3152f6229214SMichael Roth 3153f6229214SMichael Roth static void spapr_set_modern_hotplug_events(Object *obj, bool value, 3154f6229214SMichael Roth Error **errp) 3155f6229214SMichael Roth { 3156ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3157f6229214SMichael Roth 3158f6229214SMichael Roth spapr->use_hotplug_event_source = value; 3159f6229214SMichael Roth } 3160f6229214SMichael Roth 3161fcad0d21SAlexey Kardashevskiy static bool spapr_get_msix_emulation(Object *obj, Error **errp) 3162fcad0d21SAlexey Kardashevskiy { 3163fcad0d21SAlexey Kardashevskiy return true; 3164fcad0d21SAlexey Kardashevskiy } 3165fcad0d21SAlexey Kardashevskiy 316630f4b05bSDavid Gibson static char *spapr_get_resize_hpt(Object *obj, Error **errp) 316730f4b05bSDavid Gibson { 3168ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 316930f4b05bSDavid Gibson 317030f4b05bSDavid Gibson switch (spapr->resize_hpt) { 317130f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DEFAULT: 317230f4b05bSDavid Gibson return g_strdup("default"); 317330f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DISABLED: 317430f4b05bSDavid Gibson return g_strdup("disabled"); 317530f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_ENABLED: 317630f4b05bSDavid Gibson return g_strdup("enabled"); 317730f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_REQUIRED: 317830f4b05bSDavid Gibson return g_strdup("required"); 317930f4b05bSDavid Gibson } 318030f4b05bSDavid Gibson g_assert_not_reached(); 318130f4b05bSDavid Gibson } 318230f4b05bSDavid Gibson 318330f4b05bSDavid Gibson static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp) 318430f4b05bSDavid Gibson { 3185ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 318630f4b05bSDavid Gibson 318730f4b05bSDavid Gibson if (strcmp(value, "default") == 0) { 318830f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DEFAULT; 318930f4b05bSDavid Gibson } else if (strcmp(value, "disabled") == 0) { 319030f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 319130f4b05bSDavid Gibson } else if (strcmp(value, "enabled") == 0) { 319230f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_ENABLED; 319330f4b05bSDavid Gibson } else if (strcmp(value, "required") == 0) { 319430f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_REQUIRED; 319530f4b05bSDavid Gibson } else { 319630f4b05bSDavid Gibson error_setg(errp, "Bad value for \"resize-hpt\" property"); 319730f4b05bSDavid Gibson } 319830f4b05bSDavid Gibson } 319930f4b05bSDavid Gibson 32003ba3d0bcSCédric Le Goater static char *spapr_get_ic_mode(Object *obj, Error **errp) 32013ba3d0bcSCédric Le Goater { 3202ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 32033ba3d0bcSCédric Le Goater 32043ba3d0bcSCédric Le Goater if (spapr->irq == &spapr_irq_xics_legacy) { 32053ba3d0bcSCédric Le Goater return g_strdup("legacy"); 32063ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xics) { 32073ba3d0bcSCédric Le Goater return g_strdup("xics"); 32083ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xive) { 32093ba3d0bcSCédric Le Goater return g_strdup("xive"); 321013db0cd9SCédric Le Goater } else if (spapr->irq == &spapr_irq_dual) { 321113db0cd9SCédric Le Goater return g_strdup("dual"); 32123ba3d0bcSCédric Le Goater } 32133ba3d0bcSCédric Le Goater g_assert_not_reached(); 32143ba3d0bcSCédric Le Goater } 32153ba3d0bcSCédric Le Goater 32163ba3d0bcSCédric Le Goater static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp) 32173ba3d0bcSCédric Le Goater { 3218ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 32193ba3d0bcSCédric Le Goater 322021df5e4fSGreg Kurz if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { 322121df5e4fSGreg Kurz error_setg(errp, "This machine only uses the legacy XICS backend, don't pass ic-mode"); 322221df5e4fSGreg Kurz return; 322321df5e4fSGreg Kurz } 322421df5e4fSGreg Kurz 32253ba3d0bcSCédric Le Goater /* The legacy IRQ backend can not be set */ 32263ba3d0bcSCédric Le Goater if (strcmp(value, "xics") == 0) { 32273ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xics; 32283ba3d0bcSCédric Le Goater } else if (strcmp(value, "xive") == 0) { 32293ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xive; 323013db0cd9SCédric Le Goater } else if (strcmp(value, "dual") == 0) { 323113db0cd9SCédric Le Goater spapr->irq = &spapr_irq_dual; 32323ba3d0bcSCédric Le Goater } else { 32333ba3d0bcSCédric Le Goater error_setg(errp, "Bad value for \"ic-mode\" property"); 32343ba3d0bcSCédric Le Goater } 32353ba3d0bcSCédric Le Goater } 32363ba3d0bcSCédric Le Goater 323727461d69SPrasad J Pandit static char *spapr_get_host_model(Object *obj, Error **errp) 323827461d69SPrasad J Pandit { 3239ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 324027461d69SPrasad J Pandit 324127461d69SPrasad J Pandit return g_strdup(spapr->host_model); 324227461d69SPrasad J Pandit } 324327461d69SPrasad J Pandit 324427461d69SPrasad J Pandit static void spapr_set_host_model(Object *obj, const char *value, Error **errp) 324527461d69SPrasad J Pandit { 3246ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 324727461d69SPrasad J Pandit 324827461d69SPrasad J Pandit g_free(spapr->host_model); 324927461d69SPrasad J Pandit spapr->host_model = g_strdup(value); 325027461d69SPrasad J Pandit } 325127461d69SPrasad J Pandit 325227461d69SPrasad J Pandit static char *spapr_get_host_serial(Object *obj, Error **errp) 325327461d69SPrasad J Pandit { 3254ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 325527461d69SPrasad J Pandit 325627461d69SPrasad J Pandit return g_strdup(spapr->host_serial); 325727461d69SPrasad J Pandit } 325827461d69SPrasad J Pandit 325927461d69SPrasad J Pandit static void spapr_set_host_serial(Object *obj, const char *value, Error **errp) 326027461d69SPrasad J Pandit { 3261ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 326227461d69SPrasad J Pandit 326327461d69SPrasad J Pandit g_free(spapr->host_serial); 326427461d69SPrasad J Pandit spapr->host_serial = g_strdup(value); 326527461d69SPrasad J Pandit } 326627461d69SPrasad J Pandit 3267bcb5ce08SDavid Gibson static void spapr_instance_init(Object *obj) 326823825581SEduardo Habkost { 3269ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3270ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 3271715c5407SDavid Gibson 3272715c5407SDavid Gibson spapr->htab_fd = -1; 3273f6229214SMichael Roth spapr->use_hotplug_event_source = true; 327423825581SEduardo Habkost object_property_add_str(obj, "kvm-type", 3275d2623129SMarkus Armbruster spapr_get_kvm_type, spapr_set_kvm_type); 327649d2e648SMarcel Apfelbaum object_property_set_description(obj, "kvm-type", 32777eecec7dSMarkus Armbruster "Specifies the KVM virtualization mode (HV, PR)"); 3278f6229214SMichael Roth object_property_add_bool(obj, "modern-hotplug-events", 3279f6229214SMichael Roth spapr_get_modern_hotplug_events, 3280d2623129SMarkus Armbruster spapr_set_modern_hotplug_events); 3281f6229214SMichael Roth object_property_set_description(obj, "modern-hotplug-events", 3282f6229214SMichael Roth "Use dedicated hotplug event mechanism in" 3283f6229214SMichael Roth " place of standard EPOW events when possible" 32847eecec7dSMarkus Armbruster " (required for memory hot-unplug support)"); 32857843c0d6SDavid Gibson ppc_compat_add_property(obj, "max-cpu-compat", &spapr->max_compat_pvr, 328640c2281cSMarkus Armbruster "Maximum permitted CPU compatibility mode"); 328730f4b05bSDavid Gibson 328830f4b05bSDavid Gibson object_property_add_str(obj, "resize-hpt", 3289d2623129SMarkus Armbruster spapr_get_resize_hpt, spapr_set_resize_hpt); 329030f4b05bSDavid Gibson object_property_set_description(obj, "resize-hpt", 32917eecec7dSMarkus Armbruster "Resizing of the Hash Page Table (enabled, disabled, required)"); 329264a7b8deSFelipe Franciosi object_property_add_uint32_ptr(obj, "vsmt", 3293d2623129SMarkus Armbruster &spapr->vsmt, OBJ_PROP_FLAG_READWRITE); 3294fa98fbfcSSam Bobroff object_property_set_description(obj, "vsmt", 3295fa98fbfcSSam Bobroff "Virtual SMT: KVM behaves as if this were" 32967eecec7dSMarkus Armbruster " the host's SMT mode"); 329764a7b8deSFelipe Franciosi 3298fcad0d21SAlexey Kardashevskiy object_property_add_bool(obj, "vfio-no-msix-emulation", 3299d2623129SMarkus Armbruster spapr_get_msix_emulation, NULL); 33003ba3d0bcSCédric Le Goater 330164a7b8deSFelipe Franciosi object_property_add_uint64_ptr(obj, "kernel-addr", 3302d2623129SMarkus Armbruster &spapr->kernel_addr, OBJ_PROP_FLAG_READWRITE); 330387262806SAlexey Kardashevskiy object_property_set_description(obj, "kernel-addr", 330487262806SAlexey Kardashevskiy stringify(KERNEL_LOAD_ADDR) 33057eecec7dSMarkus Armbruster " for -kernel is the default"); 330687262806SAlexey Kardashevskiy spapr->kernel_addr = KERNEL_LOAD_ADDR; 33073ba3d0bcSCédric Le Goater /* The machine class defines the default interrupt controller mode */ 33083ba3d0bcSCédric Le Goater spapr->irq = smc->irq; 33093ba3d0bcSCédric Le Goater object_property_add_str(obj, "ic-mode", spapr_get_ic_mode, 3310d2623129SMarkus Armbruster spapr_set_ic_mode); 33113ba3d0bcSCédric Le Goater object_property_set_description(obj, "ic-mode", 33127eecec7dSMarkus Armbruster "Specifies the interrupt controller mode (xics, xive, dual)"); 331327461d69SPrasad J Pandit 331427461d69SPrasad J Pandit object_property_add_str(obj, "host-model", 3315d2623129SMarkus Armbruster spapr_get_host_model, spapr_set_host_model); 331627461d69SPrasad J Pandit object_property_set_description(obj, "host-model", 33177eecec7dSMarkus Armbruster "Host model to advertise in guest device tree"); 331827461d69SPrasad J Pandit object_property_add_str(obj, "host-serial", 3319d2623129SMarkus Armbruster spapr_get_host_serial, spapr_set_host_serial); 332027461d69SPrasad J Pandit object_property_set_description(obj, "host-serial", 33217eecec7dSMarkus Armbruster "Host serial number to advertise in guest device tree"); 332223825581SEduardo Habkost } 332323825581SEduardo Habkost 332487bbdd9cSDavid Gibson static void spapr_machine_finalizefn(Object *obj) 332587bbdd9cSDavid Gibson { 3326ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 332787bbdd9cSDavid Gibson 332887bbdd9cSDavid Gibson g_free(spapr->kvm_type); 332987bbdd9cSDavid Gibson } 333087bbdd9cSDavid Gibson 33311c7ad77eSNicholas Piggin void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg) 333234316482SAlexey Kardashevskiy { 33330e236d34SNicholas Piggin SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 3334b5b7f391SNicholas Piggin PowerPCCPU *cpu = POWERPC_CPU(cs); 3335b5b7f391SNicholas Piggin CPUPPCState *env = &cpu->env; 33360e236d34SNicholas Piggin 333734316482SAlexey Kardashevskiy cpu_synchronize_state(cs); 33380e236d34SNicholas Piggin /* If FWNMI is inactive, addr will be -1, which will deliver to 0x100 */ 33390e236d34SNicholas Piggin if (spapr->fwnmi_system_reset_addr != -1) { 33400e236d34SNicholas Piggin uint64_t rtas_addr, addr; 33410e236d34SNicholas Piggin 33420e236d34SNicholas Piggin /* get rtas addr from fdt */ 33430e236d34SNicholas Piggin rtas_addr = spapr_get_rtas_addr(); 33440e236d34SNicholas Piggin if (!rtas_addr) { 33450e236d34SNicholas Piggin qemu_system_guest_panicked(NULL); 33460e236d34SNicholas Piggin return; 33470e236d34SNicholas Piggin } 33480e236d34SNicholas Piggin 33490e236d34SNicholas Piggin addr = rtas_addr + RTAS_ERROR_LOG_MAX + cs->cpu_index * sizeof(uint64_t)*2; 33500e236d34SNicholas Piggin stq_be_phys(&address_space_memory, addr, env->gpr[3]); 33510e236d34SNicholas Piggin stq_be_phys(&address_space_memory, addr + sizeof(uint64_t), 0); 33520e236d34SNicholas Piggin env->gpr[3] = addr; 33530e236d34SNicholas Piggin } 3354b5b7f391SNicholas Piggin ppc_cpu_do_system_reset(cs); 3355b5b7f391SNicholas Piggin if (spapr->fwnmi_system_reset_addr != -1) { 3356b5b7f391SNicholas Piggin env->nip = spapr->fwnmi_system_reset_addr; 3357b5b7f391SNicholas Piggin } 335834316482SAlexey Kardashevskiy } 335934316482SAlexey Kardashevskiy 336034316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) 336134316482SAlexey Kardashevskiy { 336234316482SAlexey Kardashevskiy CPUState *cs; 336334316482SAlexey Kardashevskiy 336434316482SAlexey Kardashevskiy CPU_FOREACH(cs) { 33651c7ad77eSNicholas Piggin async_run_on_cpu(cs, spapr_do_system_reset_on_cpu, RUN_ON_CPU_NULL); 336634316482SAlexey Kardashevskiy } 336734316482SAlexey Kardashevskiy } 336834316482SAlexey Kardashevskiy 3369ce2918cbSDavid Gibson int spapr_lmb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 337062d38c9bSGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 337162d38c9bSGreg Kurz { 337262d38c9bSGreg Kurz uint64_t addr; 337362d38c9bSGreg Kurz uint32_t node; 337462d38c9bSGreg Kurz 337562d38c9bSGreg Kurz addr = spapr_drc_index(drc) * SPAPR_MEMORY_BLOCK_SIZE; 337662d38c9bSGreg Kurz node = object_property_get_uint(OBJECT(drc->dev), PC_DIMM_NODE_PROP, 337762d38c9bSGreg Kurz &error_abort); 3378f1aa45ffSDaniel Henrique Barboza *fdt_start_offset = spapr_dt_memory_node(spapr, fdt, node, addr, 337962d38c9bSGreg Kurz SPAPR_MEMORY_BLOCK_SIZE); 338062d38c9bSGreg Kurz return 0; 338162d38c9bSGreg Kurz } 338262d38c9bSGreg Kurz 33836e837f98SGreg Kurz static bool spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, 338462d38c9bSGreg Kurz bool dedicated_hp_event_source, Error **errp) 3385c20d332aSBharata B Rao { 3386ce2918cbSDavid Gibson SpaprDrc *drc; 3387c20d332aSBharata B Rao uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; 338862d38c9bSGreg Kurz int i; 338979b78a6bSMichael Roth uint64_t addr = addr_start; 339094fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 3391c20d332aSBharata B Rao 3392c20d332aSBharata B Rao for (i = 0; i < nr_lmbs; i++) { 3393fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 3394c20d332aSBharata B Rao addr / SPAPR_MEMORY_BLOCK_SIZE); 3395c20d332aSBharata B Rao g_assert(drc); 3396c20d332aSBharata B Rao 339717548fe6SGreg Kurz if (!spapr_drc_attach(drc, dev, errp)) { 3398160bb678SGreg Kurz while (addr > addr_start) { 3399160bb678SGreg Kurz addr -= SPAPR_MEMORY_BLOCK_SIZE; 3400160bb678SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 3401160bb678SGreg Kurz addr / SPAPR_MEMORY_BLOCK_SIZE); 3402a8dc47fdSDavid Gibson spapr_drc_detach(drc); 3403160bb678SGreg Kurz } 34046e837f98SGreg Kurz return false; 3405160bb678SGreg Kurz } 340694fd9cbaSLaurent Vivier if (!hotplugged) { 340794fd9cbaSLaurent Vivier spapr_drc_reset(drc); 340894fd9cbaSLaurent Vivier } 3409c20d332aSBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE; 3410c20d332aSBharata B Rao } 34115dd5238cSJianjun Duan /* send hotplug notification to the 34125dd5238cSJianjun Duan * guest only in case of hotplugged memory 34135dd5238cSJianjun Duan */ 341494fd9cbaSLaurent Vivier if (hotplugged) { 341579b78a6bSMichael Roth if (dedicated_hp_event_source) { 3416fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 341779b78a6bSMichael Roth addr_start / SPAPR_MEMORY_BLOCK_SIZE); 341879b78a6bSMichael Roth spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 341979b78a6bSMichael Roth nr_lmbs, 34200b55aa91SDavid Gibson spapr_drc_index(drc)); 342179b78a6bSMichael Roth } else { 342279b78a6bSMichael Roth spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, 342379b78a6bSMichael Roth nr_lmbs); 342479b78a6bSMichael Roth } 3425c20d332aSBharata B Rao } 34266e837f98SGreg Kurz return true; 34275dd5238cSJianjun Duan } 3428c20d332aSBharata B Rao 3429c20d332aSBharata B Rao static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 343081985f3bSDavid Hildenbrand Error **errp) 3431c20d332aSBharata B Rao { 3432ce2918cbSDavid Gibson SpaprMachineState *ms = SPAPR_MACHINE(hotplug_dev); 3433c20d332aSBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 3434581778ddSGreg Kurz uint64_t size, addr; 3435581778ddSGreg Kurz int64_t slot; 3436ee3a71e3SShivaprasad G Bhat bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); 343704790978SThomas Huth 3438946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dev), &error_abort); 3439df587133SThomas Huth 344084fd5496SGreg Kurz pc_dimm_plug(dimm, MACHINE(ms)); 3441c20d332aSBharata B Rao 3442ee3a71e3SShivaprasad G Bhat if (!is_nvdimm) { 34439ed442b8SMarc-André Lureau addr = object_property_get_uint(OBJECT(dimm), 3444271ced1dSGreg Kurz PC_DIMM_ADDR_PROP, &error_abort); 34456e837f98SGreg Kurz if (!spapr_add_lmbs(dev, addr, size, 34466e837f98SGreg Kurz spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), errp)) { 34476e837f98SGreg Kurz goto out_unplug; 34486e837f98SGreg Kurz } 3449ee3a71e3SShivaprasad G Bhat } else { 3450581778ddSGreg Kurz slot = object_property_get_int(OBJECT(dimm), 3451271ced1dSGreg Kurz PC_DIMM_SLOT_PROP, &error_abort); 3452581778ddSGreg Kurz /* We should have valid slot number at this point */ 3453581778ddSGreg Kurz g_assert(slot >= 0); 34546e837f98SGreg Kurz if (!spapr_add_nvdimm(dev, slot, errp)) { 3455160bb678SGreg Kurz goto out_unplug; 3456160bb678SGreg Kurz } 34576e837f98SGreg Kurz } 3458c20d332aSBharata B Rao 3459160bb678SGreg Kurz return; 3460160bb678SGreg Kurz 3461160bb678SGreg Kurz out_unplug: 3462fd3416f5SDavid Hildenbrand pc_dimm_unplug(dimm, MACHINE(ms)); 3463c20d332aSBharata B Rao } 3464c20d332aSBharata B Rao 3465c871bc70SLaurent Vivier static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3466c871bc70SLaurent Vivier Error **errp) 3467c871bc70SLaurent Vivier { 3468ce2918cbSDavid Gibson const SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev); 3469ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3470ee3a71e3SShivaprasad G Bhat bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); 3471c871bc70SLaurent Vivier PCDIMMDevice *dimm = PC_DIMM(dev); 34728f1ffe5bSDavid Hildenbrand Error *local_err = NULL; 347304790978SThomas Huth uint64_t size; 3474123eec65SDavid Gibson Object *memdev; 3475123eec65SDavid Gibson hwaddr pagesize; 3476c871bc70SLaurent Vivier 34774e8a01bdSDavid Hildenbrand if (!smc->dr_lmb_enabled) { 34784e8a01bdSDavid Hildenbrand error_setg(errp, "Memory hotplug not supported for this machine"); 34794e8a01bdSDavid Hildenbrand return; 34804e8a01bdSDavid Hildenbrand } 34814e8a01bdSDavid Hildenbrand 3482946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &local_err); 3483946d6154SDavid Hildenbrand if (local_err) { 3484946d6154SDavid Hildenbrand error_propagate(errp, local_err); 348504790978SThomas Huth return; 348604790978SThomas Huth } 348704790978SThomas Huth 3488beb6073fSDaniel Henrique Barboza if (is_nvdimm) { 3489451c6905SGreg Kurz if (!spapr_nvdimm_validate(hotplug_dev, NVDIMM(dev), size, errp)) { 3490ee3a71e3SShivaprasad G Bhat return; 3491ee3a71e3SShivaprasad G Bhat } 3492beb6073fSDaniel Henrique Barboza } else if (size % SPAPR_MEMORY_BLOCK_SIZE) { 3493beb6073fSDaniel Henrique Barboza error_setg(errp, "Hotplugged memory size must be a multiple of " 3494beb6073fSDaniel Henrique Barboza "%" PRIu64 " MB", SPAPR_MEMORY_BLOCK_SIZE / MiB); 3495beb6073fSDaniel Henrique Barboza return; 3496c871bc70SLaurent Vivier } 3497c871bc70SLaurent Vivier 3498123eec65SDavid Gibson memdev = object_property_get_link(OBJECT(dimm), PC_DIMM_MEMDEV_PROP, 3499123eec65SDavid Gibson &error_abort); 3500123eec65SDavid Gibson pagesize = host_memory_backend_pagesize(MEMORY_BACKEND(memdev)); 350135dce34fSGreg Kurz if (!spapr_check_pagesize(spapr, pagesize, errp)) { 35028f1ffe5bSDavid Hildenbrand return; 35038f1ffe5bSDavid Hildenbrand } 35048f1ffe5bSDavid Hildenbrand 3505fd3416f5SDavid Hildenbrand pc_dimm_pre_plug(dimm, MACHINE(hotplug_dev), NULL, errp); 3506c871bc70SLaurent Vivier } 3507c871bc70SLaurent Vivier 3508ce2918cbSDavid Gibson struct SpaprDimmState { 35090cffce56SDavid Gibson PCDIMMDevice *dimm; 3510cf632463SBharata B Rao uint32_t nr_lmbs; 3511ce2918cbSDavid Gibson QTAILQ_ENTRY(SpaprDimmState) next; 35120cffce56SDavid Gibson }; 35130cffce56SDavid Gibson 3514ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_find(SpaprMachineState *s, 35150cffce56SDavid Gibson PCDIMMDevice *dimm) 35160cffce56SDavid Gibson { 3517ce2918cbSDavid Gibson SpaprDimmState *dimm_state = NULL; 35180cffce56SDavid Gibson 35190cffce56SDavid Gibson QTAILQ_FOREACH(dimm_state, &s->pending_dimm_unplugs, next) { 35200cffce56SDavid Gibson if (dimm_state->dimm == dimm) { 35210cffce56SDavid Gibson break; 35220cffce56SDavid Gibson } 35230cffce56SDavid Gibson } 35240cffce56SDavid Gibson return dimm_state; 35250cffce56SDavid Gibson } 35260cffce56SDavid Gibson 3527ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_add(SpaprMachineState *spapr, 35288d5981c4SBharata B Rao uint32_t nr_lmbs, 35298d5981c4SBharata B Rao PCDIMMDevice *dimm) 35300cffce56SDavid Gibson { 3531ce2918cbSDavid Gibson SpaprDimmState *ds = NULL; 35328d5981c4SBharata B Rao 35338d5981c4SBharata B Rao /* 35348d5981c4SBharata B Rao * If this request is for a DIMM whose removal had failed earlier 35358d5981c4SBharata B Rao * (due to guest's refusal to remove the LMBs), we would have this 35368d5981c4SBharata B Rao * dimm already in the pending_dimm_unplugs list. In that 35378d5981c4SBharata B Rao * case don't add again. 35388d5981c4SBharata B Rao */ 35398d5981c4SBharata B Rao ds = spapr_pending_dimm_unplugs_find(spapr, dimm); 35408d5981c4SBharata B Rao if (!ds) { 3541ce2918cbSDavid Gibson ds = g_malloc0(sizeof(SpaprDimmState)); 35428d5981c4SBharata B Rao ds->nr_lmbs = nr_lmbs; 35438d5981c4SBharata B Rao ds->dimm = dimm; 35448d5981c4SBharata B Rao QTAILQ_INSERT_HEAD(&spapr->pending_dimm_unplugs, ds, next); 35458d5981c4SBharata B Rao } 35468d5981c4SBharata B Rao return ds; 35470cffce56SDavid Gibson } 35480cffce56SDavid Gibson 3549ce2918cbSDavid Gibson static void spapr_pending_dimm_unplugs_remove(SpaprMachineState *spapr, 3550ce2918cbSDavid Gibson SpaprDimmState *dimm_state) 35510cffce56SDavid Gibson { 35520cffce56SDavid Gibson QTAILQ_REMOVE(&spapr->pending_dimm_unplugs, dimm_state, next); 35530cffce56SDavid Gibson g_free(dimm_state); 35540cffce56SDavid Gibson } 3555cf632463SBharata B Rao 3556ce2918cbSDavid Gibson static SpaprDimmState *spapr_recover_pending_dimm_state(SpaprMachineState *ms, 355716ee9980SDaniel Henrique Barboza PCDIMMDevice *dimm) 355816ee9980SDaniel Henrique Barboza { 3559ce2918cbSDavid Gibson SpaprDrc *drc; 3560946d6154SDavid Hildenbrand uint64_t size = memory_device_get_region_size(MEMORY_DEVICE(dimm), 3561946d6154SDavid Hildenbrand &error_abort); 356216ee9980SDaniel Henrique Barboza uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 356316ee9980SDaniel Henrique Barboza uint32_t avail_lmbs = 0; 356416ee9980SDaniel Henrique Barboza uint64_t addr_start, addr; 356516ee9980SDaniel Henrique Barboza int i; 356616ee9980SDaniel Henrique Barboza 356765226afdSGreg Kurz addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, 356816ee9980SDaniel Henrique Barboza &error_abort); 356916ee9980SDaniel Henrique Barboza 357016ee9980SDaniel Henrique Barboza addr = addr_start; 357116ee9980SDaniel Henrique Barboza for (i = 0; i < nr_lmbs; i++) { 3572fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 357316ee9980SDaniel Henrique Barboza addr / SPAPR_MEMORY_BLOCK_SIZE); 357416ee9980SDaniel Henrique Barboza g_assert(drc); 3575454b580aSDavid Gibson if (drc->dev) { 357616ee9980SDaniel Henrique Barboza avail_lmbs++; 357716ee9980SDaniel Henrique Barboza } 357816ee9980SDaniel Henrique Barboza addr += SPAPR_MEMORY_BLOCK_SIZE; 357916ee9980SDaniel Henrique Barboza } 358016ee9980SDaniel Henrique Barboza 35818d5981c4SBharata B Rao return spapr_pending_dimm_unplugs_add(ms, avail_lmbs, dimm); 358216ee9980SDaniel Henrique Barboza } 358316ee9980SDaniel Henrique Barboza 358431834723SDaniel Henrique Barboza /* Callback to be called during DRC release. */ 358531834723SDaniel Henrique Barboza void spapr_lmb_release(DeviceState *dev) 3586cf632463SBharata B Rao { 35873ec71474SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3588ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl); 3589ce2918cbSDavid Gibson SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); 3590cf632463SBharata B Rao 359116ee9980SDaniel Henrique Barboza /* This information will get lost if a migration occurs 359216ee9980SDaniel Henrique Barboza * during the unplug process. In this case recover it. */ 359316ee9980SDaniel Henrique Barboza if (ds == NULL) { 359416ee9980SDaniel Henrique Barboza ds = spapr_recover_pending_dimm_state(spapr, PC_DIMM(dev)); 35958d5981c4SBharata B Rao g_assert(ds); 3596454b580aSDavid Gibson /* The DRC being examined by the caller at least must be counted */ 3597454b580aSDavid Gibson g_assert(ds->nr_lmbs); 359816ee9980SDaniel Henrique Barboza } 3599454b580aSDavid Gibson 3600454b580aSDavid Gibson if (--ds->nr_lmbs) { 3601cf632463SBharata B Rao return; 3602cf632463SBharata B Rao } 3603cf632463SBharata B Rao 3604cf632463SBharata B Rao /* 3605cf632463SBharata B Rao * Now that all the LMBs have been removed by the guest, call the 36063ec71474SDavid Hildenbrand * unplug handler chain. This can never fail. 3607cf632463SBharata B Rao */ 36083ec71474SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 360907578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 36103ec71474SDavid Hildenbrand } 36113ec71474SDavid Hildenbrand 36123ec71474SDavid Hildenbrand static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 36133ec71474SDavid Hildenbrand { 3614ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3615ce2918cbSDavid Gibson SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); 36163ec71474SDavid Hildenbrand 3617fd3416f5SDavid Hildenbrand pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev)); 3618981c3dcdSMarkus Armbruster qdev_unrealize(dev); 36192a129767SDaniel Henrique Barboza spapr_pending_dimm_unplugs_remove(spapr, ds); 3620cf632463SBharata B Rao } 3621cf632463SBharata B Rao 3622cf632463SBharata B Rao static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, 3623cf632463SBharata B Rao DeviceState *dev, Error **errp) 3624cf632463SBharata B Rao { 3625ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3626cf632463SBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 362704790978SThomas Huth uint32_t nr_lmbs; 362804790978SThomas Huth uint64_t size, addr_start, addr; 36290cffce56SDavid Gibson int i; 3630ce2918cbSDavid Gibson SpaprDrc *drc; 363104790978SThomas Huth 3632ee3a71e3SShivaprasad G Bhat if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { 3633dcfe4805SMarkus Armbruster error_setg(errp, "nvdimm device hot unplug is not supported yet."); 3634dcfe4805SMarkus Armbruster return; 3635ee3a71e3SShivaprasad G Bhat } 3636ee3a71e3SShivaprasad G Bhat 3637946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &error_abort); 363804790978SThomas Huth nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 363904790978SThomas Huth 36409ed442b8SMarc-André Lureau addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, 3641271ced1dSGreg Kurz &error_abort); 3642cf632463SBharata B Rao 36432a129767SDaniel Henrique Barboza /* 36442a129767SDaniel Henrique Barboza * An existing pending dimm state for this DIMM means that there is an 36452a129767SDaniel Henrique Barboza * unplug operation in progress, waiting for the spapr_lmb_release 36462a129767SDaniel Henrique Barboza * callback to complete the job (BQL can't cover that far). In this case, 36472a129767SDaniel Henrique Barboza * bail out to avoid detaching DRCs that were already released. 36482a129767SDaniel Henrique Barboza */ 36492a129767SDaniel Henrique Barboza if (spapr_pending_dimm_unplugs_find(spapr, dimm)) { 3650dcfe4805SMarkus Armbruster error_setg(errp, "Memory unplug already in progress for device %s", 36512a129767SDaniel Henrique Barboza dev->id); 3652dcfe4805SMarkus Armbruster return; 36532a129767SDaniel Henrique Barboza } 36542a129767SDaniel Henrique Barboza 36558d5981c4SBharata B Rao spapr_pending_dimm_unplugs_add(spapr, nr_lmbs, dimm); 36560cffce56SDavid Gibson 36570cffce56SDavid Gibson addr = addr_start; 36580cffce56SDavid Gibson for (i = 0; i < nr_lmbs; i++) { 3659fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 36600cffce56SDavid Gibson addr / SPAPR_MEMORY_BLOCK_SIZE); 36610cffce56SDavid Gibson g_assert(drc); 36620cffce56SDavid Gibson 3663a8dc47fdSDavid Gibson spapr_drc_detach(drc); 36640cffce56SDavid Gibson addr += SPAPR_MEMORY_BLOCK_SIZE; 36650cffce56SDavid Gibson } 36660cffce56SDavid Gibson 3667fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 36680cffce56SDavid Gibson addr_start / SPAPR_MEMORY_BLOCK_SIZE); 36690cffce56SDavid Gibson spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 36700b55aa91SDavid Gibson nr_lmbs, spapr_drc_index(drc)); 3671cf632463SBharata B Rao } 3672cf632463SBharata B Rao 3673765d1bddSDavid Gibson /* Callback to be called during DRC release. */ 3674765d1bddSDavid Gibson void spapr_core_release(DeviceState *dev) 3675ff9006ddSIgor Mammedov { 3676a4261be1SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3677a4261be1SDavid Hildenbrand 3678a4261be1SDavid Hildenbrand /* Call the unplug handler chain. This can never fail. */ 3679a4261be1SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 368007578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 3681a4261be1SDavid Hildenbrand } 3682a4261be1SDavid Hildenbrand 3683a4261be1SDavid Hildenbrand static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 3684a4261be1SDavid Hildenbrand { 3685a4261be1SDavid Hildenbrand MachineState *ms = MACHINE(hotplug_dev); 3686ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms); 3687ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3688535455fdSIgor Mammedov CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL); 3689ff9006ddSIgor Mammedov 369046f7afa3SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 3691ce2918cbSDavid Gibson SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); 369246f7afa3SGreg Kurz int i; 369346f7afa3SGreg Kurz 369446f7afa3SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 369594ad93bdSGreg Kurz CPUState *cs = CPU(sc->threads[i]); 369646f7afa3SGreg Kurz 369746f7afa3SGreg Kurz pre_2_10_vmstate_register_dummy_icp(cs->cpu_index); 369846f7afa3SGreg Kurz } 369946f7afa3SGreg Kurz } 370046f7afa3SGreg Kurz 370107572c06SGreg Kurz assert(core_slot); 3702535455fdSIgor Mammedov core_slot->cpu = NULL; 3703981c3dcdSMarkus Armbruster qdev_unrealize(dev); 3704ff9006ddSIgor Mammedov } 3705ff9006ddSIgor Mammedov 3706115debf2SIgor Mammedov static 3707115debf2SIgor Mammedov void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, 3708ff9006ddSIgor Mammedov Error **errp) 3709ff9006ddSIgor Mammedov { 3710ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3711535455fdSIgor Mammedov int index; 3712ce2918cbSDavid Gibson SpaprDrc *drc; 3713535455fdSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3714ff9006ddSIgor Mammedov 3715535455fdSIgor Mammedov if (!spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index)) { 3716535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 3717535455fdSIgor Mammedov cc->core_id); 3718535455fdSIgor Mammedov return; 3719535455fdSIgor Mammedov } 3720ff9006ddSIgor Mammedov if (index == 0) { 3721ff9006ddSIgor Mammedov error_setg(errp, "Boot CPU core may not be unplugged"); 3722ff9006ddSIgor Mammedov return; 3723ff9006ddSIgor Mammedov } 3724ff9006ddSIgor Mammedov 37255d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 37265d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 3727ff9006ddSIgor Mammedov g_assert(drc); 3728ff9006ddSIgor Mammedov 372947c8c915SGreg Kurz if (!spapr_drc_unplug_requested(drc)) { 3730a8dc47fdSDavid Gibson spapr_drc_detach(drc); 3731ff9006ddSIgor Mammedov spapr_hotplug_req_remove_by_index(drc); 3732ff9006ddSIgor Mammedov } 373347c8c915SGreg Kurz } 3734ff9006ddSIgor Mammedov 3735ce2918cbSDavid Gibson int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 3736345b12b9SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 3737345b12b9SGreg Kurz { 3738ce2918cbSDavid Gibson SpaprCpuCore *core = SPAPR_CPU_CORE(drc->dev); 3739345b12b9SGreg Kurz CPUState *cs = CPU(core->threads[0]); 3740345b12b9SGreg Kurz PowerPCCPU *cpu = POWERPC_CPU(cs); 3741345b12b9SGreg Kurz DeviceClass *dc = DEVICE_GET_CLASS(cs); 3742345b12b9SGreg Kurz int id = spapr_get_vcpu_id(cpu); 3743345b12b9SGreg Kurz char *nodename; 3744345b12b9SGreg Kurz int offset; 3745345b12b9SGreg Kurz 3746345b12b9SGreg Kurz nodename = g_strdup_printf("%s@%x", dc->fw_name, id); 3747345b12b9SGreg Kurz offset = fdt_add_subnode(fdt, 0, nodename); 3748345b12b9SGreg Kurz g_free(nodename); 3749345b12b9SGreg Kurz 375091335a5eSDavid Gibson spapr_dt_cpu(cs, fdt, offset, spapr); 3751345b12b9SGreg Kurz 3752345b12b9SGreg Kurz *fdt_start_offset = offset; 3753345b12b9SGreg Kurz return 0; 3754345b12b9SGreg Kurz } 3755345b12b9SGreg Kurz 3756ff9006ddSIgor Mammedov static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3757ff9006ddSIgor Mammedov Error **errp) 3758ff9006ddSIgor Mammedov { 3759ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3760ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(spapr); 3761ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 3762ce2918cbSDavid Gibson SpaprCpuCore *core = SPAPR_CPU_CORE(OBJECT(dev)); 3763ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3764345b12b9SGreg Kurz CPUState *cs; 3765ce2918cbSDavid Gibson SpaprDrc *drc; 3766535455fdSIgor Mammedov CPUArchId *core_slot; 3767535455fdSIgor Mammedov int index; 376894fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 3769b1e81567SGreg Kurz int i; 3770ff9006ddSIgor Mammedov 3771535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 3772535455fdSIgor Mammedov if (!core_slot) { 3773535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 3774535455fdSIgor Mammedov cc->core_id); 3775535455fdSIgor Mammedov return; 3776535455fdSIgor Mammedov } 37775d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 37785d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 3779ff9006ddSIgor Mammedov 3780c5514d0eSIgor Mammedov g_assert(drc || !mc->has_hotpluggable_cpus); 3781ff9006ddSIgor Mammedov 3782e49c63d5SGreg Kurz if (drc) { 378317548fe6SGreg Kurz if (!spapr_drc_attach(drc, dev, errp)) { 3784ff9006ddSIgor Mammedov return; 3785ff9006ddSIgor Mammedov } 3786ff9006ddSIgor Mammedov 378794fd9cbaSLaurent Vivier if (hotplugged) { 3788ff9006ddSIgor Mammedov /* 378994fd9cbaSLaurent Vivier * Send hotplug notification interrupt to the guest only 379094fd9cbaSLaurent Vivier * in case of hotplugged CPUs. 3791ff9006ddSIgor Mammedov */ 3792ff9006ddSIgor Mammedov spapr_hotplug_req_add_by_index(drc); 379394fd9cbaSLaurent Vivier } else { 379494fd9cbaSLaurent Vivier spapr_drc_reset(drc); 3795ff9006ddSIgor Mammedov } 379694fd9cbaSLaurent Vivier } 379794fd9cbaSLaurent Vivier 3798535455fdSIgor Mammedov core_slot->cpu = OBJECT(dev); 379946f7afa3SGreg Kurz 380046f7afa3SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 380146f7afa3SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 3802bc877283SGreg Kurz cs = CPU(core->threads[i]); 380346f7afa3SGreg Kurz pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index); 380446f7afa3SGreg Kurz } 380546f7afa3SGreg Kurz } 3806b1e81567SGreg Kurz 3807b1e81567SGreg Kurz /* 3808b1e81567SGreg Kurz * Set compatibility mode to match the boot CPU, which was either set 3809b1e81567SGreg Kurz * by the machine reset code or by CAS. 3810b1e81567SGreg Kurz */ 3811b1e81567SGreg Kurz if (hotplugged) { 3812b1e81567SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 3813a3114923SGreg Kurz if (ppc_set_compat(core->threads[i], 3814a3114923SGreg Kurz POWERPC_CPU(first_cpu)->compat_pvr, 3815a3114923SGreg Kurz errp) < 0) { 3816b1e81567SGreg Kurz return; 3817b1e81567SGreg Kurz } 3818b1e81567SGreg Kurz } 3819b1e81567SGreg Kurz } 3820ff9006ddSIgor Mammedov } 3821ff9006ddSIgor Mammedov 3822ff9006ddSIgor Mammedov static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3823ff9006ddSIgor Mammedov Error **errp) 3824ff9006ddSIgor Mammedov { 3825ff9006ddSIgor Mammedov MachineState *machine = MACHINE(OBJECT(hotplug_dev)); 3826ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); 3827ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 38282e9c10ebSIgor Mammedov const char *base_core_type = spapr_get_cpu_core_type(machine->cpu_type); 3829ff9006ddSIgor Mammedov const char *type = object_get_typename(OBJECT(dev)); 3830535455fdSIgor Mammedov CPUArchId *core_slot; 3831535455fdSIgor Mammedov int index; 3832fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 3833ff9006ddSIgor Mammedov 3834c5514d0eSIgor Mammedov if (dev->hotplugged && !mc->has_hotpluggable_cpus) { 3835dcfe4805SMarkus Armbruster error_setg(errp, "CPU hotplug not supported for this machine"); 3836dcfe4805SMarkus Armbruster return; 3837ff9006ddSIgor Mammedov } 3838ff9006ddSIgor Mammedov 3839ff9006ddSIgor Mammedov if (strcmp(base_core_type, type)) { 3840dcfe4805SMarkus Armbruster error_setg(errp, "CPU core type should be %s", base_core_type); 3841dcfe4805SMarkus Armbruster return; 3842ff9006ddSIgor Mammedov } 3843ff9006ddSIgor Mammedov 3844ff9006ddSIgor Mammedov if (cc->core_id % smp_threads) { 3845dcfe4805SMarkus Armbruster error_setg(errp, "invalid core id %d", cc->core_id); 3846dcfe4805SMarkus Armbruster return; 3847ff9006ddSIgor Mammedov } 3848ff9006ddSIgor Mammedov 3849459264efSDavid Gibson /* 3850459264efSDavid Gibson * In general we should have homogeneous threads-per-core, but old 3851459264efSDavid Gibson * (pre hotplug support) machine types allow the last core to have 3852459264efSDavid Gibson * reduced threads as a compatibility hack for when we allowed 3853459264efSDavid Gibson * total vcpus not a multiple of threads-per-core. 3854459264efSDavid Gibson */ 3855459264efSDavid Gibson if (mc->has_hotpluggable_cpus && (cc->nr_threads != smp_threads)) { 3856dcfe4805SMarkus Armbruster error_setg(errp, "invalid nr-threads %d, must be %d", cc->nr_threads, 3857dcfe4805SMarkus Armbruster smp_threads); 3858dcfe4805SMarkus Armbruster return; 38598149e299SDavid Gibson } 38608149e299SDavid Gibson 3861535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 3862535455fdSIgor Mammedov if (!core_slot) { 3863dcfe4805SMarkus Armbruster error_setg(errp, "core id %d out of range", cc->core_id); 3864dcfe4805SMarkus Armbruster return; 3865ff9006ddSIgor Mammedov } 3866ff9006ddSIgor Mammedov 3867535455fdSIgor Mammedov if (core_slot->cpu) { 3868dcfe4805SMarkus Armbruster error_setg(errp, "core %d already populated", cc->core_id); 3869dcfe4805SMarkus Armbruster return; 3870ff9006ddSIgor Mammedov } 3871ff9006ddSIgor Mammedov 3872dcfe4805SMarkus Armbruster numa_cpu_pre_plug(core_slot, dev, errp); 3873ff9006ddSIgor Mammedov } 3874ff9006ddSIgor Mammedov 3875ce2918cbSDavid Gibson int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 3876bb2bdd81SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 3877bb2bdd81SGreg Kurz { 3878ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(drc->dev); 3879bb2bdd81SGreg Kurz int intc_phandle; 3880bb2bdd81SGreg Kurz 3881bb2bdd81SGreg Kurz intc_phandle = spapr_irq_get_phandle(spapr, spapr->fdt_blob, errp); 3882bb2bdd81SGreg Kurz if (intc_phandle <= 0) { 3883bb2bdd81SGreg Kurz return -1; 3884bb2bdd81SGreg Kurz } 3885bb2bdd81SGreg Kurz 38868cbe71ecSDavid Gibson if (spapr_dt_phb(spapr, sphb, intc_phandle, fdt, fdt_start_offset)) { 3887bb2bdd81SGreg Kurz error_setg(errp, "unable to create FDT node for PHB %d", sphb->index); 3888bb2bdd81SGreg Kurz return -1; 3889bb2bdd81SGreg Kurz } 3890bb2bdd81SGreg Kurz 3891bb2bdd81SGreg Kurz /* generally SLOF creates these, for hotplug it's up to QEMU */ 3892bb2bdd81SGreg Kurz _FDT(fdt_setprop_string(fdt, *fdt_start_offset, "name", "pci")); 3893bb2bdd81SGreg Kurz 3894bb2bdd81SGreg Kurz return 0; 3895bb2bdd81SGreg Kurz } 3896bb2bdd81SGreg Kurz 3897bb2bdd81SGreg Kurz static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3898bb2bdd81SGreg Kurz Error **errp) 3899bb2bdd81SGreg Kurz { 3900ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3901ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 3902ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 3903bb2bdd81SGreg Kurz const unsigned windows_supported = spapr_phb_windows_supported(sphb); 3904bb2bdd81SGreg Kurz 3905bb2bdd81SGreg Kurz if (dev->hotplugged && !smc->dr_phb_enabled) { 3906bb2bdd81SGreg Kurz error_setg(errp, "PHB hotplug not supported for this machine"); 3907bb2bdd81SGreg Kurz return; 3908bb2bdd81SGreg Kurz } 3909bb2bdd81SGreg Kurz 3910bb2bdd81SGreg Kurz if (sphb->index == (uint32_t)-1) { 3911bb2bdd81SGreg Kurz error_setg(errp, "\"index\" for PAPR PHB is mandatory"); 3912bb2bdd81SGreg Kurz return; 3913bb2bdd81SGreg Kurz } 3914bb2bdd81SGreg Kurz 3915bb2bdd81SGreg Kurz /* 3916bb2bdd81SGreg Kurz * This will check that sphb->index doesn't exceed the maximum number of 3917bb2bdd81SGreg Kurz * PHBs for the current machine type. 3918bb2bdd81SGreg Kurz */ 3919bb2bdd81SGreg Kurz smc->phb_placement(spapr, sphb->index, 3920bb2bdd81SGreg Kurz &sphb->buid, &sphb->io_win_addr, 3921bb2bdd81SGreg Kurz &sphb->mem_win_addr, &sphb->mem64_win_addr, 3922ec132efaSAlexey Kardashevskiy windows_supported, sphb->dma_liobn, 3923ec132efaSAlexey Kardashevskiy &sphb->nv2_gpa_win_addr, &sphb->nv2_atsd_win_addr, 3924ec132efaSAlexey Kardashevskiy errp); 3925bb2bdd81SGreg Kurz } 3926bb2bdd81SGreg Kurz 3927bb2bdd81SGreg Kurz static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3928bb2bdd81SGreg Kurz Error **errp) 3929bb2bdd81SGreg Kurz { 3930ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3931ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 3932ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 3933ce2918cbSDavid Gibson SpaprDrc *drc; 3934bb2bdd81SGreg Kurz bool hotplugged = spapr_drc_hotplugged(dev); 3935bb2bdd81SGreg Kurz 3936bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) { 3937bb2bdd81SGreg Kurz return; 3938bb2bdd81SGreg Kurz } 3939bb2bdd81SGreg Kurz 3940bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); 3941bb2bdd81SGreg Kurz /* hotplug hooks should check it's enabled before getting this far */ 3942bb2bdd81SGreg Kurz assert(drc); 3943bb2bdd81SGreg Kurz 394417548fe6SGreg Kurz if (!spapr_drc_attach(drc, dev, errp)) { 3945bb2bdd81SGreg Kurz return; 3946bb2bdd81SGreg Kurz } 3947bb2bdd81SGreg Kurz 3948bb2bdd81SGreg Kurz if (hotplugged) { 3949bb2bdd81SGreg Kurz spapr_hotplug_req_add_by_index(drc); 3950bb2bdd81SGreg Kurz } else { 3951bb2bdd81SGreg Kurz spapr_drc_reset(drc); 3952bb2bdd81SGreg Kurz } 3953bb2bdd81SGreg Kurz } 3954bb2bdd81SGreg Kurz 3955bb2bdd81SGreg Kurz void spapr_phb_release(DeviceState *dev) 3956bb2bdd81SGreg Kurz { 3957bb2bdd81SGreg Kurz HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3958bb2bdd81SGreg Kurz 3959bb2bdd81SGreg Kurz hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 396007578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 3961bb2bdd81SGreg Kurz } 3962bb2bdd81SGreg Kurz 3963bb2bdd81SGreg Kurz static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 3964bb2bdd81SGreg Kurz { 3965981c3dcdSMarkus Armbruster qdev_unrealize(dev); 3966bb2bdd81SGreg Kurz } 3967bb2bdd81SGreg Kurz 3968bb2bdd81SGreg Kurz static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev, 3969bb2bdd81SGreg Kurz DeviceState *dev, Error **errp) 3970bb2bdd81SGreg Kurz { 3971ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 3972ce2918cbSDavid Gibson SpaprDrc *drc; 3973bb2bdd81SGreg Kurz 3974bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); 3975bb2bdd81SGreg Kurz assert(drc); 3976bb2bdd81SGreg Kurz 3977bb2bdd81SGreg Kurz if (!spapr_drc_unplug_requested(drc)) { 3978bb2bdd81SGreg Kurz spapr_drc_detach(drc); 3979bb2bdd81SGreg Kurz spapr_hotplug_req_remove_by_index(drc); 3980bb2bdd81SGreg Kurz } 3981bb2bdd81SGreg Kurz } 3982bb2bdd81SGreg Kurz 39830fb6bd07SMichael Roth static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 39840fb6bd07SMichael Roth Error **errp) 39850fb6bd07SMichael Roth { 39860fb6bd07SMichael Roth SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 39870fb6bd07SMichael Roth SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(dev); 39880fb6bd07SMichael Roth 39890fb6bd07SMichael Roth if (spapr->tpm_proxy != NULL) { 39900fb6bd07SMichael Roth error_setg(errp, "Only one TPM proxy can be specified for this machine"); 39910fb6bd07SMichael Roth return; 39920fb6bd07SMichael Roth } 39930fb6bd07SMichael Roth 39940fb6bd07SMichael Roth spapr->tpm_proxy = tpm_proxy; 39950fb6bd07SMichael Roth } 39960fb6bd07SMichael Roth 39970fb6bd07SMichael Roth static void spapr_tpm_proxy_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 39980fb6bd07SMichael Roth { 39990fb6bd07SMichael Roth SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 40000fb6bd07SMichael Roth 4001981c3dcdSMarkus Armbruster qdev_unrealize(dev); 40020fb6bd07SMichael Roth object_unparent(OBJECT(dev)); 40030fb6bd07SMichael Roth spapr->tpm_proxy = NULL; 40040fb6bd07SMichael Roth } 40050fb6bd07SMichael Roth 4006c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, 4007c20d332aSBharata B Rao DeviceState *dev, Error **errp) 4008c20d332aSBharata B Rao { 4009c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 401081985f3bSDavid Hildenbrand spapr_memory_plug(hotplug_dev, dev, errp); 4011af81cf32SBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4012af81cf32SBharata B Rao spapr_core_plug(hotplug_dev, dev, errp); 4013bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4014bb2bdd81SGreg Kurz spapr_phb_plug(hotplug_dev, dev, errp); 40150fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 40160fb6bd07SMichael Roth spapr_tpm_proxy_plug(hotplug_dev, dev, errp); 4017c20d332aSBharata B Rao } 4018c20d332aSBharata B Rao } 4019c20d332aSBharata B Rao 402088432f44SDavid Hildenbrand static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, 402188432f44SDavid Hildenbrand DeviceState *dev, Error **errp) 402288432f44SDavid Hildenbrand { 40233ec71474SDavid Hildenbrand if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 40243ec71474SDavid Hildenbrand spapr_memory_unplug(hotplug_dev, dev); 4025a4261be1SDavid Hildenbrand } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4026a4261be1SDavid Hildenbrand spapr_core_unplug(hotplug_dev, dev); 4027bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4028bb2bdd81SGreg Kurz spapr_phb_unplug(hotplug_dev, dev); 40290fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 40300fb6bd07SMichael Roth spapr_tpm_proxy_unplug(hotplug_dev, dev); 40313ec71474SDavid Hildenbrand } 403288432f44SDavid Hildenbrand } 403388432f44SDavid Hildenbrand 4034cf632463SBharata B Rao static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev, 4035cf632463SBharata B Rao DeviceState *dev, Error **errp) 4036cf632463SBharata B Rao { 4037ce2918cbSDavid Gibson SpaprMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev)); 4038c86c1affSDaniel Henrique Barboza MachineClass *mc = MACHINE_GET_CLASS(sms); 4039ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4040cf632463SBharata B Rao 4041cf632463SBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 4042cf632463SBharata B Rao if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) { 4043cf632463SBharata B Rao spapr_memory_unplug_request(hotplug_dev, dev, errp); 4044cf632463SBharata B Rao } else { 4045cf632463SBharata B Rao /* NOTE: this means there is a window after guest reset, prior to 4046cf632463SBharata B Rao * CAS negotiation, where unplug requests will fail due to the 4047cf632463SBharata B Rao * capability not being detected yet. This is a bit different than 4048cf632463SBharata B Rao * the case with PCI unplug, where the events will be queued and 4049cf632463SBharata B Rao * eventually handled by the guest after boot 4050cf632463SBharata B Rao */ 4051cf632463SBharata B Rao error_setg(errp, "Memory hot unplug not supported for this guest"); 4052cf632463SBharata B Rao } 40536f4b5c3eSBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4054c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 40556f4b5c3eSBharata B Rao error_setg(errp, "CPU hot unplug not supported on this machine"); 40566f4b5c3eSBharata B Rao return; 40576f4b5c3eSBharata B Rao } 4058115debf2SIgor Mammedov spapr_core_unplug_request(hotplug_dev, dev, errp); 4059bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4060bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) { 4061bb2bdd81SGreg Kurz error_setg(errp, "PHB hot unplug not supported on this machine"); 4062bb2bdd81SGreg Kurz return; 4063bb2bdd81SGreg Kurz } 4064bb2bdd81SGreg Kurz spapr_phb_unplug_request(hotplug_dev, dev, errp); 40650fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 40660fb6bd07SMichael Roth spapr_tpm_proxy_unplug(hotplug_dev, dev); 4067c20d332aSBharata B Rao } 4068c20d332aSBharata B Rao } 4069c20d332aSBharata B Rao 407094a94e4cSBharata B Rao static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, 407194a94e4cSBharata B Rao DeviceState *dev, Error **errp) 407294a94e4cSBharata B Rao { 4073c871bc70SLaurent Vivier if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 4074c871bc70SLaurent Vivier spapr_memory_pre_plug(hotplug_dev, dev, errp); 4075c871bc70SLaurent Vivier } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 407694a94e4cSBharata B Rao spapr_core_pre_plug(hotplug_dev, dev, errp); 4077bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4078bb2bdd81SGreg Kurz spapr_phb_pre_plug(hotplug_dev, dev, errp); 407994a94e4cSBharata B Rao } 408094a94e4cSBharata B Rao } 408194a94e4cSBharata B Rao 40827ebaf795SBharata B Rao static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine, 4083c20d332aSBharata B Rao DeviceState *dev) 4084c20d332aSBharata B Rao { 408594a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || 4086bb2bdd81SGreg Kurz object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE) || 40870fb6bd07SMichael Roth object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE) || 40880fb6bd07SMichael Roth object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 4089c20d332aSBharata B Rao return HOTPLUG_HANDLER(machine); 4090c20d332aSBharata B Rao } 4091cb600087SDavid Gibson if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { 4092cb600087SDavid Gibson PCIDevice *pcidev = PCI_DEVICE(dev); 4093cb600087SDavid Gibson PCIBus *root = pci_device_root_bus(pcidev); 4094cb600087SDavid Gibson SpaprPhbState *phb = 4095cb600087SDavid Gibson (SpaprPhbState *)object_dynamic_cast(OBJECT(BUS(root)->parent), 4096cb600087SDavid Gibson TYPE_SPAPR_PCI_HOST_BRIDGE); 4097cb600087SDavid Gibson 4098cb600087SDavid Gibson if (phb) { 4099cb600087SDavid Gibson return HOTPLUG_HANDLER(phb); 4100cb600087SDavid Gibson } 4101cb600087SDavid Gibson } 4102c20d332aSBharata B Rao return NULL; 4103c20d332aSBharata B Rao } 4104c20d332aSBharata B Rao 4105ea089eebSIgor Mammedov static CpuInstanceProperties 4106ea089eebSIgor Mammedov spapr_cpu_index_to_props(MachineState *machine, unsigned cpu_index) 410720bb648dSDavid Gibson { 4108ea089eebSIgor Mammedov CPUArchId *core_slot; 4109ea089eebSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 4110ea089eebSIgor Mammedov 4111ea089eebSIgor Mammedov /* make sure possible_cpu are intialized */ 4112ea089eebSIgor Mammedov mc->possible_cpu_arch_ids(machine); 4113ea089eebSIgor Mammedov /* get CPU core slot containing thread that matches cpu_index */ 4114ea089eebSIgor Mammedov core_slot = spapr_find_cpu_slot(machine, cpu_index, NULL); 4115ea089eebSIgor Mammedov assert(core_slot); 4116ea089eebSIgor Mammedov return core_slot->props; 411720bb648dSDavid Gibson } 411820bb648dSDavid Gibson 411979e07936SIgor Mammedov static int64_t spapr_get_default_cpu_node_id(const MachineState *ms, int idx) 412079e07936SIgor Mammedov { 4121aa570207STao Xu return idx / ms->smp.cores % ms->numa_state->num_nodes; 412279e07936SIgor Mammedov } 412379e07936SIgor Mammedov 4124535455fdSIgor Mammedov static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine) 4125535455fdSIgor Mammedov { 4126535455fdSIgor Mammedov int i; 4127fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 4128fe6b6346SLike Xu unsigned int smp_cpus = machine->smp.cpus; 4129d342eb76SIgor Mammedov const char *core_type; 4130fe6b6346SLike Xu int spapr_max_cores = machine->smp.max_cpus / smp_threads; 4131535455fdSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 4132535455fdSIgor Mammedov 4133c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 4134535455fdSIgor Mammedov spapr_max_cores = QEMU_ALIGN_UP(smp_cpus, smp_threads) / smp_threads; 4135535455fdSIgor Mammedov } 4136535455fdSIgor Mammedov if (machine->possible_cpus) { 4137535455fdSIgor Mammedov assert(machine->possible_cpus->len == spapr_max_cores); 4138535455fdSIgor Mammedov return machine->possible_cpus; 4139535455fdSIgor Mammedov } 4140535455fdSIgor Mammedov 4141d342eb76SIgor Mammedov core_type = spapr_get_cpu_core_type(machine->cpu_type); 4142d342eb76SIgor Mammedov if (!core_type) { 4143d342eb76SIgor Mammedov error_report("Unable to find sPAPR CPU Core definition"); 4144d342eb76SIgor Mammedov exit(1); 4145d342eb76SIgor Mammedov } 4146d342eb76SIgor Mammedov 4147535455fdSIgor Mammedov machine->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + 4148535455fdSIgor Mammedov sizeof(CPUArchId) * spapr_max_cores); 4149535455fdSIgor Mammedov machine->possible_cpus->len = spapr_max_cores; 4150535455fdSIgor Mammedov for (i = 0; i < machine->possible_cpus->len; i++) { 4151535455fdSIgor Mammedov int core_id = i * smp_threads; 4152535455fdSIgor Mammedov 4153d342eb76SIgor Mammedov machine->possible_cpus->cpus[i].type = core_type; 4154f2d672c2SIgor Mammedov machine->possible_cpus->cpus[i].vcpus_count = smp_threads; 4155535455fdSIgor Mammedov machine->possible_cpus->cpus[i].arch_id = core_id; 4156535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.has_core_id = true; 4157535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.core_id = core_id; 4158535455fdSIgor Mammedov } 4159535455fdSIgor Mammedov return machine->possible_cpus; 4160535455fdSIgor Mammedov } 4161535455fdSIgor Mammedov 4162ce2918cbSDavid Gibson static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index, 4163daa23699SDavid Gibson uint64_t *buid, hwaddr *pio, 4164daa23699SDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 4165ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4166ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 41676737d9adSDavid Gibson { 4168357d1e3bSDavid Gibson /* 4169357d1e3bSDavid Gibson * New-style PHB window placement. 4170357d1e3bSDavid Gibson * 4171357d1e3bSDavid Gibson * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window 4172357d1e3bSDavid Gibson * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO 4173357d1e3bSDavid Gibson * windows. 4174357d1e3bSDavid Gibson * 4175357d1e3bSDavid Gibson * Some guest kernels can't work with MMIO windows above 1<<46 4176357d1e3bSDavid Gibson * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB 4177357d1e3bSDavid Gibson * 4178357d1e3bSDavid Gibson * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each 4179357d1e3bSDavid Gibson * PHB stacked together. (32TiB+2GiB)..(32TiB+64GiB) contains the 4180357d1e3bSDavid Gibson * 2GiB 32-bit MMIO windows for each PHB. Then 33..64TiB has the 4181357d1e3bSDavid Gibson * 1TiB 64-bit MMIO windows for each PHB. 4182357d1e3bSDavid Gibson */ 41836737d9adSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 41846737d9adSDavid Gibson int i; 41856737d9adSDavid Gibson 4186357d1e3bSDavid Gibson /* Sanity check natural alignments */ 4187357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 4188357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 4189357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0); 4190357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0); 4191357d1e3bSDavid Gibson /* Sanity check bounds */ 419225e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_IO_WIN_SIZE) > 419325e6a118SMichael S. Tsirkin SPAPR_PCI_MEM32_WIN_SIZE); 419425e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_MEM32_WIN_SIZE) > 419525e6a118SMichael S. Tsirkin SPAPR_PCI_MEM64_WIN_SIZE); 41962efff1c0SDavid Gibson 419725e6a118SMichael S. Tsirkin if (index >= SPAPR_MAX_PHBS) { 419825e6a118SMichael S. Tsirkin error_setg(errp, "\"index\" for PAPR PHB is too large (max %llu)", 419925e6a118SMichael S. Tsirkin SPAPR_MAX_PHBS - 1); 42006737d9adSDavid Gibson return; 42016737d9adSDavid Gibson } 42026737d9adSDavid Gibson 42036737d9adSDavid Gibson *buid = base_buid + index; 42046737d9adSDavid Gibson for (i = 0; i < n_dma; ++i) { 42056737d9adSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 42066737d9adSDavid Gibson } 42076737d9adSDavid Gibson 4208357d1e3bSDavid Gibson *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE; 4209357d1e3bSDavid Gibson *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE; 4210357d1e3bSDavid Gibson *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE; 4211ec132efaSAlexey Kardashevskiy 4212ec132efaSAlexey Kardashevskiy *nv2gpa = SPAPR_PCI_NV2RAM64_WIN_BASE + index * SPAPR_PCI_NV2RAM64_WIN_SIZE; 4213ec132efaSAlexey Kardashevskiy *nv2atsd = SPAPR_PCI_NV2ATSD_WIN_BASE + index * SPAPR_PCI_NV2ATSD_WIN_SIZE; 42146737d9adSDavid Gibson } 42156737d9adSDavid Gibson 42167844e12bSCédric Le Goater static ICSState *spapr_ics_get(XICSFabric *dev, int irq) 42177844e12bSCédric Le Goater { 4218ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(dev); 42197844e12bSCédric Le Goater 42207844e12bSCédric Le Goater return ics_valid_irq(spapr->ics, irq) ? spapr->ics : NULL; 42217844e12bSCédric Le Goater } 42227844e12bSCédric Le Goater 42237844e12bSCédric Le Goater static void spapr_ics_resend(XICSFabric *dev) 42247844e12bSCédric Le Goater { 4225ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(dev); 42267844e12bSCédric Le Goater 42277844e12bSCédric Le Goater ics_resend(spapr->ics); 42287844e12bSCédric Le Goater } 42297844e12bSCédric Le Goater 423081210c20SSam Bobroff static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id) 4231b2fc59aaSCédric Le Goater { 42322e886fb3SSam Bobroff PowerPCCPU *cpu = spapr_find_cpu(vcpu_id); 4233b2fc59aaSCédric Le Goater 4234a28b9a5aSCédric Le Goater return cpu ? spapr_cpu_state(cpu)->icp : NULL; 4235b2fc59aaSCédric Le Goater } 4236b2fc59aaSCédric Le Goater 42376449da45SCédric Le Goater static void spapr_pic_print_info(InterruptStatsProvider *obj, 42386449da45SCédric Le Goater Monitor *mon) 42396449da45SCédric Le Goater { 4240ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 42416449da45SCédric Le Goater 4242328d8eb2SDavid Gibson spapr_irq_print_info(spapr, mon); 4243f041d6afSGreg Kurz monitor_printf(mon, "irqchip: %s\n", 4244f041d6afSGreg Kurz kvm_irqchip_in_kernel() ? "in-kernel" : "emulated"); 42456449da45SCédric Le Goater } 42466449da45SCédric Le Goater 4247baa45b17SCédric Le Goater /* 4248baa45b17SCédric Le Goater * This is a XIVE only operation 4249baa45b17SCédric Le Goater */ 4250932de7aeSCédric Le Goater static int spapr_match_nvt(XiveFabric *xfb, uint8_t format, 4251932de7aeSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 4252932de7aeSCédric Le Goater bool cam_ignore, uint8_t priority, 4253932de7aeSCédric Le Goater uint32_t logic_serv, XiveTCTXMatch *match) 4254932de7aeSCédric Le Goater { 4255932de7aeSCédric Le Goater SpaprMachineState *spapr = SPAPR_MACHINE(xfb); 4256baa45b17SCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(spapr->active_intc); 4257932de7aeSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 4258932de7aeSCédric Le Goater int count; 4259932de7aeSCédric Le Goater 4260932de7aeSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 4261932de7aeSCédric Le Goater priority, logic_serv, match); 4262932de7aeSCédric Le Goater if (count < 0) { 4263932de7aeSCédric Le Goater return count; 4264932de7aeSCédric Le Goater } 4265932de7aeSCédric Le Goater 4266932de7aeSCédric Le Goater /* 4267932de7aeSCédric Le Goater * When we implement the save and restore of the thread interrupt 4268932de7aeSCédric Le Goater * contexts in the enter/exit CPU handlers of the machine and the 4269932de7aeSCédric Le Goater * escalations in QEMU, we should be able to handle non dispatched 4270932de7aeSCédric Le Goater * vCPUs. 4271932de7aeSCédric Le Goater * 4272932de7aeSCédric Le Goater * Until this is done, the sPAPR machine should find at least one 4273932de7aeSCédric Le Goater * matching context always. 4274932de7aeSCédric Le Goater */ 4275932de7aeSCédric Le Goater if (count == 0) { 4276932de7aeSCédric Le Goater qemu_log_mask(LOG_GUEST_ERROR, "XIVE: NVT %x/%x is not dispatched\n", 4277932de7aeSCédric Le Goater nvt_blk, nvt_idx); 4278932de7aeSCédric Le Goater } 4279932de7aeSCédric Le Goater 4280932de7aeSCédric Le Goater return count; 4281932de7aeSCédric Le Goater } 4282932de7aeSCédric Le Goater 428314bb4486SGreg Kurz int spapr_get_vcpu_id(PowerPCCPU *cpu) 42842e886fb3SSam Bobroff { 4285b1a568c1SGreg Kurz return cpu->vcpu_id; 42862e886fb3SSam Bobroff } 42872e886fb3SSam Bobroff 4288cfdc5274SGreg Kurz bool spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp) 4289648edb64SGreg Kurz { 4290ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 4291fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 4292648edb64SGreg Kurz int vcpu_id; 4293648edb64SGreg Kurz 42945d0fb150SGreg Kurz vcpu_id = spapr_vcpu_id(spapr, cpu_index); 4295648edb64SGreg Kurz 4296648edb64SGreg Kurz if (kvm_enabled() && !kvm_vcpu_id_is_valid(vcpu_id)) { 4297648edb64SGreg Kurz error_setg(errp, "Can't create CPU with id %d in KVM", vcpu_id); 4298648edb64SGreg Kurz error_append_hint(errp, "Adjust the number of cpus to %d " 4299648edb64SGreg Kurz "or try to raise the number of threads per core\n", 4300fe6b6346SLike Xu vcpu_id * ms->smp.threads / spapr->vsmt); 4301cfdc5274SGreg Kurz return false; 4302648edb64SGreg Kurz } 4303648edb64SGreg Kurz 4304648edb64SGreg Kurz cpu->vcpu_id = vcpu_id; 4305cfdc5274SGreg Kurz return true; 4306648edb64SGreg Kurz } 4307648edb64SGreg Kurz 43082e886fb3SSam Bobroff PowerPCCPU *spapr_find_cpu(int vcpu_id) 43092e886fb3SSam Bobroff { 43102e886fb3SSam Bobroff CPUState *cs; 43112e886fb3SSam Bobroff 43122e886fb3SSam Bobroff CPU_FOREACH(cs) { 43132e886fb3SSam Bobroff PowerPCCPU *cpu = POWERPC_CPU(cs); 43142e886fb3SSam Bobroff 431514bb4486SGreg Kurz if (spapr_get_vcpu_id(cpu) == vcpu_id) { 43162e886fb3SSam Bobroff return cpu; 43172e886fb3SSam Bobroff } 43182e886fb3SSam Bobroff } 43192e886fb3SSam Bobroff 43202e886fb3SSam Bobroff return NULL; 43212e886fb3SSam Bobroff } 43222e886fb3SSam Bobroff 432303ef074cSNicholas Piggin static void spapr_cpu_exec_enter(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) 432403ef074cSNicholas Piggin { 432503ef074cSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 432603ef074cSNicholas Piggin 432703ef074cSNicholas Piggin /* These are only called by TCG, KVM maintains dispatch state */ 432803ef074cSNicholas Piggin 43293a6e6224SNicholas Piggin spapr_cpu->prod = false; 433003ef074cSNicholas Piggin if (spapr_cpu->vpa_addr) { 433103ef074cSNicholas Piggin CPUState *cs = CPU(cpu); 433203ef074cSNicholas Piggin uint32_t dispatch; 433303ef074cSNicholas Piggin 433403ef074cSNicholas Piggin dispatch = ldl_be_phys(cs->as, 433503ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER); 433603ef074cSNicholas Piggin dispatch++; 433703ef074cSNicholas Piggin if ((dispatch & 1) != 0) { 433803ef074cSNicholas Piggin qemu_log_mask(LOG_GUEST_ERROR, 433903ef074cSNicholas Piggin "VPA: incorrect dispatch counter value for " 434003ef074cSNicholas Piggin "dispatched partition %u, correcting.\n", dispatch); 434103ef074cSNicholas Piggin dispatch++; 434203ef074cSNicholas Piggin } 434303ef074cSNicholas Piggin stl_be_phys(cs->as, 434403ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch); 434503ef074cSNicholas Piggin } 434603ef074cSNicholas Piggin } 434703ef074cSNicholas Piggin 434803ef074cSNicholas Piggin static void spapr_cpu_exec_exit(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) 434903ef074cSNicholas Piggin { 435003ef074cSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 435103ef074cSNicholas Piggin 435203ef074cSNicholas Piggin if (spapr_cpu->vpa_addr) { 435303ef074cSNicholas Piggin CPUState *cs = CPU(cpu); 435403ef074cSNicholas Piggin uint32_t dispatch; 435503ef074cSNicholas Piggin 435603ef074cSNicholas Piggin dispatch = ldl_be_phys(cs->as, 435703ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER); 435803ef074cSNicholas Piggin dispatch++; 435903ef074cSNicholas Piggin if ((dispatch & 1) != 1) { 436003ef074cSNicholas Piggin qemu_log_mask(LOG_GUEST_ERROR, 436103ef074cSNicholas Piggin "VPA: incorrect dispatch counter value for " 436203ef074cSNicholas Piggin "preempted partition %u, correcting.\n", dispatch); 436303ef074cSNicholas Piggin dispatch++; 436403ef074cSNicholas Piggin } 436503ef074cSNicholas Piggin stl_be_phys(cs->as, 436603ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch); 436703ef074cSNicholas Piggin } 436803ef074cSNicholas Piggin } 436903ef074cSNicholas Piggin 437029ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data) 437153018216SPaolo Bonzini { 437229ee3247SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 4373ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(oc); 437471461b0fSAlexey Kardashevskiy FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); 437534316482SAlexey Kardashevskiy NMIClass *nc = NMI_CLASS(oc); 4376c20d332aSBharata B Rao HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); 43771d1be34dSDavid Gibson PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc); 43787844e12bSCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 43796449da45SCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 4380932de7aeSCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 438129ee3247SAlexey Kardashevskiy 43820eb9054cSDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant)"; 4383907aac2fSMark Cave-Ayland mc->ignore_boot_device_suffixes = true; 4384fc9f38c3SDavid Gibson 4385fc9f38c3SDavid Gibson /* 4386fc9f38c3SDavid Gibson * We set up the default / latest behaviour here. The class_init 4387fc9f38c3SDavid Gibson * functions for the specific versioned machine types can override 4388fc9f38c3SDavid Gibson * these details for backwards compatibility 4389fc9f38c3SDavid Gibson */ 4390bcb5ce08SDavid Gibson mc->init = spapr_machine_init; 4391bcb5ce08SDavid Gibson mc->reset = spapr_machine_reset; 4392958db90cSMarcel Apfelbaum mc->block_default_type = IF_SCSI; 43936244bb7eSGreg Kurz mc->max_cpus = 1024; 4394958db90cSMarcel Apfelbaum mc->no_parallel = 1; 43955b2128d2SAlexander Graf mc->default_boot_order = ""; 4396d23b6caaSPhilippe Mathieu-Daudé mc->default_ram_size = 512 * MiB; 4397ab74e543SIgor Mammedov mc->default_ram_id = "ppc_spapr.ram"; 439829f9cef3SSebastian Bauer mc->default_display = "std"; 4399958db90cSMarcel Apfelbaum mc->kvm_type = spapr_kvm_type; 44007da79a16SEduardo Habkost machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SPAPR_PCI_HOST_BRIDGE); 4401e4024630SLaurent Vivier mc->pci_allow_0_address = true; 4402debbdc00SIgor Mammedov assert(!mc->get_hotplug_handler); 44037ebaf795SBharata B Rao mc->get_hotplug_handler = spapr_get_hotplug_handler; 440494a94e4cSBharata B Rao hc->pre_plug = spapr_machine_device_pre_plug; 4405c20d332aSBharata B Rao hc->plug = spapr_machine_device_plug; 4406ea089eebSIgor Mammedov mc->cpu_index_to_instance_props = spapr_cpu_index_to_props; 440779e07936SIgor Mammedov mc->get_default_cpu_node_id = spapr_get_default_cpu_node_id; 4408535455fdSIgor Mammedov mc->possible_cpu_arch_ids = spapr_possible_cpu_arch_ids; 4409cf632463SBharata B Rao hc->unplug_request = spapr_machine_device_unplug_request; 441088432f44SDavid Hildenbrand hc->unplug = spapr_machine_device_unplug; 441100b4fbe2SMarcel Apfelbaum 4412fc9f38c3SDavid Gibson smc->dr_lmb_enabled = true; 4413fea35ca4SAlexey Kardashevskiy smc->update_dt_enabled = true; 441434a6b015SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 4415c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = true; 4416ee3a71e3SShivaprasad G Bhat mc->nvdimm_supported = true; 441752b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED; 441871461b0fSAlexey Kardashevskiy fwc->get_dev_path = spapr_get_fw_dev_path; 441934316482SAlexey Kardashevskiy nc->nmi_monitor_handler = spapr_nmi; 44206737d9adSDavid Gibson smc->phb_placement = spapr_phb_placement; 44211d1be34dSDavid Gibson vhc->hypercall = emulate_spapr_hypercall; 4422e57ca75cSDavid Gibson vhc->hpt_mask = spapr_hpt_mask; 4423e57ca75cSDavid Gibson vhc->map_hptes = spapr_map_hptes; 4424e57ca75cSDavid Gibson vhc->unmap_hptes = spapr_unmap_hptes; 4425a2dd4e83SBenjamin Herrenschmidt vhc->hpte_set_c = spapr_hpte_set_c; 4426a2dd4e83SBenjamin Herrenschmidt vhc->hpte_set_r = spapr_hpte_set_r; 442779825f4dSBenjamin Herrenschmidt vhc->get_pate = spapr_get_pate; 44281ec26c75SGreg Kurz vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr; 442903ef074cSNicholas Piggin vhc->cpu_exec_enter = spapr_cpu_exec_enter; 443003ef074cSNicholas Piggin vhc->cpu_exec_exit = spapr_cpu_exec_exit; 44317844e12bSCédric Le Goater xic->ics_get = spapr_ics_get; 44327844e12bSCédric Le Goater xic->ics_resend = spapr_ics_resend; 4433b2fc59aaSCédric Le Goater xic->icp_get = spapr_icp_get; 44346449da45SCédric Le Goater ispc->print_info = spapr_pic_print_info; 443555641213SLaurent Vivier /* Force NUMA node memory size to be a multiple of 443655641213SLaurent Vivier * SPAPR_MEMORY_BLOCK_SIZE (256M) since that's the granularity 443755641213SLaurent Vivier * in which LMBs are represented and hot-added 443855641213SLaurent Vivier */ 443955641213SLaurent Vivier mc->numa_mem_align_shift = 28; 44400533ef5fSTao Xu mc->auto_enable_numa = true; 444133face6bSDavid Gibson 44424e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF; 44434e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON; 44444e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON; 44452782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND; 44462782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND; 44472782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_WORKAROUND; 44482309832aSDavid Gibson smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */ 4449b9a477b7SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF; 4450edaa7995SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON; 445137965dfeSDavid Gibson smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_ON; 44528af7e1feSNicholas Piggin smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_ON; 445340c2281cSMarkus Armbruster spapr_caps_add_properties(smc); 4454bd94bc06SCédric Le Goater smc->irq = &spapr_irq_dual; 4455dae5e39aSMichael Roth smc->dr_phb_enabled = true; 44566c3829a2SAlexey Kardashevskiy smc->linux_pci_probe = true; 445729cb4187SGreg Kurz smc->smp_threads_vsmt = true; 445854255c1fSDavid Gibson smc->nr_xirqs = SPAPR_NR_XIRQS; 4459932de7aeSCédric Le Goater xfc->match_nvt = spapr_match_nvt; 446053018216SPaolo Bonzini } 446153018216SPaolo Bonzini 446229ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = { 446329ee3247SAlexey Kardashevskiy .name = TYPE_SPAPR_MACHINE, 446429ee3247SAlexey Kardashevskiy .parent = TYPE_MACHINE, 44654aee7362SDavid Gibson .abstract = true, 4466ce2918cbSDavid Gibson .instance_size = sizeof(SpaprMachineState), 4467bcb5ce08SDavid Gibson .instance_init = spapr_instance_init, 446887bbdd9cSDavid Gibson .instance_finalize = spapr_machine_finalizefn, 4469ce2918cbSDavid Gibson .class_size = sizeof(SpaprMachineClass), 447029ee3247SAlexey Kardashevskiy .class_init = spapr_machine_class_init, 447171461b0fSAlexey Kardashevskiy .interfaces = (InterfaceInfo[]) { 447271461b0fSAlexey Kardashevskiy { TYPE_FW_PATH_PROVIDER }, 447334316482SAlexey Kardashevskiy { TYPE_NMI }, 4474c20d332aSBharata B Rao { TYPE_HOTPLUG_HANDLER }, 44751d1be34dSDavid Gibson { TYPE_PPC_VIRTUAL_HYPERVISOR }, 44767844e12bSCédric Le Goater { TYPE_XICS_FABRIC }, 44776449da45SCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 4478932de7aeSCédric Le Goater { TYPE_XIVE_FABRIC }, 447971461b0fSAlexey Kardashevskiy { } 448071461b0fSAlexey Kardashevskiy }, 448129ee3247SAlexey Kardashevskiy }; 448229ee3247SAlexey Kardashevskiy 4483a7849268SMichael S. Tsirkin static void spapr_machine_latest_class_options(MachineClass *mc) 4484a7849268SMichael S. Tsirkin { 4485a7849268SMichael S. Tsirkin mc->alias = "pseries"; 4486ea0ac7f6SPhilippe Mathieu-Daudé mc->is_default = true; 4487a7849268SMichael S. Tsirkin } 4488a7849268SMichael S. Tsirkin 4489fccbc785SDavid Gibson #define DEFINE_SPAPR_MACHINE(suffix, verstr, latest) \ 44905013c547SDavid Gibson static void spapr_machine_##suffix##_class_init(ObjectClass *oc, \ 44915013c547SDavid Gibson void *data) \ 44925013c547SDavid Gibson { \ 44935013c547SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); \ 44945013c547SDavid Gibson spapr_machine_##suffix##_class_options(mc); \ 4495fccbc785SDavid Gibson if (latest) { \ 4496a7849268SMichael S. Tsirkin spapr_machine_latest_class_options(mc); \ 4497fccbc785SDavid Gibson } \ 44985013c547SDavid Gibson } \ 44995013c547SDavid Gibson static const TypeInfo spapr_machine_##suffix##_info = { \ 45005013c547SDavid Gibson .name = MACHINE_TYPE_NAME("pseries-" verstr), \ 45015013c547SDavid Gibson .parent = TYPE_SPAPR_MACHINE, \ 45025013c547SDavid Gibson .class_init = spapr_machine_##suffix##_class_init, \ 45035013c547SDavid Gibson }; \ 45045013c547SDavid Gibson static void spapr_machine_register_##suffix(void) \ 45055013c547SDavid Gibson { \ 45065013c547SDavid Gibson type_register(&spapr_machine_##suffix##_info); \ 45075013c547SDavid Gibson } \ 45080e6aac87SEduardo Habkost type_init(spapr_machine_register_##suffix) 45095013c547SDavid Gibson 45101c5f29bbSDavid Gibson /* 4511576a00bdSCornelia Huck * pseries-6.0 45123eb74d20SCornelia Huck */ 4513576a00bdSCornelia Huck static void spapr_machine_6_0_class_options(MachineClass *mc) 45143eb74d20SCornelia Huck { 45153eb74d20SCornelia Huck /* Defaults for the latest behaviour inherited from the base class */ 45163eb74d20SCornelia Huck } 45173eb74d20SCornelia Huck 4518576a00bdSCornelia Huck DEFINE_SPAPR_MACHINE(6_0, "6.0", true); 4519576a00bdSCornelia Huck 4520576a00bdSCornelia Huck /* 4521576a00bdSCornelia Huck * pseries-5.2 4522576a00bdSCornelia Huck */ 4523576a00bdSCornelia Huck static void spapr_machine_5_2_class_options(MachineClass *mc) 4524576a00bdSCornelia Huck { 4525576a00bdSCornelia Huck spapr_machine_6_0_class_options(mc); 4526576a00bdSCornelia Huck compat_props_add(mc->compat_props, hw_compat_5_2, hw_compat_5_2_len); 4527576a00bdSCornelia Huck } 4528576a00bdSCornelia Huck 4529576a00bdSCornelia Huck DEFINE_SPAPR_MACHINE(5_2, "5.2", false); 45303ff3c5d3SCornelia Huck 45313ff3c5d3SCornelia Huck /* 45323ff3c5d3SCornelia Huck * pseries-5.1 45333ff3c5d3SCornelia Huck */ 45343ff3c5d3SCornelia Huck static void spapr_machine_5_1_class_options(MachineClass *mc) 45353ff3c5d3SCornelia Huck { 453629bfe52aSDaniel Henrique Barboza SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 453729bfe52aSDaniel Henrique Barboza 45383ff3c5d3SCornelia Huck spapr_machine_5_2_class_options(mc); 45393ff3c5d3SCornelia Huck compat_props_add(mc->compat_props, hw_compat_5_1, hw_compat_5_1_len); 454029bfe52aSDaniel Henrique Barboza smc->pre_5_2_numa_associativity = true; 45413ff3c5d3SCornelia Huck } 45423ff3c5d3SCornelia Huck 45433ff3c5d3SCornelia Huck DEFINE_SPAPR_MACHINE(5_1, "5.1", false); 4544541aaa1dSCornelia Huck 4545541aaa1dSCornelia Huck /* 4546541aaa1dSCornelia Huck * pseries-5.0 4547541aaa1dSCornelia Huck */ 4548541aaa1dSCornelia Huck static void spapr_machine_5_0_class_options(MachineClass *mc) 4549541aaa1dSCornelia Huck { 4550a6030d7eSReza Arbab SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4551a6030d7eSReza Arbab static GlobalProperty compat[] = { 4552a6030d7eSReza Arbab { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-5.1-associativity", "on" }, 4553a6030d7eSReza Arbab }; 4554a6030d7eSReza Arbab 4555541aaa1dSCornelia Huck spapr_machine_5_1_class_options(mc); 4556541aaa1dSCornelia Huck compat_props_add(mc->compat_props, hw_compat_5_0, hw_compat_5_0_len); 4557a6030d7eSReza Arbab compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 455832a354dcSIgor Mammedov mc->numa_mem_supported = true; 4559a6030d7eSReza Arbab smc->pre_5_1_assoc_refpoints = true; 4560541aaa1dSCornelia Huck } 4561541aaa1dSCornelia Huck 4562541aaa1dSCornelia Huck DEFINE_SPAPR_MACHINE(5_0, "5.0", false); 45633eb74d20SCornelia Huck 45643eb74d20SCornelia Huck /* 45659aec2e52SCornelia Huck * pseries-4.2 4566e2676b16SGreg Kurz */ 45679aec2e52SCornelia Huck static void spapr_machine_4_2_class_options(MachineClass *mc) 4568e2676b16SGreg Kurz { 456937965dfeSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 457037965dfeSDavid Gibson 45713eb74d20SCornelia Huck spapr_machine_5_0_class_options(mc); 45725f258577SEvgeny Yakovlev compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len); 457337965dfeSDavid Gibson smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF; 45748af7e1feSNicholas Piggin smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_OFF; 45751052ab67SDavid Gibson smc->rma_limit = 16 * GiB; 4576ee3a71e3SShivaprasad G Bhat mc->nvdimm_supported = false; 4577e2676b16SGreg Kurz } 4578e2676b16SGreg Kurz 45793eb74d20SCornelia Huck DEFINE_SPAPR_MACHINE(4_2, "4.2", false); 45809aec2e52SCornelia Huck 45819aec2e52SCornelia Huck /* 45829aec2e52SCornelia Huck * pseries-4.1 45839aec2e52SCornelia Huck */ 45849aec2e52SCornelia Huck static void spapr_machine_4_1_class_options(MachineClass *mc) 45859aec2e52SCornelia Huck { 45866c3829a2SAlexey Kardashevskiy SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4587d15d4ad6SDavid Gibson static GlobalProperty compat[] = { 4588d15d4ad6SDavid Gibson /* Only allow 4kiB and 64kiB IOMMU pagesizes */ 4589d15d4ad6SDavid Gibson { TYPE_SPAPR_PCI_HOST_BRIDGE, "pgsz", "0x11000" }, 4590d15d4ad6SDavid Gibson }; 4591d15d4ad6SDavid Gibson 45929aec2e52SCornelia Huck spapr_machine_4_2_class_options(mc); 45936c3829a2SAlexey Kardashevskiy smc->linux_pci_probe = false; 459429cb4187SGreg Kurz smc->smp_threads_vsmt = false; 45959aec2e52SCornelia Huck compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len); 4596d15d4ad6SDavid Gibson compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 45979aec2e52SCornelia Huck } 45989aec2e52SCornelia Huck 45999aec2e52SCornelia Huck DEFINE_SPAPR_MACHINE(4_1, "4.1", false); 46009bf2650bSCornelia Huck 46019bf2650bSCornelia Huck /* 46029bf2650bSCornelia Huck * pseries-4.0 46039bf2650bSCornelia Huck */ 4604eb3cba82SDavid Gibson static void phb_placement_4_0(SpaprMachineState *spapr, uint32_t index, 4605ec132efaSAlexey Kardashevskiy uint64_t *buid, hwaddr *pio, 4606ec132efaSAlexey Kardashevskiy hwaddr *mmio32, hwaddr *mmio64, 4607ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4608ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 4609ec132efaSAlexey Kardashevskiy { 4610ec132efaSAlexey Kardashevskiy spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma, liobns, 4611ec132efaSAlexey Kardashevskiy nv2gpa, nv2atsd, errp); 4612ec132efaSAlexey Kardashevskiy *nv2gpa = 0; 4613ec132efaSAlexey Kardashevskiy *nv2atsd = 0; 4614ec132efaSAlexey Kardashevskiy } 4615ec132efaSAlexey Kardashevskiy 4616eb3cba82SDavid Gibson static void spapr_machine_4_0_class_options(MachineClass *mc) 4617eb3cba82SDavid Gibson { 4618eb3cba82SDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4619eb3cba82SDavid Gibson 4620eb3cba82SDavid Gibson spapr_machine_4_1_class_options(mc); 4621eb3cba82SDavid Gibson compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); 4622eb3cba82SDavid Gibson smc->phb_placement = phb_placement_4_0; 4623bd94bc06SCédric Le Goater smc->irq = &spapr_irq_xics; 46243725ef1aSGreg Kurz smc->pre_4_1_migration = true; 4625eb3cba82SDavid Gibson } 4626eb3cba82SDavid Gibson 4627eb3cba82SDavid Gibson DEFINE_SPAPR_MACHINE(4_0, "4.0", false); 4628eb3cba82SDavid Gibson 4629eb3cba82SDavid Gibson /* 4630eb3cba82SDavid Gibson * pseries-3.1 4631eb3cba82SDavid Gibson */ 463288cbe073SMarc-André Lureau static void spapr_machine_3_1_class_options(MachineClass *mc) 463388cbe073SMarc-André Lureau { 4634ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4635fea35ca4SAlexey Kardashevskiy 463684e060bfSAlex Williamson spapr_machine_4_0_class_options(mc); 4637abd93cc7SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len); 463827461d69SPrasad J Pandit 463934a6b015SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 4640fea35ca4SAlexey Kardashevskiy smc->update_dt_enabled = false; 4641dae5e39aSMichael Roth smc->dr_phb_enabled = false; 46420a794529SDavid Gibson smc->broken_host_serial_model = true; 46432782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN; 46442782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN; 46452782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN; 4646edaa7995SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF; 464784e060bfSAlex Williamson } 464884e060bfSAlex Williamson 464984e060bfSAlex Williamson DEFINE_SPAPR_MACHINE(3_1, "3.1", false); 4650d45360d9SCédric Le Goater 4651d45360d9SCédric Le Goater /* 4652d45360d9SCédric Le Goater * pseries-3.0 4653d45360d9SCédric Le Goater */ 4654d45360d9SCédric Le Goater 4655d45360d9SCédric Le Goater static void spapr_machine_3_0_class_options(MachineClass *mc) 4656d45360d9SCédric Le Goater { 4657ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 465882cffa2eSCédric Le Goater 4659d45360d9SCédric Le Goater spapr_machine_3_1_class_options(mc); 4660ddb3235dSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len); 466182cffa2eSCédric Le Goater 466282cffa2eSCédric Le Goater smc->legacy_irq_allocation = true; 466354255c1fSDavid Gibson smc->nr_xirqs = 0x400; 4664ae837402SCédric Le Goater smc->irq = &spapr_irq_xics_legacy; 4665d45360d9SCédric Le Goater } 4666d45360d9SCédric Le Goater 4667d45360d9SCédric Le Goater DEFINE_SPAPR_MACHINE(3_0, "3.0", false); 46688a4fd427SDavid Gibson 46698a4fd427SDavid Gibson /* 46708a4fd427SDavid Gibson * pseries-2.12 46718a4fd427SDavid Gibson */ 467288cbe073SMarc-André Lureau static void spapr_machine_2_12_class_options(MachineClass *mc) 467388cbe073SMarc-André Lureau { 4674ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 467588cbe073SMarc-André Lureau static GlobalProperty compat[] = { 46766c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-3.0-migration", "on" }, 46776c36bddfSEduardo Habkost { TYPE_SPAPR_CPU_CORE, "pre-3.0-migration", "on" }, 4678fa386d98SMarc-André Lureau }; 46798a4fd427SDavid Gibson 4680d8c0c7afSPeter Maydell spapr_machine_3_0_class_options(mc); 46810d47310bSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_12, hw_compat_2_12_len); 468288cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 46832309832aSDavid Gibson 4684e8937295SGreg Kurz /* We depend on kvm_enabled() to choose a default value for the 4685e8937295SGreg Kurz * hpt-max-page-size capability. Of course we can't do it here 4686e8937295SGreg Kurz * because this is too early and the HW accelerator isn't initialzed 4687e8937295SGreg Kurz * yet. Postpone this to machine init (see default_caps_with_cpu()). 4688e8937295SGreg Kurz */ 4689e8937295SGreg Kurz smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 0; 46908a4fd427SDavid Gibson } 46918a4fd427SDavid Gibson 46928a4fd427SDavid Gibson DEFINE_SPAPR_MACHINE(2_12, "2.12", false); 46932b615412SDavid Gibson 4694813f3cf6SSuraj Jitindar Singh static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc) 4695813f3cf6SSuraj Jitindar Singh { 4696ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4697813f3cf6SSuraj Jitindar Singh 4698813f3cf6SSuraj Jitindar Singh spapr_machine_2_12_class_options(mc); 4699813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND; 4700813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND; 4701813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_FIXED_CCD; 4702813f3cf6SSuraj Jitindar Singh } 4703813f3cf6SSuraj Jitindar Singh 4704813f3cf6SSuraj Jitindar Singh DEFINE_SPAPR_MACHINE(2_12_sxxm, "2.12-sxxm", false); 4705813f3cf6SSuraj Jitindar Singh 47062b615412SDavid Gibson /* 47072b615412SDavid Gibson * pseries-2.11 47082b615412SDavid Gibson */ 47092b615412SDavid Gibson 47102b615412SDavid Gibson static void spapr_machine_2_11_class_options(MachineClass *mc) 47112b615412SDavid Gibson { 4712ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4713ee76a09fSDavid Gibson 47142b615412SDavid Gibson spapr_machine_2_12_class_options(mc); 47154e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON; 471643df70a9SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len); 47172b615412SDavid Gibson } 47182b615412SDavid Gibson 47192b615412SDavid Gibson DEFINE_SPAPR_MACHINE(2_11, "2.11", false); 4720e2676b16SGreg Kurz 4721e2676b16SGreg Kurz /* 47223fa14fbeSDavid Gibson * pseries-2.10 4723db800b21SDavid Gibson */ 4724e2676b16SGreg Kurz 47253fa14fbeSDavid Gibson static void spapr_machine_2_10_class_options(MachineClass *mc) 4726db800b21SDavid Gibson { 4727e2676b16SGreg Kurz spapr_machine_2_11_class_options(mc); 4728503224f4SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_10, hw_compat_2_10_len); 4729db800b21SDavid Gibson } 4730db800b21SDavid Gibson 4731e2676b16SGreg Kurz DEFINE_SPAPR_MACHINE(2_10, "2.10", false); 47323fa14fbeSDavid Gibson 47333fa14fbeSDavid Gibson /* 47343fa14fbeSDavid Gibson * pseries-2.9 47353fa14fbeSDavid Gibson */ 473688cbe073SMarc-André Lureau 473788cbe073SMarc-André Lureau static void spapr_machine_2_9_class_options(MachineClass *mc) 473888cbe073SMarc-André Lureau { 4739ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 474088cbe073SMarc-André Lureau static GlobalProperty compat[] = { 47416c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-2.10-migration", "on" }, 4742fa386d98SMarc-André Lureau }; 47433fa14fbeSDavid Gibson 47443fa14fbeSDavid Gibson spapr_machine_2_10_class_options(mc); 47453e803152SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len); 474688cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 474746f7afa3SGreg Kurz smc->pre_2_10_has_unused_icps = true; 474852b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED; 47493fa14fbeSDavid Gibson } 47503fa14fbeSDavid Gibson 47513fa14fbeSDavid Gibson DEFINE_SPAPR_MACHINE(2_9, "2.9", false); 4752fa325e6cSDavid Gibson 4753fa325e6cSDavid Gibson /* 4754fa325e6cSDavid Gibson * pseries-2.8 4755fa325e6cSDavid Gibson */ 475688cbe073SMarc-André Lureau 475788cbe073SMarc-André Lureau static void spapr_machine_2_8_class_options(MachineClass *mc) 475888cbe073SMarc-André Lureau { 475988cbe073SMarc-André Lureau static GlobalProperty compat[] = { 47606c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "pcie-extended-configuration-space", "off" }, 4761fa386d98SMarc-André Lureau }; 4762fa325e6cSDavid Gibson 4763fa325e6cSDavid Gibson spapr_machine_2_9_class_options(mc); 4764edc24ccdSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len); 476588cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 476655641213SLaurent Vivier mc->numa_mem_align_shift = 23; 4767fa325e6cSDavid Gibson } 4768fa325e6cSDavid Gibson 4769fa325e6cSDavid Gibson DEFINE_SPAPR_MACHINE(2_8, "2.8", false); 4770db800b21SDavid Gibson 4771db800b21SDavid Gibson /* 47721ea1eefcSBharata B Rao * pseries-2.7 47731ea1eefcSBharata B Rao */ 4774357d1e3bSDavid Gibson 4775ce2918cbSDavid Gibson static void phb_placement_2_7(SpaprMachineState *spapr, uint32_t index, 4776357d1e3bSDavid Gibson uint64_t *buid, hwaddr *pio, 4777357d1e3bSDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 4778ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4779ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 4780357d1e3bSDavid Gibson { 4781357d1e3bSDavid Gibson /* Legacy PHB placement for pseries-2.7 and earlier machine types */ 4782357d1e3bSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 4783357d1e3bSDavid Gibson const hwaddr phb_spacing = 0x1000000000ULL; /* 64 GiB */ 4784357d1e3bSDavid Gibson const hwaddr mmio_offset = 0xa0000000; /* 2 GiB + 512 MiB */ 4785357d1e3bSDavid Gibson const hwaddr pio_offset = 0x80000000; /* 2 GiB */ 4786357d1e3bSDavid Gibson const uint32_t max_index = 255; 4787357d1e3bSDavid Gibson const hwaddr phb0_alignment = 0x10000000000ULL; /* 1 TiB */ 4788357d1e3bSDavid Gibson 4789357d1e3bSDavid Gibson uint64_t ram_top = MACHINE(spapr)->ram_size; 4790357d1e3bSDavid Gibson hwaddr phb0_base, phb_base; 4791357d1e3bSDavid Gibson int i; 4792357d1e3bSDavid Gibson 47930c9269a5SDavid Hildenbrand /* Do we have device memory? */ 4794357d1e3bSDavid Gibson if (MACHINE(spapr)->maxram_size > ram_top) { 4795357d1e3bSDavid Gibson /* Can't just use maxram_size, because there may be an 47960c9269a5SDavid Hildenbrand * alignment gap between normal and device memory regions 47970c9269a5SDavid Hildenbrand */ 4798b0c14ec4SDavid Hildenbrand ram_top = MACHINE(spapr)->device_memory->base + 4799b0c14ec4SDavid Hildenbrand memory_region_size(&MACHINE(spapr)->device_memory->mr); 4800357d1e3bSDavid Gibson } 4801357d1e3bSDavid Gibson 4802357d1e3bSDavid Gibson phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment); 4803357d1e3bSDavid Gibson 4804357d1e3bSDavid Gibson if (index > max_index) { 4805357d1e3bSDavid Gibson error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", 4806357d1e3bSDavid Gibson max_index); 4807357d1e3bSDavid Gibson return; 4808357d1e3bSDavid Gibson } 4809357d1e3bSDavid Gibson 4810357d1e3bSDavid Gibson *buid = base_buid + index; 4811357d1e3bSDavid Gibson for (i = 0; i < n_dma; ++i) { 4812357d1e3bSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 4813357d1e3bSDavid Gibson } 4814357d1e3bSDavid Gibson 4815357d1e3bSDavid Gibson phb_base = phb0_base + index * phb_spacing; 4816357d1e3bSDavid Gibson *pio = phb_base + pio_offset; 4817357d1e3bSDavid Gibson *mmio32 = phb_base + mmio_offset; 4818357d1e3bSDavid Gibson /* 4819357d1e3bSDavid Gibson * We don't set the 64-bit MMIO window, relying on the PHB's 4820357d1e3bSDavid Gibson * fallback behaviour of automatically splitting a large "32-bit" 4821357d1e3bSDavid Gibson * window into contiguous 32-bit and 64-bit windows 4822357d1e3bSDavid Gibson */ 4823ec132efaSAlexey Kardashevskiy 4824ec132efaSAlexey Kardashevskiy *nv2gpa = 0; 4825ec132efaSAlexey Kardashevskiy *nv2atsd = 0; 4826357d1e3bSDavid Gibson } 4827db800b21SDavid Gibson 48281ea1eefcSBharata B Rao static void spapr_machine_2_7_class_options(MachineClass *mc) 48291ea1eefcSBharata B Rao { 4830ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 483188cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48326c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0xf80000000", }, 48336c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem64_win_size", "0", }, 48346c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-2.8-migration", "on", }, 48356c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-2.8-migration", "on", }, 483688cbe073SMarc-André Lureau }; 48373daa4a9fSThomas Huth 4838db800b21SDavid Gibson spapr_machine_2_8_class_options(mc); 48392e9c10ebSIgor Mammedov mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power7_v2.3"); 4840a140c199SEduardo Habkost mc->default_machine_opts = "modern-hotplug-events=off"; 48415a995064SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_7, hw_compat_2_7_len); 484288cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 4843357d1e3bSDavid Gibson smc->phb_placement = phb_placement_2_7; 48441ea1eefcSBharata B Rao } 48451ea1eefcSBharata B Rao 4846db800b21SDavid Gibson DEFINE_SPAPR_MACHINE(2_7, "2.7", false); 48471ea1eefcSBharata B Rao 48481ea1eefcSBharata B Rao /* 48494b23699cSDavid Gibson * pseries-2.6 48504b23699cSDavid Gibson */ 485188cbe073SMarc-André Lureau 485288cbe073SMarc-André Lureau static void spapr_machine_2_6_class_options(MachineClass *mc) 485388cbe073SMarc-André Lureau { 485488cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48556c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "ddw", "off" }, 4856fa386d98SMarc-André Lureau }; 48571ea1eefcSBharata B Rao 48581ea1eefcSBharata B Rao spapr_machine_2_7_class_options(mc); 4859c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = false; 4860ff8f261fSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_6, hw_compat_2_6_len); 486188cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 48624b23699cSDavid Gibson } 48634b23699cSDavid Gibson 48641ea1eefcSBharata B Rao DEFINE_SPAPR_MACHINE(2_6, "2.6", false); 48654b23699cSDavid Gibson 48664b23699cSDavid Gibson /* 48671c5f29bbSDavid Gibson * pseries-2.5 48681c5f29bbSDavid Gibson */ 486988cbe073SMarc-André Lureau 487088cbe073SMarc-André Lureau static void spapr_machine_2_5_class_options(MachineClass *mc) 487188cbe073SMarc-André Lureau { 4872ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 487388cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48746c36bddfSEduardo Habkost { "spapr-vlan", "use-rx-buffer-pools", "off" }, 4875fa386d98SMarc-André Lureau }; 48764b23699cSDavid Gibson 48774b23699cSDavid Gibson spapr_machine_2_6_class_options(mc); 487857040d45SThomas Huth smc->use_ohci_by_default = true; 4879fe759610SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_5, hw_compat_2_5_len); 488088cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 48811c5f29bbSDavid Gibson } 48821c5f29bbSDavid Gibson 48834b23699cSDavid Gibson DEFINE_SPAPR_MACHINE(2_5, "2.5", false); 48841c5f29bbSDavid Gibson 48851c5f29bbSDavid Gibson /* 48861c5f29bbSDavid Gibson * pseries-2.4 48871c5f29bbSDavid Gibson */ 488880fd50f9SCornelia Huck 48895013c547SDavid Gibson static void spapr_machine_2_4_class_options(MachineClass *mc) 48905013c547SDavid Gibson { 4891ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4892fc9f38c3SDavid Gibson 4893fc9f38c3SDavid Gibson spapr_machine_2_5_class_options(mc); 4894fc9f38c3SDavid Gibson smc->dr_lmb_enabled = false; 48952f99b9c2SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_4, hw_compat_2_4_len); 48961c5f29bbSDavid Gibson } 48971c5f29bbSDavid Gibson 4898fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_4, "2.4", false); 48991c5f29bbSDavid Gibson 49001c5f29bbSDavid Gibson /* 49011c5f29bbSDavid Gibson * pseries-2.3 49021c5f29bbSDavid Gibson */ 490388cbe073SMarc-André Lureau 490488cbe073SMarc-André Lureau static void spapr_machine_2_3_class_options(MachineClass *mc) 490588cbe073SMarc-André Lureau { 490688cbe073SMarc-André Lureau static GlobalProperty compat[] = { 49076c36bddfSEduardo Habkost { "spapr-pci-host-bridge", "dynamic-reconfiguration", "off" }, 4908fa386d98SMarc-André Lureau }; 4909fc9f38c3SDavid Gibson spapr_machine_2_4_class_options(mc); 49108995dd90SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_3, hw_compat_2_3_len); 491188cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 49121c5f29bbSDavid Gibson } 4913fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_3, "2.3", false); 49141c5f29bbSDavid Gibson 49151c5f29bbSDavid Gibson /* 49161c5f29bbSDavid Gibson * pseries-2.2 49171c5f29bbSDavid Gibson */ 491888cbe073SMarc-André Lureau 491988cbe073SMarc-André Lureau static void spapr_machine_2_2_class_options(MachineClass *mc) 492088cbe073SMarc-André Lureau { 492188cbe073SMarc-André Lureau static GlobalProperty compat[] = { 49226c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0x20000000" }, 4923fa386d98SMarc-André Lureau }; 4924b194df47SAlexey Kardashevskiy 4925fc9f38c3SDavid Gibson spapr_machine_2_3_class_options(mc); 49261c30044eSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_2, hw_compat_2_2_len); 492788cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 4928f6d0656bSEduardo Habkost mc->default_machine_opts = "modern-hotplug-events=off,suppress-vmdesc=on"; 49291c5f29bbSDavid Gibson } 4930fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_2, "2.2", false); 49311c5f29bbSDavid Gibson 49321c5f29bbSDavid Gibson /* 49331c5f29bbSDavid Gibson * pseries-2.1 49341c5f29bbSDavid Gibson */ 49351c5f29bbSDavid Gibson 49365013c547SDavid Gibson static void spapr_machine_2_1_class_options(MachineClass *mc) 4937b0e966d0SJason Wang { 4938fc9f38c3SDavid Gibson spapr_machine_2_2_class_options(mc); 4939c4fc5695SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_1, hw_compat_2_1_len); 49406026db45SAlexey Kardashevskiy } 4941fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_1, "2.1", false); 49426026db45SAlexey Kardashevskiy 494329ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void) 494429ee3247SAlexey Kardashevskiy { 494529ee3247SAlexey Kardashevskiy type_register_static(&spapr_machine_info); 494629ee3247SAlexey Kardashevskiy } 494729ee3247SAlexey Kardashevskiy 494829ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types) 4949