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 297a1d59c0fSAlexey Kardashevskiy static void add_str(GString *s, const gchar *s1) 298a1d59c0fSAlexey Kardashevskiy { 299a1d59c0fSAlexey Kardashevskiy g_string_append_len(s, s1, strlen(s1) + 1); 300a1d59c0fSAlexey Kardashevskiy } 30153018216SPaolo Bonzini 302f1aa45ffSDaniel Henrique Barboza static int spapr_dt_memory_node(SpaprMachineState *spapr, void *fdt, int nodeid, 303f1aa45ffSDaniel Henrique Barboza hwaddr start, hwaddr size) 30426a8c353SAlexey Kardashevskiy { 30526a8c353SAlexey Kardashevskiy char mem_name[32]; 30626a8c353SAlexey Kardashevskiy uint64_t mem_reg_property[2]; 30726a8c353SAlexey Kardashevskiy int off; 30826a8c353SAlexey Kardashevskiy 30926a8c353SAlexey Kardashevskiy mem_reg_property[0] = cpu_to_be64(start); 31026a8c353SAlexey Kardashevskiy mem_reg_property[1] = cpu_to_be64(size); 31126a8c353SAlexey Kardashevskiy 3123a17e38fSAlexey Kardashevskiy sprintf(mem_name, "memory@%" HWADDR_PRIx, start); 31326a8c353SAlexey Kardashevskiy off = fdt_add_subnode(fdt, 0, mem_name); 31426a8c353SAlexey Kardashevskiy _FDT(off); 31526a8c353SAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 31626a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 31726a8c353SAlexey Kardashevskiy sizeof(mem_reg_property)))); 318f1aa45ffSDaniel Henrique Barboza spapr_numa_write_associativity_dt(spapr, fdt, off, nodeid); 31903d196b7SBharata B Rao return off; 32026a8c353SAlexey Kardashevskiy } 32126a8c353SAlexey Kardashevskiy 322f47bd1c8SIgor Mammedov static uint32_t spapr_pc_dimm_node(MemoryDeviceInfoList *list, ram_addr_t addr) 323f47bd1c8SIgor Mammedov { 324f47bd1c8SIgor Mammedov MemoryDeviceInfoList *info; 325f47bd1c8SIgor Mammedov 326f47bd1c8SIgor Mammedov for (info = list; info; info = info->next) { 327f47bd1c8SIgor Mammedov MemoryDeviceInfo *value = info->value; 328f47bd1c8SIgor Mammedov 329f47bd1c8SIgor Mammedov if (value && value->type == MEMORY_DEVICE_INFO_KIND_DIMM) { 330f47bd1c8SIgor Mammedov PCDIMMDeviceInfo *pcdimm_info = value->u.dimm.data; 331f47bd1c8SIgor Mammedov 332ccc2cef8SDavid Gibson if (addr >= pcdimm_info->addr && 333f47bd1c8SIgor Mammedov addr < (pcdimm_info->addr + pcdimm_info->size)) { 334f47bd1c8SIgor Mammedov return pcdimm_info->node; 335f47bd1c8SIgor Mammedov } 336f47bd1c8SIgor Mammedov } 337f47bd1c8SIgor Mammedov } 338f47bd1c8SIgor Mammedov 339f47bd1c8SIgor Mammedov return -1; 340f47bd1c8SIgor Mammedov } 341f47bd1c8SIgor Mammedov 342a324d6f1SBharata B Rao struct sPAPRDrconfCellV2 { 343a324d6f1SBharata B Rao uint32_t seq_lmbs; 344a324d6f1SBharata B Rao uint64_t base_addr; 345a324d6f1SBharata B Rao uint32_t drc_index; 346a324d6f1SBharata B Rao uint32_t aa_index; 347a324d6f1SBharata B Rao uint32_t flags; 348a324d6f1SBharata B Rao } QEMU_PACKED; 349a324d6f1SBharata B Rao 350a324d6f1SBharata B Rao typedef struct DrconfCellQueue { 351a324d6f1SBharata B Rao struct sPAPRDrconfCellV2 cell; 352a324d6f1SBharata B Rao QSIMPLEQ_ENTRY(DrconfCellQueue) entry; 353a324d6f1SBharata B Rao } DrconfCellQueue; 354a324d6f1SBharata B Rao 355a324d6f1SBharata B Rao static DrconfCellQueue * 356a324d6f1SBharata B Rao spapr_get_drconf_cell(uint32_t seq_lmbs, uint64_t base_addr, 357a324d6f1SBharata B Rao uint32_t drc_index, uint32_t aa_index, 358a324d6f1SBharata B Rao uint32_t flags) 35903d196b7SBharata B Rao { 360a324d6f1SBharata B Rao DrconfCellQueue *elem; 361a324d6f1SBharata B Rao 362a324d6f1SBharata B Rao elem = g_malloc0(sizeof(*elem)); 363a324d6f1SBharata B Rao elem->cell.seq_lmbs = cpu_to_be32(seq_lmbs); 364a324d6f1SBharata B Rao elem->cell.base_addr = cpu_to_be64(base_addr); 365a324d6f1SBharata B Rao elem->cell.drc_index = cpu_to_be32(drc_index); 366a324d6f1SBharata B Rao elem->cell.aa_index = cpu_to_be32(aa_index); 367a324d6f1SBharata B Rao elem->cell.flags = cpu_to_be32(flags); 368a324d6f1SBharata B Rao 369a324d6f1SBharata B Rao return elem; 370a324d6f1SBharata B Rao } 371a324d6f1SBharata B Rao 37291335a5eSDavid Gibson static int spapr_dt_dynamic_memory_v2(SpaprMachineState *spapr, void *fdt, 373a324d6f1SBharata B Rao int offset, MemoryDeviceInfoList *dimms) 3742a6593cbSAlexey Kardashevskiy { 3752a6593cbSAlexey Kardashevskiy MachineState *machine = MACHINE(spapr); 376cc941111SFabiano Rosas uint8_t *int_buf, *cur_index; 377a324d6f1SBharata B Rao int ret; 37803d196b7SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 379a324d6f1SBharata B Rao uint64_t addr, cur_addr, size; 380b0c14ec4SDavid Hildenbrand uint32_t nr_boot_lmbs = (machine->device_memory->base / lmb_size); 381b0c14ec4SDavid Hildenbrand uint64_t mem_end = machine->device_memory->base + 382b0c14ec4SDavid Hildenbrand memory_region_size(&machine->device_memory->mr); 383cc941111SFabiano Rosas uint32_t node, buf_len, nr_entries = 0; 384ce2918cbSDavid Gibson SpaprDrc *drc; 385a324d6f1SBharata B Rao DrconfCellQueue *elem, *next; 386a324d6f1SBharata B Rao MemoryDeviceInfoList *info; 387a324d6f1SBharata B Rao QSIMPLEQ_HEAD(, DrconfCellQueue) drconf_queue 388a324d6f1SBharata B Rao = QSIMPLEQ_HEAD_INITIALIZER(drconf_queue); 389a324d6f1SBharata B Rao 390a324d6f1SBharata B Rao /* Entry to cover RAM and the gap area */ 391a324d6f1SBharata B Rao elem = spapr_get_drconf_cell(nr_boot_lmbs, 0, 0, -1, 392a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_RESERVED | 393a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 394a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 395a324d6f1SBharata B Rao nr_entries++; 396a324d6f1SBharata B Rao 397b0c14ec4SDavid Hildenbrand cur_addr = machine->device_memory->base; 398a324d6f1SBharata B Rao for (info = dimms; info; info = info->next) { 399a324d6f1SBharata B Rao PCDIMMDeviceInfo *di = info->value->u.dimm.data; 400a324d6f1SBharata B Rao 401a324d6f1SBharata B Rao addr = di->addr; 402a324d6f1SBharata B Rao size = di->size; 403a324d6f1SBharata B Rao node = di->node; 404a324d6f1SBharata B Rao 405ee3a71e3SShivaprasad G Bhat /* 406ee3a71e3SShivaprasad G Bhat * The NVDIMM area is hotpluggable after the NVDIMM is unplugged. The 407ee3a71e3SShivaprasad G Bhat * area is marked hotpluggable in the next iteration for the bigger 408ee3a71e3SShivaprasad G Bhat * chunk including the NVDIMM occupied area. 409ee3a71e3SShivaprasad G Bhat */ 410ee3a71e3SShivaprasad G Bhat if (info->value->type == MEMORY_DEVICE_INFO_KIND_NVDIMM) 411ee3a71e3SShivaprasad G Bhat continue; 412ee3a71e3SShivaprasad G Bhat 413a324d6f1SBharata B Rao /* Entry for hot-pluggable area */ 414a324d6f1SBharata B Rao if (cur_addr < addr) { 415a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size); 416a324d6f1SBharata B Rao g_assert(drc); 417a324d6f1SBharata B Rao elem = spapr_get_drconf_cell((addr - cur_addr) / lmb_size, 418a324d6f1SBharata B Rao cur_addr, spapr_drc_index(drc), -1, 0); 419a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 420a324d6f1SBharata B Rao nr_entries++; 421a324d6f1SBharata B Rao } 422a324d6f1SBharata B Rao 423a324d6f1SBharata B Rao /* Entry for DIMM */ 424a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr / lmb_size); 425a324d6f1SBharata B Rao g_assert(drc); 426a324d6f1SBharata B Rao elem = spapr_get_drconf_cell(size / lmb_size, addr, 427a324d6f1SBharata B Rao spapr_drc_index(drc), node, 4280911a60cSLeonardo Bras (SPAPR_LMB_FLAGS_ASSIGNED | 4290911a60cSLeonardo Bras SPAPR_LMB_FLAGS_HOTREMOVABLE)); 430a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 431a324d6f1SBharata B Rao nr_entries++; 432a324d6f1SBharata B Rao cur_addr = addr + size; 433a324d6f1SBharata B Rao } 434a324d6f1SBharata B Rao 435a324d6f1SBharata B Rao /* Entry for remaining hotpluggable area */ 436a324d6f1SBharata B Rao if (cur_addr < mem_end) { 437a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size); 438a324d6f1SBharata B Rao g_assert(drc); 439a324d6f1SBharata B Rao elem = spapr_get_drconf_cell((mem_end - cur_addr) / lmb_size, 440a324d6f1SBharata B Rao cur_addr, spapr_drc_index(drc), -1, 0); 441a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 442a324d6f1SBharata B Rao nr_entries++; 443a324d6f1SBharata B Rao } 444a324d6f1SBharata B Rao 445a324d6f1SBharata B Rao buf_len = nr_entries * sizeof(struct sPAPRDrconfCellV2) + sizeof(uint32_t); 446a324d6f1SBharata B Rao int_buf = cur_index = g_malloc0(buf_len); 447a324d6f1SBharata B Rao *(uint32_t *)int_buf = cpu_to_be32(nr_entries); 448a324d6f1SBharata B Rao cur_index += sizeof(nr_entries); 449a324d6f1SBharata B Rao 450a324d6f1SBharata B Rao QSIMPLEQ_FOREACH_SAFE(elem, &drconf_queue, entry, next) { 451a324d6f1SBharata B Rao memcpy(cur_index, &elem->cell, sizeof(elem->cell)); 452a324d6f1SBharata B Rao cur_index += sizeof(elem->cell); 453a324d6f1SBharata B Rao QSIMPLEQ_REMOVE(&drconf_queue, elem, DrconfCellQueue, entry); 454a324d6f1SBharata B Rao g_free(elem); 455a324d6f1SBharata B Rao } 456a324d6f1SBharata B Rao 457a324d6f1SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory-v2", int_buf, buf_len); 458a324d6f1SBharata B Rao g_free(int_buf); 459a324d6f1SBharata B Rao if (ret < 0) { 460a324d6f1SBharata B Rao return -1; 461a324d6f1SBharata B Rao } 462a324d6f1SBharata B Rao return 0; 463a324d6f1SBharata B Rao } 464a324d6f1SBharata B Rao 46591335a5eSDavid Gibson static int spapr_dt_dynamic_memory(SpaprMachineState *spapr, void *fdt, 466a324d6f1SBharata B Rao int offset, MemoryDeviceInfoList *dimms) 467a324d6f1SBharata B Rao { 468b0c14ec4SDavid Hildenbrand MachineState *machine = MACHINE(spapr); 469a324d6f1SBharata B Rao int i, ret; 470a324d6f1SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 4710c9269a5SDavid Hildenbrand uint32_t device_lmb_start = machine->device_memory->base / lmb_size; 472b0c14ec4SDavid Hildenbrand uint32_t nr_lmbs = (machine->device_memory->base + 473b0c14ec4SDavid Hildenbrand memory_region_size(&machine->device_memory->mr)) / 474d0e5a8f2SBharata B Rao lmb_size; 47503d196b7SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 47616c25aefSBharata B Rao 47716c25aefSBharata B Rao /* 478ef001f06SThomas Huth * Allocate enough buffer size to fit in ibm,dynamic-memory 479ef001f06SThomas Huth */ 480a324d6f1SBharata B Rao buf_len = (nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1) * sizeof(uint32_t); 48103d196b7SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 48203d196b7SBharata B Rao int_buf[0] = cpu_to_be32(nr_lmbs); 48303d196b7SBharata B Rao cur_index++; 48403d196b7SBharata B Rao for (i = 0; i < nr_lmbs; i++) { 485d0e5a8f2SBharata B Rao uint64_t addr = i * lmb_size; 48603d196b7SBharata B Rao uint32_t *dynamic_memory = cur_index; 48703d196b7SBharata B Rao 4880c9269a5SDavid Hildenbrand if (i >= device_lmb_start) { 489ce2918cbSDavid Gibson SpaprDrc *drc; 490d0e5a8f2SBharata B Rao 491fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, i); 49203d196b7SBharata B Rao g_assert(drc); 49303d196b7SBharata B Rao 49403d196b7SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 49503d196b7SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 4960b55aa91SDavid Gibson dynamic_memory[2] = cpu_to_be32(spapr_drc_index(drc)); 49703d196b7SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 498f47bd1c8SIgor Mammedov dynamic_memory[4] = cpu_to_be32(spapr_pc_dimm_node(dimms, addr)); 499d0e5a8f2SBharata B Rao if (memory_region_present(get_system_memory(), addr)) { 50003d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); 50103d196b7SBharata B Rao } else { 50203d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(0); 50303d196b7SBharata B Rao } 504d0e5a8f2SBharata B Rao } else { 505d0e5a8f2SBharata B Rao /* 506d0e5a8f2SBharata B Rao * LMB information for RMA, boot time RAM and gap b/n RAM and 5070c9269a5SDavid Hildenbrand * device memory region -- all these are marked as reserved 508d0e5a8f2SBharata B Rao * and as having no valid DRC. 509d0e5a8f2SBharata B Rao */ 510d0e5a8f2SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 511d0e5a8f2SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 512d0e5a8f2SBharata B Rao dynamic_memory[2] = cpu_to_be32(0); 513d0e5a8f2SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 514d0e5a8f2SBharata B Rao dynamic_memory[4] = cpu_to_be32(-1); 515d0e5a8f2SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED | 516d0e5a8f2SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 517d0e5a8f2SBharata B Rao } 51803d196b7SBharata B Rao 51903d196b7SBharata B Rao cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; 52003d196b7SBharata B Rao } 52103d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len); 522a324d6f1SBharata B Rao g_free(int_buf); 52303d196b7SBharata B Rao if (ret < 0) { 524a324d6f1SBharata B Rao return -1; 525a324d6f1SBharata B Rao } 526a324d6f1SBharata B Rao return 0; 527a324d6f1SBharata B Rao } 528a324d6f1SBharata B Rao 529a324d6f1SBharata B Rao /* 530a324d6f1SBharata B Rao * Adds ibm,dynamic-reconfiguration-memory node. 531a324d6f1SBharata B Rao * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation 532a324d6f1SBharata B Rao * of this device tree node. 533a324d6f1SBharata B Rao */ 53491335a5eSDavid Gibson static int spapr_dt_dynamic_reconfiguration_memory(SpaprMachineState *spapr, 53591335a5eSDavid Gibson void *fdt) 536a324d6f1SBharata B Rao { 537a324d6f1SBharata B Rao MachineState *machine = MACHINE(spapr); 5380ee52012SDaniel Henrique Barboza int ret, offset; 539a324d6f1SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 5407abf9797SAnton Blanchard uint32_t prop_lmb_size[] = {cpu_to_be32(lmb_size >> 32), 5417abf9797SAnton Blanchard cpu_to_be32(lmb_size & 0xffffffff)}; 542a324d6f1SBharata B Rao MemoryDeviceInfoList *dimms = NULL; 543a324d6f1SBharata B Rao 544a324d6f1SBharata B Rao /* 5450c9269a5SDavid Hildenbrand * Don't create the node if there is no device memory 546a324d6f1SBharata B Rao */ 547a324d6f1SBharata B Rao if (machine->ram_size == machine->maxram_size) { 548a324d6f1SBharata B Rao return 0; 549a324d6f1SBharata B Rao } 550a324d6f1SBharata B Rao 551a324d6f1SBharata B Rao offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory"); 552a324d6f1SBharata B Rao 553a324d6f1SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size, 554a324d6f1SBharata B Rao sizeof(prop_lmb_size)); 555a324d6f1SBharata B Rao if (ret < 0) { 556a324d6f1SBharata B Rao return ret; 557a324d6f1SBharata B Rao } 558a324d6f1SBharata B Rao 559a324d6f1SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff); 560a324d6f1SBharata B Rao if (ret < 0) { 561a324d6f1SBharata B Rao return ret; 562a324d6f1SBharata B Rao } 563a324d6f1SBharata B Rao 564a324d6f1SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0); 565a324d6f1SBharata B Rao if (ret < 0) { 566a324d6f1SBharata B Rao return ret; 567a324d6f1SBharata B Rao } 568a324d6f1SBharata B Rao 569a324d6f1SBharata B Rao /* ibm,dynamic-memory or ibm,dynamic-memory-v2 */ 5702cc0e2e8SDavid Hildenbrand dimms = qmp_memory_device_list(); 571a324d6f1SBharata B Rao if (spapr_ovec_test(spapr->ov5_cas, OV5_DRMEM_V2)) { 57291335a5eSDavid Gibson ret = spapr_dt_dynamic_memory_v2(spapr, fdt, offset, dimms); 573a324d6f1SBharata B Rao } else { 57491335a5eSDavid Gibson ret = spapr_dt_dynamic_memory(spapr, fdt, offset, dimms); 575a324d6f1SBharata B Rao } 576a324d6f1SBharata B Rao qapi_free_MemoryDeviceInfoList(dimms); 577a324d6f1SBharata B Rao 578a324d6f1SBharata B Rao if (ret < 0) { 579a324d6f1SBharata B Rao return ret; 58003d196b7SBharata B Rao } 58103d196b7SBharata B Rao 5820ee52012SDaniel Henrique Barboza ret = spapr_numa_write_assoc_lookup_arrays(spapr, fdt, offset); 583a324d6f1SBharata B Rao 58403d196b7SBharata B Rao return ret; 58503d196b7SBharata B Rao } 58603d196b7SBharata B Rao 58791335a5eSDavid Gibson static int spapr_dt_memory(SpaprMachineState *spapr, void *fdt) 5886787d27bSMichael Roth { 589fa523f0dSDavid Gibson MachineState *machine = MACHINE(spapr); 590ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 59153018216SPaolo Bonzini hwaddr mem_start, node_size; 59253018216SPaolo Bonzini int i, nb_nodes = machine->numa_state->num_nodes; 59353018216SPaolo Bonzini NodeInfo *nodes = machine->numa_state->nodes; 59453018216SPaolo Bonzini 59553018216SPaolo Bonzini for (i = 0, mem_start = 0; i < nb_nodes; ++i) { 59653018216SPaolo Bonzini if (!nodes[i].node_mem) { 59753018216SPaolo Bonzini continue; 59853018216SPaolo Bonzini } 59953018216SPaolo Bonzini if (mem_start >= machine->ram_size) { 60053018216SPaolo Bonzini node_size = 0; 60153018216SPaolo Bonzini } else { 60253018216SPaolo Bonzini node_size = nodes[i].node_mem; 60353018216SPaolo Bonzini if (node_size > machine->ram_size - mem_start) { 60453018216SPaolo Bonzini node_size = machine->ram_size - mem_start; 60553018216SPaolo Bonzini } 60653018216SPaolo Bonzini } 60753018216SPaolo Bonzini if (!mem_start) { 60853018216SPaolo Bonzini /* spapr_machine_init() checks for rma_size <= node0_size 60953018216SPaolo Bonzini * already */ 610f1aa45ffSDaniel Henrique Barboza spapr_dt_memory_node(spapr, fdt, i, 0, spapr->rma_size); 61153018216SPaolo Bonzini mem_start += spapr->rma_size; 61253018216SPaolo Bonzini node_size -= spapr->rma_size; 61353018216SPaolo Bonzini } 61453018216SPaolo Bonzini for ( ; node_size; ) { 61553018216SPaolo Bonzini hwaddr sizetmp = pow2floor(node_size); 61653018216SPaolo Bonzini 61753018216SPaolo Bonzini /* mem_start != 0 here */ 61853018216SPaolo Bonzini if (ctzl(mem_start) < ctzl(sizetmp)) { 61953018216SPaolo Bonzini sizetmp = 1ULL << ctzl(mem_start); 62053018216SPaolo Bonzini } 62153018216SPaolo Bonzini 622f1aa45ffSDaniel Henrique Barboza spapr_dt_memory_node(spapr, fdt, i, mem_start, sizetmp); 62353018216SPaolo Bonzini node_size -= sizetmp; 62453018216SPaolo Bonzini mem_start += sizetmp; 62553018216SPaolo Bonzini } 62653018216SPaolo Bonzini } 62753018216SPaolo Bonzini 6286787d27bSMichael Roth /* Generate ibm,dynamic-reconfiguration-memory node if required */ 629fa523f0dSDavid Gibson if (spapr_ovec_test(spapr->ov5_cas, OV5_DRCONF_MEMORY)) { 630fa523f0dSDavid Gibson int ret; 631fa523f0dSDavid Gibson 6326787d27bSMichael Roth g_assert(smc->dr_lmb_enabled); 63391335a5eSDavid Gibson ret = spapr_dt_dynamic_reconfiguration_memory(spapr, fdt); 634417ece33SMichael Roth if (ret) { 6359b6c1da5SDaniel Henrique Barboza return ret; 636417ece33SMichael Roth } 6376787d27bSMichael Roth } 6386787d27bSMichael Roth 63953018216SPaolo Bonzini return 0; 64053018216SPaolo Bonzini } 64153018216SPaolo Bonzini 64291335a5eSDavid Gibson static void spapr_dt_cpu(CPUState *cs, void *fdt, int offset, 64353018216SPaolo Bonzini SpaprMachineState *spapr) 64453018216SPaolo Bonzini { 64553018216SPaolo Bonzini MachineState *ms = MACHINE(spapr); 64653018216SPaolo Bonzini PowerPCCPU *cpu = POWERPC_CPU(cs); 64753018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 64853018216SPaolo Bonzini PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 64953018216SPaolo Bonzini int index = spapr_get_vcpu_id(cpu); 65053018216SPaolo Bonzini uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 65153018216SPaolo Bonzini 0xffffffff, 0xffffffff}; 65253018216SPaolo Bonzini uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() 65353018216SPaolo Bonzini : SPAPR_TIMEBASE_FREQ; 65453018216SPaolo Bonzini uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; 65553018216SPaolo Bonzini uint32_t page_sizes_prop[64]; 65653018216SPaolo Bonzini size_t page_sizes_prop_size; 65753018216SPaolo Bonzini unsigned int smp_threads = ms->smp.threads; 65853018216SPaolo Bonzini uint32_t vcpus_per_socket = smp_threads * ms->smp.cores; 65953018216SPaolo Bonzini uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 66053018216SPaolo Bonzini int compat_smt = MIN(smp_threads, ppc_compat_max_vthreads(cpu)); 66153018216SPaolo Bonzini SpaprDrc *drc; 66253018216SPaolo Bonzini int drc_index; 66353018216SPaolo Bonzini uint32_t radix_AP_encodings[PPC_PAGE_SIZES_MAX_SZ]; 66453018216SPaolo Bonzini int i; 66553018216SPaolo Bonzini 66653018216SPaolo Bonzini drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index); 66753018216SPaolo Bonzini if (drc) { 66853018216SPaolo Bonzini drc_index = spapr_drc_index(drc); 66953018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index))); 6702a6593cbSAlexey Kardashevskiy } 6712a6593cbSAlexey Kardashevskiy 6722a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); 6732a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 6742a6593cbSAlexey Kardashevskiy 6752a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 6762a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 6772a6593cbSAlexey Kardashevskiy env->dcache_line_size))); 6782a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 6792a6593cbSAlexey Kardashevskiy env->dcache_line_size))); 6802a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 6812a6593cbSAlexey Kardashevskiy env->icache_line_size))); 6822a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 6832a6593cbSAlexey Kardashevskiy env->icache_line_size))); 6842a6593cbSAlexey Kardashevskiy 6852a6593cbSAlexey Kardashevskiy if (pcc->l1_dcache_size) { 6862a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 6872a6593cbSAlexey Kardashevskiy pcc->l1_dcache_size))); 6882a6593cbSAlexey Kardashevskiy } else { 6892a6593cbSAlexey Kardashevskiy warn_report("Unknown L1 dcache size for cpu"); 6902a6593cbSAlexey Kardashevskiy } 6912a6593cbSAlexey Kardashevskiy if (pcc->l1_icache_size) { 6922a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 6932a6593cbSAlexey Kardashevskiy pcc->l1_icache_size))); 6942a6593cbSAlexey Kardashevskiy } else { 6952a6593cbSAlexey Kardashevskiy warn_report("Unknown L1 icache size for cpu"); 6962a6593cbSAlexey Kardashevskiy } 6972a6593cbSAlexey Kardashevskiy 6982a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 6992a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 7002a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "slb-size", cpu->hash64_opts->slb_size))); 7012a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", cpu->hash64_opts->slb_size))); 7022a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 7032a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 7042a6593cbSAlexey Kardashevskiy 70553018216SPaolo Bonzini if (env->spr_cb[SPR_PURR].oea_read) { 70653018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,purr", 1))); 70753018216SPaolo Bonzini } 70853018216SPaolo Bonzini if (env->spr_cb[SPR_SPURR].oea_read) { 70953018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,spurr", 1))); 71053018216SPaolo Bonzini } 7115fe269b1SPaul Mackerras 71253018216SPaolo Bonzini if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 71353018216SPaolo Bonzini _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 71453018216SPaolo Bonzini segs, sizeof(segs)))); 71553018216SPaolo Bonzini } 7165fe269b1SPaul Mackerras 7175fe269b1SPaul Mackerras /* Advertise VSX (vector extensions) if available 7185fe269b1SPaul Mackerras * 1 == VMX / Altivec available 7195fe269b1SPaul Mackerras * 2 == VSX available 7205fe269b1SPaul Mackerras * 72153018216SPaolo Bonzini * Only CPUs for which we create core types in spapr_cpu_core.c 72253018216SPaolo Bonzini * are possible, and all of those have VMX */ 72353018216SPaolo Bonzini if (spapr_get_cap(spapr, SPAPR_CAP_VSX) != 0) { 72453018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2))); 72553018216SPaolo Bonzini } else { 72653018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1))); 72728e02042SDavid Gibson } 72853018216SPaolo Bonzini 729fb164994SDavid Gibson /* Advertise DFP (Decimal Floating Point) if available 7307db8a127SAlexey Kardashevskiy * 0 / no property == no DFP 7317db8a127SAlexey Kardashevskiy * 1 == DFP available */ 7327db8a127SAlexey Kardashevskiy if (spapr_get_cap(spapr, SPAPR_CAP_DFP) != 0) { 7337db8a127SAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 73453018216SPaolo Bonzini } 7357db8a127SAlexey Kardashevskiy 7367db8a127SAlexey Kardashevskiy page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 7377db8a127SAlexey Kardashevskiy sizeof(page_sizes_prop)); 738fb164994SDavid Gibson if (page_sizes_prop_size) { 7397db8a127SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 74053018216SPaolo Bonzini page_sizes_prop, page_sizes_prop_size))); 74153018216SPaolo Bonzini } 7427db8a127SAlexey Kardashevskiy 74391335a5eSDavid Gibson spapr_dt_pa_features(spapr, cpu, fdt, offset); 74453018216SPaolo Bonzini 7457db8a127SAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", 7467db8a127SAlexey Kardashevskiy cs->cpu_index / vcpus_per_socket))); 7477db8a127SAlexey Kardashevskiy 74853018216SPaolo Bonzini _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", 749fb164994SDavid Gibson pft_size_prop, sizeof(pft_size_prop)))); 7505fe269b1SPaul Mackerras 7515fe269b1SPaul Mackerras if (ms->numa_state->num_nodes > 1) { 7528f86a408SDaniel Henrique Barboza _FDT(spapr_numa_fixup_cpu_dt(spapr, fdt, offset, cpu)); 7535fe269b1SPaul Mackerras } 7545fe269b1SPaul Mackerras 7557db8a127SAlexey Kardashevskiy _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt)); 7567db8a127SAlexey Kardashevskiy 7577db8a127SAlexey Kardashevskiy if (pcc->radix_page_info) { 7587db8a127SAlexey Kardashevskiy for (i = 0; i < pcc->radix_page_info->count; i++) { 7597db8a127SAlexey Kardashevskiy radix_AP_encodings[i] = 7607db8a127SAlexey Kardashevskiy cpu_to_be32(pcc->radix_page_info->entries[i]); 7616010818cSAlexey Kardashevskiy } 7626010818cSAlexey Kardashevskiy _FDT((fdt_setprop(fdt, offset, "ibm,processor-radix-AP-encodings", 7636010818cSAlexey Kardashevskiy radix_AP_encodings, 7646010818cSAlexey Kardashevskiy pcc->radix_page_info->count * 7656010818cSAlexey Kardashevskiy sizeof(radix_AP_encodings[0])))); 7666010818cSAlexey Kardashevskiy } 7676010818cSAlexey Kardashevskiy 7686010818cSAlexey Kardashevskiy /* 7696010818cSAlexey Kardashevskiy * We set this property to let the guest know that it can use the large 7706010818cSAlexey Kardashevskiy * decrementer and its width in bits. 7716010818cSAlexey Kardashevskiy */ 7726010818cSAlexey Kardashevskiy if (spapr_get_cap(spapr, SPAPR_CAP_LARGE_DECREMENTER) != SPAPR_CAP_OFF) 77353018216SPaolo Bonzini _FDT((fdt_setprop_u32(fdt, offset, "ibm,dec-bits", 77453018216SPaolo Bonzini pcc->lrg_decr_bits))); 77553018216SPaolo Bonzini } 77653018216SPaolo Bonzini 77791335a5eSDavid Gibson static void spapr_dt_cpus(void *fdt, SpaprMachineState *spapr) 77853018216SPaolo Bonzini { 77953018216SPaolo Bonzini CPUState **rev; 78053018216SPaolo Bonzini CPUState *cs; 78153018216SPaolo Bonzini int n_cpus; 78253018216SPaolo Bonzini int cpus_offset; 78353018216SPaolo Bonzini char *nodename; 78453018216SPaolo Bonzini int i; 78553018216SPaolo Bonzini 78653018216SPaolo Bonzini cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 78753018216SPaolo Bonzini _FDT(cpus_offset); 78853018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 78953018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 79053018216SPaolo Bonzini 79153018216SPaolo Bonzini /* 79253018216SPaolo Bonzini * We walk the CPUs in reverse order to ensure that CPU DT nodes 79353018216SPaolo Bonzini * created by fdt_add_subnode() end up in the right order in FDT 79453018216SPaolo Bonzini * for the guest kernel the enumerate the CPUs correctly. 79553018216SPaolo Bonzini * 79653018216SPaolo Bonzini * The CPU list cannot be traversed in reverse order, so we need 79753018216SPaolo Bonzini * to do extra work. 79853018216SPaolo Bonzini */ 79953018216SPaolo Bonzini n_cpus = 0; 80053018216SPaolo Bonzini rev = NULL; 8010da6f3feSBharata B Rao CPU_FOREACH(cs) { 8020da6f3feSBharata B Rao rev = g_renew(CPUState *, rev, n_cpus + 1); 8030da6f3feSBharata B Rao rev[n_cpus++] = cs; 8040da6f3feSBharata B Rao } 8050da6f3feSBharata B Rao 8060da6f3feSBharata B Rao for (i = n_cpus - 1; i >= 0; i--) { 8070da6f3feSBharata B Rao CPUState *cs = rev[i]; 8080da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 8090da6f3feSBharata B Rao int index = spapr_get_vcpu_id(cpu); 8100da6f3feSBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 8110da6f3feSBharata B Rao int offset; 8120da6f3feSBharata B Rao 8130da6f3feSBharata B Rao if (!spapr_is_thread0_in_vcore(spapr, cpu)) { 81422419c2aSDavid Gibson continue; 8150da6f3feSBharata B Rao } 8160da6f3feSBharata B Rao 8170da6f3feSBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, index); 8180da6f3feSBharata B Rao offset = fdt_add_subnode(fdt, cpus_offset, nodename); 8190da6f3feSBharata B Rao g_free(nodename); 8200da6f3feSBharata B Rao _FDT(offset); 82191335a5eSDavid Gibson spapr_dt_cpu(cs, fdt, offset, spapr); 8220da6f3feSBharata B Rao } 8230da6f3feSBharata B Rao 8240da6f3feSBharata B Rao g_free(rev); 8250da6f3feSBharata B Rao } 8260da6f3feSBharata B Rao 82791335a5eSDavid Gibson static int spapr_dt_rng(void *fdt) 8280da6f3feSBharata B Rao { 8290da6f3feSBharata B Rao int node; 8300da6f3feSBharata B Rao int ret; 8310da6f3feSBharata B Rao 8320da6f3feSBharata B Rao node = qemu_fdt_add_subnode(fdt, "/ibm,platform-facilities"); 8330da6f3feSBharata B Rao if (node <= 0) { 8340da6f3feSBharata B Rao return -1; 8350da6f3feSBharata B Rao } 8360da6f3feSBharata B Rao ret = fdt_setprop_string(fdt, node, "device_type", 8370da6f3feSBharata B Rao "ibm,platform-facilities"); 8380da6f3feSBharata B Rao ret |= fdt_setprop_cell(fdt, node, "#address-cells", 0x1); 8390da6f3feSBharata B Rao ret |= fdt_setprop_cell(fdt, node, "#size-cells", 0x0); 8400da6f3feSBharata B Rao 8410da6f3feSBharata B Rao node = fdt_add_subnode(fdt, node, "ibm,random-v1"); 8420da6f3feSBharata B Rao if (node <= 0) { 8430da6f3feSBharata B Rao return -1; 8440da6f3feSBharata B Rao } 8450da6f3feSBharata B Rao ret |= fdt_setprop_string(fdt, node, "compatible", "ibm,random"); 8460da6f3feSBharata B Rao 8470da6f3feSBharata B Rao return ret ? -1 : 0; 8480da6f3feSBharata B Rao } 8490da6f3feSBharata B Rao 850ce2918cbSDavid Gibson static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt) 8513f5dabceSDavid Gibson { 852fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 8533f5dabceSDavid Gibson int rtas; 8543f5dabceSDavid Gibson GString *hypertas = g_string_sized_new(256); 8553f5dabceSDavid Gibson GString *qemu_hypertas = g_string_sized_new(256); 8560c9269a5SDavid Hildenbrand uint64_t max_device_addr = MACHINE(spapr)->device_memory->base + 857b0c14ec4SDavid Hildenbrand memory_region_size(&MACHINE(spapr)->device_memory->mr); 8583f5dabceSDavid Gibson uint32_t lrdr_capacity[] = { 8590c9269a5SDavid Hildenbrand cpu_to_be32(max_device_addr >> 32), 8600c9269a5SDavid Hildenbrand cpu_to_be32(max_device_addr & 0xffffffff), 8617abf9797SAnton Blanchard cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE >> 32), 8627abf9797SAnton Blanchard cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE & 0xffffffff), 863fe6b6346SLike Xu cpu_to_be32(ms->smp.max_cpus / ms->smp.threads), 8643f5dabceSDavid Gibson }; 8653f5dabceSDavid Gibson 8663f5dabceSDavid Gibson _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas")); 8673f5dabceSDavid Gibson 8683f5dabceSDavid Gibson /* hypertas */ 8693f5dabceSDavid Gibson add_str(hypertas, "hcall-pft"); 8703f5dabceSDavid Gibson add_str(hypertas, "hcall-term"); 8713f5dabceSDavid Gibson add_str(hypertas, "hcall-dabr"); 8723f5dabceSDavid Gibson add_str(hypertas, "hcall-interrupt"); 8733f5dabceSDavid Gibson add_str(hypertas, "hcall-tce"); 8743f5dabceSDavid Gibson add_str(hypertas, "hcall-vio"); 8753f5dabceSDavid Gibson add_str(hypertas, "hcall-splpar"); 87610741314SNicholas Piggin add_str(hypertas, "hcall-join"); 8773f5dabceSDavid Gibson add_str(hypertas, "hcall-bulk"); 8783f5dabceSDavid Gibson add_str(hypertas, "hcall-set-mode"); 8793f5dabceSDavid Gibson add_str(hypertas, "hcall-sprg0"); 8803f5dabceSDavid Gibson add_str(hypertas, "hcall-copy"); 8813f5dabceSDavid Gibson add_str(hypertas, "hcall-debug"); 882c24ba3d0SLaurent Vivier add_str(hypertas, "hcall-vphn"); 8833f5dabceSDavid Gibson add_str(qemu_hypertas, "hcall-memop1"); 8843f5dabceSDavid Gibson 8853f5dabceSDavid Gibson if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { 8863f5dabceSDavid Gibson add_str(hypertas, "hcall-multi-tce"); 8873f5dabceSDavid Gibson } 88830f4b05bSDavid Gibson 88930f4b05bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { 89030f4b05bSDavid Gibson add_str(hypertas, "hcall-hpt-resize"); 89130f4b05bSDavid Gibson } 89230f4b05bSDavid Gibson 8933f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions", 8943f5dabceSDavid Gibson hypertas->str, hypertas->len)); 8953f5dabceSDavid Gibson g_string_free(hypertas, TRUE); 8963f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "qemu,hypertas-functions", 8973f5dabceSDavid Gibson qemu_hypertas->str, qemu_hypertas->len)); 8983f5dabceSDavid Gibson g_string_free(qemu_hypertas, TRUE); 8993f5dabceSDavid Gibson 9001eee9950SDaniel Henrique Barboza spapr_numa_write_rtas_dt(spapr, fdt, rtas); 901da9f80fbSSerhii Popovych 9020e236d34SNicholas Piggin /* 9030e236d34SNicholas Piggin * FWNMI reserves RTAS_ERROR_LOG_MAX for the machine check error log, 9040e236d34SNicholas Piggin * and 16 bytes per CPU for system reset error log plus an extra 8 bytes. 9050e236d34SNicholas Piggin * 9060e236d34SNicholas Piggin * The system reset requirements are driven by existing Linux and PowerVM 9070e236d34SNicholas Piggin * implementation which (contrary to PAPR) saves r3 in the error log 9080e236d34SNicholas Piggin * structure like machine check, so Linux expects to find the saved r3 9090e236d34SNicholas Piggin * value at the address in r3 upon FWNMI-enabled sreset interrupt (and 9100e236d34SNicholas Piggin * does not look at the error value). 9110e236d34SNicholas Piggin * 9120e236d34SNicholas Piggin * System reset interrupts are not subject to interlock like machine 9130e236d34SNicholas Piggin * check, so this memory area could be corrupted if the sreset is 9140e236d34SNicholas Piggin * interrupted by a machine check (or vice versa) if it was shared. To 9150e236d34SNicholas Piggin * prevent this, system reset uses per-CPU areas for the sreset save 9160e236d34SNicholas Piggin * area. A system reset that interrupts a system reset handler could 9170e236d34SNicholas Piggin * still overwrite this area, but Linux doesn't try to recover in that 9180e236d34SNicholas Piggin * case anyway. 9190e236d34SNicholas Piggin * 9200e236d34SNicholas Piggin * The extra 8 bytes is required because Linux's FWNMI error log check 9210e236d34SNicholas Piggin * is off-by-one. 9220e236d34SNicholas Piggin */ 9230e236d34SNicholas Piggin _FDT(fdt_setprop_cell(fdt, rtas, "rtas-size", RTAS_ERROR_LOG_MAX + 9240e236d34SNicholas Piggin ms->smp.max_cpus * sizeof(uint64_t)*2 + sizeof(uint64_t))); 9253f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-error-log-max", 9263f5dabceSDavid Gibson RTAS_ERROR_LOG_MAX)); 9273f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-event-scan-rate", 9283f5dabceSDavid Gibson RTAS_EVENT_SCAN_RATE)); 9293f5dabceSDavid Gibson 9304f441474SDavid Gibson g_assert(msi_nonbroken); 9313f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,change-msix-capable", NULL, 0)); 9323f5dabceSDavid Gibson 9333f5dabceSDavid Gibson /* 9343f5dabceSDavid Gibson * According to PAPR, rtas ibm,os-term does not guarantee a return 9353f5dabceSDavid Gibson * back to the guest cpu. 9363f5dabceSDavid Gibson * 9373f5dabceSDavid Gibson * While an additional ibm,extended-os-term property indicates 9383f5dabceSDavid Gibson * that rtas call return will always occur. Set this property. 9393f5dabceSDavid Gibson */ 9403f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,extended-os-term", NULL, 0)); 9413f5dabceSDavid Gibson 9423f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,lrdr-capacity", 9433f5dabceSDavid Gibson lrdr_capacity, sizeof(lrdr_capacity))); 9443f5dabceSDavid Gibson 9453f5dabceSDavid Gibson spapr_dt_rtas_tokens(fdt, rtas); 9463f5dabceSDavid Gibson } 9473f5dabceSDavid Gibson 948db592b5bSCédric Le Goater /* 949db592b5bSCédric Le Goater * Prepare ibm,arch-vec-5-platform-support, which indicates the MMU 950db592b5bSCédric Le Goater * and the XIVE features that the guest may request and thus the valid 951db592b5bSCédric Le Goater * values for bytes 23..26 of option vector 5: 952db592b5bSCédric Le Goater */ 953ce2918cbSDavid Gibson static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt, 954db592b5bSCédric Le Goater int chosen) 9559fb4541fSSam Bobroff { 956545d6e2bSSuraj Jitindar Singh PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); 957545d6e2bSSuraj Jitindar Singh 958f2b14e3aSCédric Le Goater char val[2 * 4] = { 959ca62823bSDavid Gibson 23, 0x00, /* XICS / XIVE mode */ 9609fb4541fSSam Bobroff 24, 0x00, /* Hash/Radix, filled in below. */ 9619fb4541fSSam Bobroff 25, 0x00, /* Hash options: Segment Tables == no, GTSE == no. */ 9629fb4541fSSam Bobroff 26, 0x40, /* Radix options: GTSE == yes. */ 9639fb4541fSSam Bobroff }; 9649fb4541fSSam Bobroff 965ca62823bSDavid Gibson if (spapr->irq->xics && spapr->irq->xive) { 966ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_BOTH; 967ca62823bSDavid Gibson } else if (spapr->irq->xive) { 968ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_EXPLOIT; 969ca62823bSDavid Gibson } else { 970ca62823bSDavid Gibson assert(spapr->irq->xics); 971ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_LEGACY; 972ca62823bSDavid Gibson } 973ca62823bSDavid Gibson 9747abd43baSSuraj Jitindar Singh if (!ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0, 9757abd43baSSuraj Jitindar Singh first_ppc_cpu->compat_pvr)) { 976db592b5bSCédric Le Goater /* 977db592b5bSCédric Le Goater * If we're in a pre POWER9 compat mode then the guest should 978db592b5bSCédric Le Goater * do hash and use the legacy interrupt mode 979db592b5bSCédric Le Goater */ 980ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_LEGACY; /* XICS */ 9817abd43baSSuraj Jitindar Singh val[3] = 0x00; /* Hash */ 9827abd43baSSuraj Jitindar Singh } else if (kvm_enabled()) { 9839fb4541fSSam Bobroff if (kvmppc_has_cap_mmu_radix() && kvmppc_has_cap_mmu_hash_v3()) { 984f2b14e3aSCédric Le Goater val[3] = 0x80; /* OV5_MMU_BOTH */ 9859fb4541fSSam Bobroff } else if (kvmppc_has_cap_mmu_radix()) { 986f2b14e3aSCédric Le Goater val[3] = 0x40; /* OV5_MMU_RADIX_300 */ 9879fb4541fSSam Bobroff } else { 988f2b14e3aSCédric Le Goater val[3] = 0x00; /* Hash */ 9899fb4541fSSam Bobroff } 9909fb4541fSSam Bobroff } else { 9917abd43baSSuraj Jitindar Singh /* V3 MMU supports both hash and radix in tcg (with dynamic switching) */ 992f2b14e3aSCédric Le Goater val[3] = 0xC0; 993545d6e2bSSuraj Jitindar Singh } 9949fb4541fSSam Bobroff _FDT(fdt_setprop(fdt, chosen, "ibm,arch-vec-5-platform-support", 9959fb4541fSSam Bobroff val, sizeof(val))); 9969fb4541fSSam Bobroff } 9979fb4541fSSam Bobroff 9981e0e1108SDavid Gibson static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt, bool reset) 9997c866c6aSDavid Gibson { 10007c866c6aSDavid Gibson MachineState *machine = MACHINE(spapr); 10016c3829a2SAlexey Kardashevskiy SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 10027c866c6aSDavid Gibson int chosen; 10031e0e1108SDavid Gibson 10041e0e1108SDavid Gibson _FDT(chosen = fdt_add_subnode(fdt, 0, "chosen")); 10051e0e1108SDavid Gibson 10061e0e1108SDavid Gibson if (reset) { 10077c866c6aSDavid Gibson const char *boot_device = machine->boot_order; 10087c866c6aSDavid Gibson char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus); 10097c866c6aSDavid Gibson size_t cb = 0; 1010907aac2fSMark Cave-Ayland char *bootlist = get_boot_devices_list(&cb); 10117c866c6aSDavid Gibson 10125ced7895SAlexey Kardashevskiy if (machine->kernel_cmdline && machine->kernel_cmdline[0]) { 10135ced7895SAlexey Kardashevskiy _FDT(fdt_setprop_string(fdt, chosen, "bootargs", 10145ced7895SAlexey Kardashevskiy machine->kernel_cmdline)); 10155ced7895SAlexey Kardashevskiy } 10161e0e1108SDavid Gibson 10175ced7895SAlexey Kardashevskiy if (spapr->initrd_size) { 10187c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-start", 10197c866c6aSDavid Gibson spapr->initrd_base)); 10207c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-end", 10217c866c6aSDavid Gibson spapr->initrd_base + spapr->initrd_size)); 10225ced7895SAlexey Kardashevskiy } 10237c866c6aSDavid Gibson 10247c866c6aSDavid Gibson if (spapr->kernel_size) { 102587262806SAlexey Kardashevskiy uint64_t kprop[2] = { cpu_to_be64(spapr->kernel_addr), 10267c866c6aSDavid Gibson cpu_to_be64(spapr->kernel_size) }; 10277c866c6aSDavid Gibson 10287c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel", 10297c866c6aSDavid Gibson &kprop, sizeof(kprop))); 10307c866c6aSDavid Gibson if (spapr->kernel_le) { 10317c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel-le", NULL, 0)); 10327c866c6aSDavid Gibson } 10337c866c6aSDavid Gibson } 10347c866c6aSDavid Gibson if (boot_menu) { 10357c866c6aSDavid Gibson _FDT((fdt_setprop_cell(fdt, chosen, "qemu,boot-menu", boot_menu))); 10367c866c6aSDavid Gibson } 10377c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-width", graphic_width)); 10387c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-height", graphic_height)); 10397c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-depth", graphic_depth)); 10407c866c6aSDavid Gibson 10417c866c6aSDavid Gibson if (cb && bootlist) { 10427c866c6aSDavid Gibson int i; 10437c866c6aSDavid Gibson 10447c866c6aSDavid Gibson for (i = 0; i < cb; i++) { 10457c866c6aSDavid Gibson if (bootlist[i] == '\n') { 10467c866c6aSDavid Gibson bootlist[i] = ' '; 10477c866c6aSDavid Gibson } 10487c866c6aSDavid Gibson } 10497c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-list", bootlist)); 10507c866c6aSDavid Gibson } 10517c866c6aSDavid Gibson 10527c866c6aSDavid Gibson if (boot_device && strlen(boot_device)) { 10537c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-device", boot_device)); 10547c866c6aSDavid Gibson } 10557c866c6aSDavid Gibson 10567c866c6aSDavid Gibson if (!spapr->has_graphics && stdout_path) { 105790ee4e01SNikunj A Dadhania /* 10581e0e1108SDavid Gibson * "linux,stdout-path" and "stdout" properties are 10591e0e1108SDavid Gibson * deprecated by linux kernel. New platforms should only 10601e0e1108SDavid Gibson * use the "stdout-path" property. Set the new property 10611e0e1108SDavid Gibson * and continue using older property to remain compatible 10621e0e1108SDavid Gibson * with the existing firmware. 106390ee4e01SNikunj A Dadhania */ 10647c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "linux,stdout-path", stdout_path)); 106590ee4e01SNikunj A Dadhania _FDT(fdt_setprop_string(fdt, chosen, "stdout-path", stdout_path)); 10667c866c6aSDavid Gibson } 10677c866c6aSDavid Gibson 10681e0e1108SDavid Gibson /* 10691e0e1108SDavid Gibson * We can deal with BAR reallocation just fine, advertise it 10701e0e1108SDavid Gibson * to the guest 10711e0e1108SDavid Gibson */ 10726c3829a2SAlexey Kardashevskiy if (smc->linux_pci_probe) { 10736c3829a2SAlexey Kardashevskiy _FDT(fdt_setprop_cell(fdt, chosen, "linux,pci-probe-only", 0)); 10746c3829a2SAlexey Kardashevskiy } 10756c3829a2SAlexey Kardashevskiy 1076db592b5bSCédric Le Goater spapr_dt_ov5_platform_support(spapr, fdt, chosen); 10779fb4541fSSam Bobroff 10787c866c6aSDavid Gibson g_free(stdout_path); 10797c866c6aSDavid Gibson g_free(bootlist); 10807c866c6aSDavid Gibson } 10817c866c6aSDavid Gibson 108291335a5eSDavid Gibson _FDT(spapr_dt_ovec(fdt, chosen, spapr->ov5_cas, "ibm,architecture-vec-5")); 10831e0e1108SDavid Gibson } 10841e0e1108SDavid Gibson 1085ce2918cbSDavid Gibson static void spapr_dt_hypervisor(SpaprMachineState *spapr, void *fdt) 1086fca5f2dcSDavid Gibson { 1087fca5f2dcSDavid Gibson /* The /hypervisor node isn't in PAPR - this is a hack to allow PR 1088fca5f2dcSDavid Gibson * KVM to work under pHyp with some guest co-operation */ 1089fca5f2dcSDavid Gibson int hypervisor; 1090fca5f2dcSDavid Gibson uint8_t hypercall[16]; 1091fca5f2dcSDavid Gibson 1092fca5f2dcSDavid Gibson _FDT(hypervisor = fdt_add_subnode(fdt, 0, "hypervisor")); 1093fca5f2dcSDavid Gibson /* indicate KVM hypercall interface */ 1094fca5f2dcSDavid Gibson _FDT(fdt_setprop_string(fdt, hypervisor, "compatible", "linux,kvm")); 1095fca5f2dcSDavid Gibson if (kvmppc_has_cap_fixup_hcalls()) { 1096fca5f2dcSDavid Gibson /* 1097fca5f2dcSDavid Gibson * Older KVM versions with older guest kernels were broken 1098fca5f2dcSDavid Gibson * with the magic page, don't allow the guest to map it. 1099fca5f2dcSDavid Gibson */ 1100fca5f2dcSDavid Gibson if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall, 1101fca5f2dcSDavid Gibson sizeof(hypercall))) { 1102fca5f2dcSDavid Gibson _FDT(fdt_setprop(fdt, hypervisor, "hcall-instructions", 1103fca5f2dcSDavid Gibson hypercall, sizeof(hypercall))); 1104fca5f2dcSDavid Gibson } 1105fca5f2dcSDavid Gibson } 1106fca5f2dcSDavid Gibson } 1107fca5f2dcSDavid Gibson 11080c21e073SDavid Gibson void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space) 110953018216SPaolo Bonzini { 1110c86c1affSDaniel Henrique Barboza MachineState *machine = MACHINE(spapr); 11113c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 1112ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 11137c866c6aSDavid Gibson int ret; 111453018216SPaolo Bonzini void *fdt; 1115ce2918cbSDavid Gibson SpaprPhbState *phb; 1116398a0bd5SDavid Gibson char *buf; 111753018216SPaolo Bonzini 111897b32a6aSDavid Gibson fdt = g_malloc0(space); 111997b32a6aSDavid Gibson _FDT((fdt_create_empty_tree(fdt, space))); 112053018216SPaolo Bonzini 1121398a0bd5SDavid Gibson /* Root node */ 1122398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "device_type", "chrp")); 1123398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "model", "IBM pSeries (emulated by qemu)")); 1124398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "compatible", "qemu,pseries")); 1125398a0bd5SDavid Gibson 11260a794529SDavid Gibson /* Guest UUID & Name*/ 1127398a0bd5SDavid Gibson buf = qemu_uuid_unparse_strdup(&qemu_uuid); 1128398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "vm,uuid", buf)); 1129398a0bd5SDavid Gibson if (qemu_uuid_set) { 1130398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "system-id", buf)); 1131398a0bd5SDavid Gibson } 1132398a0bd5SDavid Gibson g_free(buf); 1133398a0bd5SDavid Gibson 1134398a0bd5SDavid Gibson if (qemu_get_vm_name()) { 1135398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "ibm,partition-name", 1136398a0bd5SDavid Gibson qemu_get_vm_name())); 1137398a0bd5SDavid Gibson } 1138398a0bd5SDavid Gibson 11390a794529SDavid Gibson /* Host Model & Serial Number */ 11400a794529SDavid Gibson if (spapr->host_model) { 11410a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model)); 11420a794529SDavid Gibson } else if (smc->broken_host_serial_model && kvmppc_get_host_model(&buf)) { 11430a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-model", buf)); 11440a794529SDavid Gibson g_free(buf); 11450a794529SDavid Gibson } 11460a794529SDavid Gibson 11470a794529SDavid Gibson if (spapr->host_serial) { 11480a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial)); 11490a794529SDavid Gibson } else if (smc->broken_host_serial_model && kvmppc_get_host_serial(&buf)) { 11500a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf)); 11510a794529SDavid Gibson g_free(buf); 11520a794529SDavid Gibson } 11530a794529SDavid Gibson 1154398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#address-cells", 2)); 1155398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2)); 115653018216SPaolo Bonzini 1157fc7e0765SDavid Gibson /* /interrupt controller */ 115805289273SDavid Gibson spapr_irq_dt(spapr, spapr_max_server_number(spapr), fdt, PHANDLE_INTC); 1159fc7e0765SDavid Gibson 116091335a5eSDavid Gibson ret = spapr_dt_memory(spapr, fdt); 1161e8f986fcSBharata B Rao if (ret < 0) { 1162ce9863b7SCédric Le Goater error_report("couldn't setup memory nodes in fdt"); 1163e8f986fcSBharata B Rao exit(1); 116453018216SPaolo Bonzini } 116553018216SPaolo Bonzini 1166bf5a6696SDavid Gibson /* /vdevice */ 1167bf5a6696SDavid Gibson spapr_dt_vdevice(spapr->vio_bus, fdt); 116853018216SPaolo Bonzini 11694d9392beSThomas Huth if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) { 117091335a5eSDavid Gibson ret = spapr_dt_rng(fdt); 11714d9392beSThomas Huth if (ret < 0) { 1172ce9863b7SCédric Le Goater error_report("could not set up rng device in the fdt"); 11734d9392beSThomas Huth exit(1); 11744d9392beSThomas Huth } 11754d9392beSThomas Huth } 11764d9392beSThomas Huth 117753018216SPaolo Bonzini QLIST_FOREACH(phb, &spapr->phbs, list) { 11788cbe71ecSDavid Gibson ret = spapr_dt_phb(spapr, phb, PHANDLE_INTC, fdt, NULL); 117953018216SPaolo Bonzini if (ret < 0) { 1180da34fed7SThomas Huth error_report("couldn't setup PCI devices in fdt"); 118153018216SPaolo Bonzini exit(1); 118253018216SPaolo Bonzini } 1183da34fed7SThomas Huth } 118453018216SPaolo Bonzini 118591335a5eSDavid Gibson spapr_dt_cpus(fdt, spapr); 118653018216SPaolo Bonzini 1187c20d332aSBharata B Rao if (smc->dr_lmb_enabled) { 11889e7d38e8SDavid Gibson _FDT(spapr_dt_drc(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB)); 1189c20d332aSBharata B Rao } 1190c20d332aSBharata B Rao 1191c5514d0eSIgor Mammedov if (mc->has_hotpluggable_cpus) { 1192af81cf32SBharata B Rao int offset = fdt_path_offset(fdt, "/cpus"); 11939e7d38e8SDavid Gibson ret = spapr_dt_drc(fdt, offset, NULL, SPAPR_DR_CONNECTOR_TYPE_CPU); 1194af81cf32SBharata B Rao if (ret < 0) { 1195af81cf32SBharata B Rao error_report("Couldn't set up CPU DR device tree properties"); 1196af81cf32SBharata B Rao exit(1); 1197af81cf32SBharata B Rao } 1198af81cf32SBharata B Rao } 1199af81cf32SBharata B Rao 1200ffb1e275SDavid Gibson /* /event-sources */ 1201ffbb1705SMichael Roth spapr_dt_events(spapr, fdt); 1202ffb1e275SDavid Gibson 12033f5dabceSDavid Gibson /* /rtas */ 12043f5dabceSDavid Gibson spapr_dt_rtas(spapr, fdt); 12053f5dabceSDavid Gibson 12067c866c6aSDavid Gibson /* /chosen */ 12071e0e1108SDavid Gibson spapr_dt_chosen(spapr, fdt, reset); 1208cf6e5223SDavid Gibson 1209fca5f2dcSDavid Gibson /* /hypervisor */ 1210fca5f2dcSDavid Gibson if (kvm_enabled()) { 1211fca5f2dcSDavid Gibson spapr_dt_hypervisor(spapr, fdt); 1212fca5f2dcSDavid Gibson } 1213fca5f2dcSDavid Gibson 1214cf6e5223SDavid Gibson /* Build memory reserve map */ 1215a49f62b9SAlexey Kardashevskiy if (reset) { 1216cf6e5223SDavid Gibson if (spapr->kernel_size) { 121787262806SAlexey Kardashevskiy _FDT((fdt_add_mem_rsv(fdt, spapr->kernel_addr, 121887262806SAlexey Kardashevskiy spapr->kernel_size))); 1219cf6e5223SDavid Gibson } 1220cf6e5223SDavid Gibson if (spapr->initrd_size) { 1221a49f62b9SAlexey Kardashevskiy _FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base, 1222a49f62b9SAlexey Kardashevskiy spapr->initrd_size))); 1223a49f62b9SAlexey Kardashevskiy } 1224cf6e5223SDavid Gibson } 1225cf6e5223SDavid Gibson 12263998ccd0SNathan Fontenot if (smc->dr_phb_enabled) { 12279e7d38e8SDavid Gibson ret = spapr_dt_drc(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_PHB); 12283998ccd0SNathan Fontenot if (ret < 0) { 12293998ccd0SNathan Fontenot error_report("Couldn't set up PHB DR device tree properties"); 12303998ccd0SNathan Fontenot exit(1); 12313998ccd0SNathan Fontenot } 12323998ccd0SNathan Fontenot } 12333998ccd0SNathan Fontenot 1234ee3a71e3SShivaprasad G Bhat /* NVDIMM devices */ 1235ee3a71e3SShivaprasad G Bhat if (mc->nvdimm_supported) { 1236f1aa45ffSDaniel Henrique Barboza spapr_dt_persistent_memory(spapr, fdt); 1237ee3a71e3SShivaprasad G Bhat } 1238ee3a71e3SShivaprasad G Bhat 1239997b6cfcSDavid Gibson return fdt; 124053018216SPaolo Bonzini } 124153018216SPaolo Bonzini 124253018216SPaolo Bonzini static uint64_t translate_kernel_address(void *opaque, uint64_t addr) 124353018216SPaolo Bonzini { 124487262806SAlexey Kardashevskiy SpaprMachineState *spapr = opaque; 124587262806SAlexey Kardashevskiy 124687262806SAlexey Kardashevskiy return (addr & 0x0fffffff) + spapr->kernel_addr; 124753018216SPaolo Bonzini } 124853018216SPaolo Bonzini 12491d1be34dSDavid Gibson static void emulate_spapr_hypercall(PPCVirtualHypervisor *vhyp, 12501d1be34dSDavid Gibson PowerPCCPU *cpu) 125153018216SPaolo Bonzini { 125253018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 125353018216SPaolo Bonzini 12548d04fb55SJan Kiszka /* The TCG path should also be holding the BQL at this point */ 12558d04fb55SJan Kiszka g_assert(qemu_mutex_iothread_locked()); 12568d04fb55SJan Kiszka 125753018216SPaolo Bonzini if (msr_pr) { 125853018216SPaolo Bonzini hcall_dprintf("Hypercall made with MSR[PR]=1\n"); 125953018216SPaolo Bonzini env->gpr[3] = H_PRIVILEGE; 126053018216SPaolo Bonzini } else { 126153018216SPaolo Bonzini env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]); 126253018216SPaolo Bonzini } 126353018216SPaolo Bonzini } 126453018216SPaolo Bonzini 126500fd075eSBenjamin Herrenschmidt struct LPCRSyncState { 126600fd075eSBenjamin Herrenschmidt target_ulong value; 126700fd075eSBenjamin Herrenschmidt target_ulong mask; 126800fd075eSBenjamin Herrenschmidt }; 126900fd075eSBenjamin Herrenschmidt 127000fd075eSBenjamin Herrenschmidt static void do_lpcr_sync(CPUState *cs, run_on_cpu_data arg) 127100fd075eSBenjamin Herrenschmidt { 127200fd075eSBenjamin Herrenschmidt struct LPCRSyncState *s = arg.host_ptr; 127300fd075eSBenjamin Herrenschmidt PowerPCCPU *cpu = POWERPC_CPU(cs); 127400fd075eSBenjamin Herrenschmidt CPUPPCState *env = &cpu->env; 127500fd075eSBenjamin Herrenschmidt target_ulong lpcr; 127600fd075eSBenjamin Herrenschmidt 127700fd075eSBenjamin Herrenschmidt cpu_synchronize_state(cs); 127800fd075eSBenjamin Herrenschmidt lpcr = env->spr[SPR_LPCR]; 127900fd075eSBenjamin Herrenschmidt lpcr &= ~s->mask; 128000fd075eSBenjamin Herrenschmidt lpcr |= s->value; 128100fd075eSBenjamin Herrenschmidt ppc_store_lpcr(cpu, lpcr); 128200fd075eSBenjamin Herrenschmidt } 128300fd075eSBenjamin Herrenschmidt 128400fd075eSBenjamin Herrenschmidt void spapr_set_all_lpcrs(target_ulong value, target_ulong mask) 128500fd075eSBenjamin Herrenschmidt { 128600fd075eSBenjamin Herrenschmidt CPUState *cs; 128700fd075eSBenjamin Herrenschmidt struct LPCRSyncState s = { 128800fd075eSBenjamin Herrenschmidt .value = value, 128900fd075eSBenjamin Herrenschmidt .mask = mask 129000fd075eSBenjamin Herrenschmidt }; 129100fd075eSBenjamin Herrenschmidt CPU_FOREACH(cs) { 129200fd075eSBenjamin Herrenschmidt run_on_cpu(cs, do_lpcr_sync, RUN_ON_CPU_HOST_PTR(&s)); 129300fd075eSBenjamin Herrenschmidt } 129400fd075eSBenjamin Herrenschmidt } 129500fd075eSBenjamin Herrenschmidt 129679825f4dSBenjamin Herrenschmidt static void spapr_get_pate(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry) 12979861bb3eSSuraj Jitindar Singh { 1298ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 12999861bb3eSSuraj Jitindar Singh 130079825f4dSBenjamin Herrenschmidt /* Copy PATE1:GR into PATE0:HR */ 130179825f4dSBenjamin Herrenschmidt entry->dw0 = spapr->patb_entry & PATE0_HR; 130279825f4dSBenjamin Herrenschmidt entry->dw1 = spapr->patb_entry; 13039861bb3eSSuraj Jitindar Singh } 13049861bb3eSSuraj Jitindar Singh 1305e6b8fd24SSamuel Mendoza-Jonas #define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2)) 1306e6b8fd24SSamuel Mendoza-Jonas #define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID) 1307e6b8fd24SSamuel Mendoza-Jonas #define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY) 1308e6b8fd24SSamuel Mendoza-Jonas #define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY)) 1309e6b8fd24SSamuel Mendoza-Jonas #define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY)) 1310e6b8fd24SSamuel Mendoza-Jonas 1311715c5407SDavid Gibson /* 1312715c5407SDavid Gibson * Get the fd to access the kernel htab, re-opening it if necessary 1313715c5407SDavid Gibson */ 1314ce2918cbSDavid Gibson static int get_htab_fd(SpaprMachineState *spapr) 1315715c5407SDavid Gibson { 131614b0d748SGreg Kurz Error *local_err = NULL; 131714b0d748SGreg Kurz 1318715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1319715c5407SDavid Gibson return spapr->htab_fd; 1320715c5407SDavid Gibson } 1321715c5407SDavid Gibson 132214b0d748SGreg Kurz spapr->htab_fd = kvmppc_get_htab_fd(false, 0, &local_err); 1323715c5407SDavid Gibson if (spapr->htab_fd < 0) { 132414b0d748SGreg Kurz error_report_err(local_err); 1325715c5407SDavid Gibson } 1326715c5407SDavid Gibson 1327715c5407SDavid Gibson return spapr->htab_fd; 1328715c5407SDavid Gibson } 1329715c5407SDavid Gibson 1330ce2918cbSDavid Gibson void close_htab_fd(SpaprMachineState *spapr) 1331715c5407SDavid Gibson { 1332715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1333715c5407SDavid Gibson close(spapr->htab_fd); 1334715c5407SDavid Gibson } 1335715c5407SDavid Gibson spapr->htab_fd = -1; 1336715c5407SDavid Gibson } 1337715c5407SDavid Gibson 1338e57ca75cSDavid Gibson static hwaddr spapr_hpt_mask(PPCVirtualHypervisor *vhyp) 1339e57ca75cSDavid Gibson { 1340ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1341e57ca75cSDavid Gibson 1342e57ca75cSDavid Gibson return HTAB_SIZE(spapr) / HASH_PTEG_SIZE_64 - 1; 1343e57ca75cSDavid Gibson } 1344e57ca75cSDavid Gibson 13451ec26c75SGreg Kurz static target_ulong spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp) 13461ec26c75SGreg Kurz { 1347ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 13481ec26c75SGreg Kurz 13491ec26c75SGreg Kurz assert(kvm_enabled()); 13501ec26c75SGreg Kurz 13511ec26c75SGreg Kurz if (!spapr->htab) { 13521ec26c75SGreg Kurz return 0; 13531ec26c75SGreg Kurz } 13541ec26c75SGreg Kurz 13551ec26c75SGreg Kurz return (target_ulong)(uintptr_t)spapr->htab | (spapr->htab_shift - 18); 13561ec26c75SGreg Kurz } 13571ec26c75SGreg Kurz 1358e57ca75cSDavid Gibson static const ppc_hash_pte64_t *spapr_map_hptes(PPCVirtualHypervisor *vhyp, 1359e57ca75cSDavid Gibson hwaddr ptex, int n) 1360e57ca75cSDavid Gibson { 1361ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1362e57ca75cSDavid Gibson hwaddr pte_offset = ptex * HASH_PTE_SIZE_64; 1363e57ca75cSDavid Gibson 1364e57ca75cSDavid Gibson if (!spapr->htab) { 1365e57ca75cSDavid Gibson /* 1366e57ca75cSDavid Gibson * HTAB is controlled by KVM. Fetch into temporary buffer 1367e57ca75cSDavid Gibson */ 1368e57ca75cSDavid Gibson ppc_hash_pte64_t *hptes = g_malloc(n * HASH_PTE_SIZE_64); 1369e57ca75cSDavid Gibson kvmppc_read_hptes(hptes, ptex, n); 1370e57ca75cSDavid Gibson return hptes; 1371e57ca75cSDavid Gibson } 1372e57ca75cSDavid Gibson 1373e57ca75cSDavid Gibson /* 1374e57ca75cSDavid Gibson * HTAB is controlled by QEMU. Just point to the internally 1375e57ca75cSDavid Gibson * accessible PTEG. 1376e57ca75cSDavid Gibson */ 1377e57ca75cSDavid Gibson return (const ppc_hash_pte64_t *)(spapr->htab + pte_offset); 1378e57ca75cSDavid Gibson } 1379e57ca75cSDavid Gibson 1380e57ca75cSDavid Gibson static void spapr_unmap_hptes(PPCVirtualHypervisor *vhyp, 1381e57ca75cSDavid Gibson const ppc_hash_pte64_t *hptes, 1382e57ca75cSDavid Gibson hwaddr ptex, int n) 1383e57ca75cSDavid Gibson { 1384ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1385e57ca75cSDavid Gibson 1386e57ca75cSDavid Gibson if (!spapr->htab) { 1387e57ca75cSDavid Gibson g_free((void *)hptes); 1388e57ca75cSDavid Gibson } 1389e57ca75cSDavid Gibson 1390e57ca75cSDavid Gibson /* Nothing to do for qemu managed HPT */ 1391e57ca75cSDavid Gibson } 1392e57ca75cSDavid Gibson 1393a2dd4e83SBenjamin Herrenschmidt void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex, 1394e57ca75cSDavid Gibson uint64_t pte0, uint64_t pte1) 1395e57ca75cSDavid Gibson { 1396a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(cpu->vhyp); 1397e57ca75cSDavid Gibson hwaddr offset = ptex * HASH_PTE_SIZE_64; 1398e57ca75cSDavid Gibson 1399e57ca75cSDavid Gibson if (!spapr->htab) { 1400e57ca75cSDavid Gibson kvmppc_write_hpte(ptex, pte0, pte1); 1401e57ca75cSDavid Gibson } else { 14023054b0caSBenjamin Herrenschmidt if (pte0 & HPTE64_V_VALID) { 1403e57ca75cSDavid Gibson stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); 14043054b0caSBenjamin Herrenschmidt /* 14053054b0caSBenjamin Herrenschmidt * When setting valid, we write PTE1 first. This ensures 14063054b0caSBenjamin Herrenschmidt * proper synchronization with the reading code in 14073054b0caSBenjamin Herrenschmidt * ppc_hash64_pteg_search() 14083054b0caSBenjamin Herrenschmidt */ 14093054b0caSBenjamin Herrenschmidt smp_wmb(); 14103054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset, pte0); 14113054b0caSBenjamin Herrenschmidt } else { 14123054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset, pte0); 14133054b0caSBenjamin Herrenschmidt /* 14143054b0caSBenjamin Herrenschmidt * When clearing it we set PTE0 first. This ensures proper 14153054b0caSBenjamin Herrenschmidt * 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 + HASH_PTE_SIZE_64 / 2, pte1); 14203054b0caSBenjamin Herrenschmidt } 1421e57ca75cSDavid Gibson } 1422e57ca75cSDavid Gibson } 1423e57ca75cSDavid Gibson 1424a2dd4e83SBenjamin Herrenschmidt static void spapr_hpte_set_c(PPCVirtualHypervisor *vhyp, hwaddr ptex, 1425a2dd4e83SBenjamin Herrenschmidt uint64_t pte1) 1426a2dd4e83SBenjamin Herrenschmidt { 1427a2dd4e83SBenjamin Herrenschmidt hwaddr offset = ptex * HASH_PTE_SIZE_64 + 15; 1428a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1429a2dd4e83SBenjamin Herrenschmidt 1430a2dd4e83SBenjamin Herrenschmidt if (!spapr->htab) { 1431a2dd4e83SBenjamin Herrenschmidt /* There should always be a hash table when this is called */ 1432a2dd4e83SBenjamin Herrenschmidt error_report("spapr_hpte_set_c called with no hash table !"); 1433a2dd4e83SBenjamin Herrenschmidt return; 1434a2dd4e83SBenjamin Herrenschmidt } 1435a2dd4e83SBenjamin Herrenschmidt 1436a2dd4e83SBenjamin Herrenschmidt /* The HW performs a non-atomic byte update */ 1437a2dd4e83SBenjamin Herrenschmidt stb_p(spapr->htab + offset, (pte1 & 0xff) | 0x80); 1438a2dd4e83SBenjamin Herrenschmidt } 1439a2dd4e83SBenjamin Herrenschmidt 1440a2dd4e83SBenjamin Herrenschmidt static void spapr_hpte_set_r(PPCVirtualHypervisor *vhyp, hwaddr ptex, 1441a2dd4e83SBenjamin Herrenschmidt uint64_t pte1) 1442a2dd4e83SBenjamin Herrenschmidt { 1443a2dd4e83SBenjamin Herrenschmidt hwaddr offset = ptex * HASH_PTE_SIZE_64 + 14; 1444a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1445a2dd4e83SBenjamin Herrenschmidt 1446a2dd4e83SBenjamin Herrenschmidt if (!spapr->htab) { 1447a2dd4e83SBenjamin Herrenschmidt /* There should always be a hash table when this is called */ 1448a2dd4e83SBenjamin Herrenschmidt error_report("spapr_hpte_set_r called with no hash table !"); 1449a2dd4e83SBenjamin Herrenschmidt return; 1450a2dd4e83SBenjamin Herrenschmidt } 1451a2dd4e83SBenjamin Herrenschmidt 1452a2dd4e83SBenjamin Herrenschmidt /* The HW performs a non-atomic byte update */ 1453a2dd4e83SBenjamin Herrenschmidt stb_p(spapr->htab + offset, ((pte1 >> 8) & 0xff) | 0x01); 1454a2dd4e83SBenjamin Herrenschmidt } 1455a2dd4e83SBenjamin Herrenschmidt 14560b0b8310SDavid Gibson int spapr_hpt_shift_for_ramsize(uint64_t ramsize) 14578dfe8e7fSDavid Gibson { 14588dfe8e7fSDavid Gibson int shift; 14598dfe8e7fSDavid Gibson 14608dfe8e7fSDavid Gibson /* We aim for a hash table of size 1/128 the size of RAM (rounded 14618dfe8e7fSDavid Gibson * up). The PAPR recommendation is actually 1/64 of RAM size, but 14628dfe8e7fSDavid Gibson * that's much more than is needed for Linux guests */ 14638dfe8e7fSDavid Gibson shift = ctz64(pow2ceil(ramsize)) - 7; 14648dfe8e7fSDavid Gibson shift = MAX(shift, 18); /* Minimum architected size */ 14658dfe8e7fSDavid Gibson shift = MIN(shift, 46); /* Maximum architected size */ 14668dfe8e7fSDavid Gibson return shift; 14678dfe8e7fSDavid Gibson } 14688dfe8e7fSDavid Gibson 1469ce2918cbSDavid Gibson void spapr_free_hpt(SpaprMachineState *spapr) 147006ec79e8SBharata B Rao { 147106ec79e8SBharata B Rao g_free(spapr->htab); 147206ec79e8SBharata B Rao spapr->htab = NULL; 147306ec79e8SBharata B Rao spapr->htab_shift = 0; 147406ec79e8SBharata B Rao close_htab_fd(spapr); 147506ec79e8SBharata B Rao } 147606ec79e8SBharata B Rao 1477ce2918cbSDavid Gibson void spapr_reallocate_hpt(SpaprMachineState *spapr, int shift, 1478c5f54f3eSDavid Gibson Error **errp) 147953018216SPaolo Bonzini { 1480c5f54f3eSDavid Gibson long rc; 148153018216SPaolo Bonzini 1482c5f54f3eSDavid Gibson /* Clean up any HPT info from a previous boot */ 148306ec79e8SBharata B Rao spapr_free_hpt(spapr); 148453018216SPaolo Bonzini 1485c5f54f3eSDavid Gibson rc = kvmppc_reset_htab(shift); 1486f0638a0bSFabiano Rosas 1487f0638a0bSFabiano Rosas if (rc == -EOPNOTSUPP) { 1488f0638a0bSFabiano Rosas error_setg(errp, "HPT not supported in nested guests"); 1489f0638a0bSFabiano Rosas return; 1490f0638a0bSFabiano Rosas } 1491f0638a0bSFabiano Rosas 1492c5f54f3eSDavid Gibson if (rc < 0) { 1493c5f54f3eSDavid Gibson /* kernel-side HPT needed, but couldn't allocate one */ 1494c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1495c5f54f3eSDavid Gibson "Failed to allocate KVM HPT of order %d (try smaller maxmem?)", 1496c5f54f3eSDavid Gibson shift); 1497c5f54f3eSDavid Gibson /* This is almost certainly fatal, but if the caller really 1498c5f54f3eSDavid Gibson * wants to carry on with shift == 0, it's welcome to try */ 1499c5f54f3eSDavid Gibson } else if (rc > 0) { 1500c5f54f3eSDavid Gibson /* kernel-side HPT allocated */ 1501c5f54f3eSDavid Gibson if (rc != shift) { 1502c5f54f3eSDavid Gibson error_setg(errp, 1503c5f54f3eSDavid Gibson "Requested order %d HPT, but kernel allocated order %ld (try smaller maxmem?)", 1504c5f54f3eSDavid Gibson shift, rc); 15057735fedaSBharata B Rao } 15067735fedaSBharata B Rao 150753018216SPaolo Bonzini spapr->htab_shift = shift; 1508c18ad9a5SDavid Gibson spapr->htab = NULL; 1509b817772aSBharata B Rao } else { 1510c5f54f3eSDavid Gibson /* kernel-side HPT not needed, allocate in userspace instead */ 1511c5f54f3eSDavid Gibson size_t size = 1ULL << shift; 1512c5f54f3eSDavid Gibson int i; 151301a57972SSamuel Mendoza-Jonas 1514c5f54f3eSDavid Gibson spapr->htab = qemu_memalign(size, size); 1515c5f54f3eSDavid Gibson if (!spapr->htab) { 1516c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1517c5f54f3eSDavid Gibson "Could not allocate HPT of order %d", shift); 1518c5f54f3eSDavid Gibson return; 1519b817772aSBharata B Rao } 1520b817772aSBharata B Rao 1521c5f54f3eSDavid Gibson memset(spapr->htab, 0, size); 1522c5f54f3eSDavid Gibson spapr->htab_shift = shift; 1523b817772aSBharata B Rao 1524c5f54f3eSDavid Gibson for (i = 0; i < size / HASH_PTE_SIZE_64; i++) { 1525c5f54f3eSDavid Gibson DIRTY_HPTE(HPTE(spapr->htab, i)); 15267735fedaSBharata B Rao } 152753018216SPaolo Bonzini } 1528ee4d9eccSSuraj Jitindar Singh /* We're setting up a hash table, so that means we're not radix */ 1529176dcceeSSuraj Jitindar Singh spapr->patb_entry = 0; 153000fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(0, LPCR_HR | LPCR_UPRT); 153153018216SPaolo Bonzini } 153253018216SPaolo Bonzini 15338897ea5aSDavid Gibson void spapr_setup_hpt(SpaprMachineState *spapr) 1534b4db5413SSuraj Jitindar Singh { 15352772cf6bSDavid Gibson int hpt_shift; 15362772cf6bSDavid Gibson 1537087820e3SGreg Kurz if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DISABLED) { 15382772cf6bSDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(MACHINE(spapr)->maxram_size); 15392772cf6bSDavid Gibson } else { 1540768a20f3SDavid Gibson uint64_t current_ram_size; 1541768a20f3SDavid Gibson 1542768a20f3SDavid Gibson current_ram_size = MACHINE(spapr)->ram_size + get_plugged_memory_size(); 1543768a20f3SDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(current_ram_size); 15442772cf6bSDavid Gibson } 15452772cf6bSDavid Gibson spapr_reallocate_hpt(spapr, hpt_shift, &error_fatal); 15462772cf6bSDavid Gibson 15478897ea5aSDavid Gibson if (kvm_enabled()) { 15486a84737cSDavid Gibson hwaddr vrma_limit = kvmppc_vrma_limit(spapr->htab_shift); 15496a84737cSDavid Gibson 15508897ea5aSDavid Gibson /* Check our RMA fits in the possible VRMA */ 15518897ea5aSDavid Gibson if (vrma_limit < spapr->rma_size) { 15528897ea5aSDavid Gibson error_report("Unable to create %" HWADDR_PRIu 15538897ea5aSDavid Gibson "MiB RMA (VRMA only allows %" HWADDR_PRIu "MiB", 15548897ea5aSDavid Gibson spapr->rma_size / MiB, vrma_limit / MiB); 15558897ea5aSDavid Gibson exit(EXIT_FAILURE); 15568897ea5aSDavid Gibson } 1557b4db5413SSuraj Jitindar Singh } 1558b4db5413SSuraj Jitindar Singh } 1559b4db5413SSuraj Jitindar Singh 156082512483SGreg Kurz static int spapr_reset_drcs(Object *child, void *opaque) 156182512483SGreg Kurz { 1562ce2918cbSDavid Gibson SpaprDrc *drc = 1563ce2918cbSDavid Gibson (SpaprDrc *) object_dynamic_cast(child, 156482512483SGreg Kurz TYPE_SPAPR_DR_CONNECTOR); 156582512483SGreg Kurz 156682512483SGreg Kurz if (drc) { 156782512483SGreg Kurz spapr_drc_reset(drc); 156882512483SGreg Kurz } 156982512483SGreg Kurz 157082512483SGreg Kurz return 0; 157182512483SGreg Kurz } 157282512483SGreg Kurz 1573a0628599SLike Xu static void spapr_machine_reset(MachineState *machine) 157453018216SPaolo Bonzini { 1575ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(machine); 1576182735efSAndreas Färber PowerPCCPU *first_ppc_cpu; 1577744a928cSAlexey Kardashevskiy hwaddr fdt_addr; 1578997b6cfcSDavid Gibson void *fdt; 1579997b6cfcSDavid Gibson int rc; 1580259186a7SAndreas Färber 1581905db916SBharata B Rao kvmppc_svm_off(&error_fatal); 15829f6edd06SDavid Gibson spapr_caps_apply(spapr); 158333face6bSDavid Gibson 15841481fe5fSLaurent Vivier first_ppc_cpu = POWERPC_CPU(first_cpu); 15851481fe5fSLaurent Vivier if (kvm_enabled() && kvmppc_has_cap_mmu_radix() && 1586ad99d04cSDavid Gibson ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, 15871481fe5fSLaurent Vivier spapr->max_compat_pvr)) { 158879825f4dSBenjamin Herrenschmidt /* 158979825f4dSBenjamin Herrenschmidt * If using KVM with radix mode available, VCPUs can be started 1590b4db5413SSuraj Jitindar Singh * without a HPT because KVM will start them in radix mode. 159179825f4dSBenjamin Herrenschmidt * Set the GR bit in PATE so that we know there is no HPT. 159279825f4dSBenjamin Herrenschmidt */ 159379825f4dSBenjamin Herrenschmidt spapr->patb_entry = PATE1_GR; 159400fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(LPCR_HR | LPCR_UPRT, LPCR_HR | LPCR_UPRT); 1595b4db5413SSuraj Jitindar Singh } else { 15968897ea5aSDavid Gibson spapr_setup_hpt(spapr); 1597c5f54f3eSDavid Gibson } 159853018216SPaolo Bonzini 159925c9780dSDavid Gibson qemu_devices_reset(); 160025c9780dSDavid Gibson 16019012a53fSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas); 16029012a53fSGreg Kurz spapr->ov5_cas = spapr_ovec_new(); 16039012a53fSGreg Kurz 1604ce03a193SLaurent Vivier ppc_set_compat_all(spapr->max_compat_pvr, &error_fatal); 16059012a53fSGreg Kurz 1606ec132efaSAlexey Kardashevskiy /* 1607b2e22477SCédric Le Goater * This is fixing some of the default configuration of the XIVE 1608b2e22477SCédric Le Goater * devices. To be called after the reset of the machine devices. 1609b2e22477SCédric Le Goater */ 1610b2e22477SCédric Le Goater spapr_irq_reset(spapr, &error_fatal); 1611b2e22477SCédric Le Goater 161223ff81bdSGreg Kurz /* 161323ff81bdSGreg Kurz * There is no CAS under qtest. Simulate one to please the code that 161423ff81bdSGreg Kurz * depends on spapr->ov5_cas. This is especially needed to test device 161523ff81bdSGreg Kurz * unplug, so we do that before resetting the DRCs. 161623ff81bdSGreg Kurz */ 161723ff81bdSGreg Kurz if (qtest_enabled()) { 161823ff81bdSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas); 161923ff81bdSGreg Kurz spapr->ov5_cas = spapr_ovec_clone(spapr->ov5); 162023ff81bdSGreg Kurz } 162123ff81bdSGreg Kurz 162282512483SGreg Kurz /* DRC reset may cause a device to be unplugged. This will cause troubles 162382512483SGreg Kurz * if this device is used by another device (eg, a running vhost backend 162482512483SGreg Kurz * will crash QEMU if the DIMM holding the vring goes away). To avoid such 162582512483SGreg Kurz * situations, we reset DRCs after all devices have been reset. 162682512483SGreg Kurz */ 162782512483SGreg Kurz object_child_foreach_recursive(object_get_root(), spapr_reset_drcs, NULL); 162882512483SGreg Kurz 162956258174SDaniel Henrique Barboza spapr_clear_pending_events(spapr); 163053018216SPaolo Bonzini 1631b7d1f77aSBenjamin Herrenschmidt /* 1632b7d1f77aSBenjamin Herrenschmidt * We place the device tree and RTAS just below either the top of the RMA, 1633df269271SAlexey Kardashevskiy * or just below 2GB, whichever is lower, so that it can be 1634b7d1f77aSBenjamin Herrenschmidt * processed with 32-bit real mode code if necessary 1635b7d1f77aSBenjamin Herrenschmidt */ 1636744a928cSAlexey Kardashevskiy fdt_addr = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FDT_MAX_SIZE; 1637b7d1f77aSBenjamin Herrenschmidt 163897b32a6aSDavid Gibson fdt = spapr_build_fdt(spapr, true, FDT_MAX_SIZE); 163953018216SPaolo Bonzini 1640997b6cfcSDavid Gibson rc = fdt_pack(fdt); 1641997b6cfcSDavid Gibson 1642997b6cfcSDavid Gibson /* Should only fail if we've built a corrupted tree */ 1643997b6cfcSDavid Gibson assert(rc == 0); 1644997b6cfcSDavid Gibson 1645997b6cfcSDavid Gibson /* Load the fdt */ 1646997b6cfcSDavid Gibson qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 1647cae172abSDavid Gibson cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); 1648fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob); 1649fea35ca4SAlexey Kardashevskiy spapr->fdt_size = fdt_totalsize(fdt); 1650fea35ca4SAlexey Kardashevskiy spapr->fdt_initial_size = spapr->fdt_size; 1651fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = fdt; 1652997b6cfcSDavid Gibson 165353018216SPaolo Bonzini /* Set up the entry state */ 1654395a20d3SAlexey Kardashevskiy spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT, 0, fdt_addr, 0); 1655182735efSAndreas Färber first_ppc_cpu->env.gpr[5] = 0; 165653018216SPaolo Bonzini 1657edfdbf9cSNicholas Piggin spapr->fwnmi_system_reset_addr = -1; 16588af7e1feSNicholas Piggin spapr->fwnmi_machine_check_addr = -1; 16598af7e1feSNicholas Piggin spapr->fwnmi_machine_check_interlock = -1; 16609ac703acSAravinda Prasad 16619ac703acSAravinda Prasad /* Signal all vCPUs waiting on this condition */ 16628af7e1feSNicholas Piggin qemu_cond_broadcast(&spapr->fwnmi_machine_check_interlock_cond); 16632500fb42SAravinda Prasad 16642500fb42SAravinda Prasad migrate_del_blocker(spapr->fwnmi_migration_blocker); 166553018216SPaolo Bonzini } 166653018216SPaolo Bonzini 1667ce2918cbSDavid Gibson static void spapr_create_nvram(SpaprMachineState *spapr) 166853018216SPaolo Bonzini { 16693e80f690SMarkus Armbruster DeviceState *dev = qdev_new("spapr-nvram"); 16703978b863SPaolo Bonzini DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); 167153018216SPaolo Bonzini 16723978b863SPaolo Bonzini if (dinfo) { 1673934df912SMarkus Armbruster qdev_prop_set_drive_err(dev, "drive", blk_by_legacy_dinfo(dinfo), 16746231a6daSMarkus Armbruster &error_fatal); 167553018216SPaolo Bonzini } 167653018216SPaolo Bonzini 16773e80f690SMarkus Armbruster qdev_realize_and_unref(dev, &spapr->vio_bus->bus, &error_fatal); 167853018216SPaolo Bonzini 1679ce2918cbSDavid Gibson spapr->nvram = (struct SpaprNvram *)dev; 168053018216SPaolo Bonzini } 168153018216SPaolo Bonzini 1682ce2918cbSDavid Gibson static void spapr_rtc_create(SpaprMachineState *spapr) 168328df36a1SDavid Gibson { 16849fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(spapr), "rtc", &spapr->rtc, 16859fc7fc4dSMarkus Armbruster sizeof(spapr->rtc), TYPE_SPAPR_RTC, 1686f6d4dca8SThomas Huth &error_fatal, NULL); 1687ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&spapr->rtc), NULL, &error_fatal); 1688147ff807SCédric Le Goater object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc), 1689d2623129SMarkus Armbruster "date"); 169028df36a1SDavid Gibson } 169128df36a1SDavid Gibson 169253018216SPaolo Bonzini /* Returns whether we want to use VGA or not */ 169314c6a894SDavid Gibson static bool spapr_vga_init(PCIBus *pci_bus, Error **errp) 169453018216SPaolo Bonzini { 169553018216SPaolo Bonzini switch (vga_interface_type) { 169653018216SPaolo Bonzini case VGA_NONE: 16977effdaa3SMark Wu return false; 16987effdaa3SMark Wu case VGA_DEVICE: 16997effdaa3SMark Wu return true; 170053018216SPaolo Bonzini case VGA_STD: 1701b798c190SBenjamin Herrenschmidt case VGA_VIRTIO: 17026e66d0c6SThomas Huth case VGA_CIRRUS: 170353018216SPaolo Bonzini return pci_vga_init(pci_bus) != NULL; 170453018216SPaolo Bonzini default: 170514c6a894SDavid Gibson error_setg(errp, 170614c6a894SDavid Gibson "Unsupported VGA mode, only -vga std or -vga virtio is supported"); 170714c6a894SDavid Gibson return false; 170853018216SPaolo Bonzini } 170953018216SPaolo Bonzini } 171053018216SPaolo Bonzini 17114e5fe368SSuraj Jitindar Singh static int spapr_pre_load(void *opaque) 17124e5fe368SSuraj Jitindar Singh { 17134e5fe368SSuraj Jitindar Singh int rc; 17144e5fe368SSuraj Jitindar Singh 17154e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_load(opaque); 17164e5fe368SSuraj Jitindar Singh if (rc) { 17174e5fe368SSuraj Jitindar Singh return rc; 17184e5fe368SSuraj Jitindar Singh } 17194e5fe368SSuraj Jitindar Singh 17204e5fe368SSuraj Jitindar Singh return 0; 17214e5fe368SSuraj Jitindar Singh } 17224e5fe368SSuraj Jitindar Singh 1723880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id) 1724880ae7deSDavid Gibson { 1725ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 1726880ae7deSDavid Gibson int err = 0; 1727880ae7deSDavid Gibson 1728be85537dSDavid Gibson err = spapr_caps_post_migration(spapr); 1729be85537dSDavid Gibson if (err) { 1730be85537dSDavid Gibson return err; 1731be85537dSDavid Gibson } 1732be85537dSDavid Gibson 1733e502202cSCédric Le Goater /* 1734e502202cSCédric Le Goater * In earlier versions, there was no separate qdev for the PAPR 1735880ae7deSDavid Gibson * RTC, so the RTC offset was stored directly in sPAPREnvironment. 1736880ae7deSDavid Gibson * So when migrating from those versions, poke the incoming offset 1737e502202cSCédric Le Goater * value into the RTC device 1738e502202cSCédric Le Goater */ 1739880ae7deSDavid Gibson if (version_id < 3) { 1740147ff807SCédric Le Goater err = spapr_rtc_import_offset(&spapr->rtc, spapr->rtc_offset); 1741e502202cSCédric Le Goater if (err) { 1742e502202cSCédric Le Goater return err; 1743e502202cSCédric Le Goater } 1744880ae7deSDavid Gibson } 1745880ae7deSDavid Gibson 17460c86b2dfSLaurent Vivier if (kvm_enabled() && spapr->patb_entry) { 1747d39c90f5SBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(first_cpu); 174879825f4dSBenjamin Herrenschmidt bool radix = !!(spapr->patb_entry & PATE1_GR); 1749d39c90f5SBharata B Rao bool gtse = !!(cpu->env.spr[SPR_LPCR] & LPCR_GTSE); 1750d39c90f5SBharata B Rao 175100fd075eSBenjamin Herrenschmidt /* 175200fd075eSBenjamin Herrenschmidt * Update LPCR:HR and UPRT as they may not be set properly in 175300fd075eSBenjamin Herrenschmidt * the stream 175400fd075eSBenjamin Herrenschmidt */ 175500fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(radix ? (LPCR_HR | LPCR_UPRT) : 0, 175600fd075eSBenjamin Herrenschmidt LPCR_HR | LPCR_UPRT); 175700fd075eSBenjamin Herrenschmidt 1758d39c90f5SBharata B Rao err = kvmppc_configure_v3_mmu(cpu, radix, gtse, spapr->patb_entry); 1759d39c90f5SBharata B Rao if (err) { 1760d39c90f5SBharata B Rao error_report("Process table config unsupported by the host"); 1761d39c90f5SBharata B Rao return -EINVAL; 1762d39c90f5SBharata B Rao } 1763d39c90f5SBharata B Rao } 1764d39c90f5SBharata B Rao 17651c53b06cSCédric Le Goater err = spapr_irq_post_load(spapr, version_id); 17661c53b06cSCédric Le Goater if (err) { 17671c53b06cSCédric Le Goater return err; 17681c53b06cSCédric Le Goater } 17691c53b06cSCédric Le Goater 1770880ae7deSDavid Gibson return err; 1771880ae7deSDavid Gibson } 1772880ae7deSDavid Gibson 17734e5fe368SSuraj Jitindar Singh static int spapr_pre_save(void *opaque) 17744e5fe368SSuraj Jitindar Singh { 17754e5fe368SSuraj Jitindar Singh int rc; 17764e5fe368SSuraj Jitindar Singh 17774e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_save(opaque); 17784e5fe368SSuraj Jitindar Singh if (rc) { 17794e5fe368SSuraj Jitindar Singh return rc; 17804e5fe368SSuraj Jitindar Singh } 17814e5fe368SSuraj Jitindar Singh 17824e5fe368SSuraj Jitindar Singh return 0; 17834e5fe368SSuraj Jitindar Singh } 17844e5fe368SSuraj Jitindar Singh 1785880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id) 1786880ae7deSDavid Gibson { 1787880ae7deSDavid Gibson return version_id < 3; 1788880ae7deSDavid Gibson } 1789880ae7deSDavid Gibson 1790fd38804bSDaniel Henrique Barboza static bool spapr_pending_events_needed(void *opaque) 1791fd38804bSDaniel Henrique Barboza { 1792ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 1793fd38804bSDaniel Henrique Barboza return !QTAILQ_EMPTY(&spapr->pending_events); 1794fd38804bSDaniel Henrique Barboza } 1795fd38804bSDaniel Henrique Barboza 1796fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_event_entry = { 1797fd38804bSDaniel Henrique Barboza .name = "spapr_event_log_entry", 1798fd38804bSDaniel Henrique Barboza .version_id = 1, 1799fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1800fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 1801ce2918cbSDavid Gibson VMSTATE_UINT32(summary, SpaprEventLogEntry), 1802ce2918cbSDavid Gibson VMSTATE_UINT32(extended_length, SpaprEventLogEntry), 1803ce2918cbSDavid Gibson VMSTATE_VBUFFER_ALLOC_UINT32(extended_log, SpaprEventLogEntry, 0, 18045341258eSDavid Gibson NULL, extended_length), 1805fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1806fd38804bSDaniel Henrique Barboza }, 1807fd38804bSDaniel Henrique Barboza }; 1808fd38804bSDaniel Henrique Barboza 1809fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_pending_events = { 1810fd38804bSDaniel Henrique Barboza .name = "spapr_pending_events", 1811fd38804bSDaniel Henrique Barboza .version_id = 1, 1812fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1813fd38804bSDaniel Henrique Barboza .needed = spapr_pending_events_needed, 1814fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 1815ce2918cbSDavid Gibson VMSTATE_QTAILQ_V(pending_events, SpaprMachineState, 1, 1816ce2918cbSDavid Gibson vmstate_spapr_event_entry, SpaprEventLogEntry, next), 1817fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1818fd38804bSDaniel Henrique Barboza }, 1819fd38804bSDaniel Henrique Barboza }; 1820fd38804bSDaniel Henrique Barboza 182162ef3760SMichael Roth static bool spapr_ov5_cas_needed(void *opaque) 182262ef3760SMichael Roth { 1823ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 1824ce2918cbSDavid Gibson SpaprOptionVector *ov5_mask = spapr_ovec_new(); 182562ef3760SMichael Roth bool cas_needed; 182662ef3760SMichael Roth 1827ce2918cbSDavid Gibson /* Prior to the introduction of SpaprOptionVector, we had two option 182862ef3760SMichael Roth * vectors we dealt with: OV5_FORM1_AFFINITY, and OV5_DRCONF_MEMORY. 182962ef3760SMichael Roth * Both of these options encode machine topology into the device-tree 183062ef3760SMichael Roth * in such a way that the now-booted OS should still be able to interact 183162ef3760SMichael Roth * appropriately with QEMU regardless of what options were actually 183262ef3760SMichael Roth * negotiatied on the source side. 183362ef3760SMichael Roth * 183462ef3760SMichael Roth * As such, we can avoid migrating the CAS-negotiated options if these 183562ef3760SMichael Roth * are the only options available on the current machine/platform. 183662ef3760SMichael Roth * Since these are the only options available for pseries-2.7 and 183762ef3760SMichael Roth * earlier, this allows us to maintain old->new/new->old migration 183862ef3760SMichael Roth * compatibility. 183962ef3760SMichael Roth * 184062ef3760SMichael Roth * For QEMU 2.8+, there are additional CAS-negotiatable options available 184162ef3760SMichael Roth * via default pseries-2.8 machines and explicit command-line parameters. 184262ef3760SMichael Roth * Some of these options, like OV5_HP_EVT, *do* require QEMU to be aware 184362ef3760SMichael Roth * of the actual CAS-negotiated values to continue working properly. For 184462ef3760SMichael Roth * example, availability of memory unplug depends on knowing whether 184562ef3760SMichael Roth * OV5_HP_EVT was negotiated via CAS. 184662ef3760SMichael Roth * 184762ef3760SMichael Roth * Thus, for any cases where the set of available CAS-negotiatable 184862ef3760SMichael Roth * options extends beyond OV5_FORM1_AFFINITY and OV5_DRCONF_MEMORY, we 1849aef19c04SGreg Kurz * include the CAS-negotiated options in the migration stream, unless 1850aef19c04SGreg Kurz * if they affect boot time behaviour only. 185162ef3760SMichael Roth */ 185262ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_FORM1_AFFINITY); 185362ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_DRCONF_MEMORY); 1854aef19c04SGreg Kurz spapr_ovec_set(ov5_mask, OV5_DRMEM_V2); 185562ef3760SMichael Roth 1856d1d32d62SDavid Gibson /* We need extra information if we have any bits outside the mask 1857d1d32d62SDavid Gibson * defined above */ 1858d1d32d62SDavid Gibson cas_needed = !spapr_ovec_subset(spapr->ov5, ov5_mask); 185962ef3760SMichael Roth 186062ef3760SMichael Roth spapr_ovec_cleanup(ov5_mask); 186162ef3760SMichael Roth 186262ef3760SMichael Roth return cas_needed; 186362ef3760SMichael Roth } 186462ef3760SMichael Roth 186562ef3760SMichael Roth static const VMStateDescription vmstate_spapr_ov5_cas = { 186662ef3760SMichael Roth .name = "spapr_option_vector_ov5_cas", 186762ef3760SMichael Roth .version_id = 1, 186862ef3760SMichael Roth .minimum_version_id = 1, 186962ef3760SMichael Roth .needed = spapr_ov5_cas_needed, 187062ef3760SMichael Roth .fields = (VMStateField[]) { 1871ce2918cbSDavid Gibson VMSTATE_STRUCT_POINTER_V(ov5_cas, SpaprMachineState, 1, 1872ce2918cbSDavid Gibson vmstate_spapr_ovec, SpaprOptionVector), 187362ef3760SMichael Roth VMSTATE_END_OF_LIST() 187462ef3760SMichael Roth }, 187562ef3760SMichael Roth }; 187662ef3760SMichael Roth 18779861bb3eSSuraj Jitindar Singh static bool spapr_patb_entry_needed(void *opaque) 18789861bb3eSSuraj Jitindar Singh { 1879ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 18809861bb3eSSuraj Jitindar Singh 18819861bb3eSSuraj Jitindar Singh return !!spapr->patb_entry; 18829861bb3eSSuraj Jitindar Singh } 18839861bb3eSSuraj Jitindar Singh 18849861bb3eSSuraj Jitindar Singh static const VMStateDescription vmstate_spapr_patb_entry = { 18859861bb3eSSuraj Jitindar Singh .name = "spapr_patb_entry", 18869861bb3eSSuraj Jitindar Singh .version_id = 1, 18879861bb3eSSuraj Jitindar Singh .minimum_version_id = 1, 18889861bb3eSSuraj Jitindar Singh .needed = spapr_patb_entry_needed, 18899861bb3eSSuraj Jitindar Singh .fields = (VMStateField[]) { 1890ce2918cbSDavid Gibson VMSTATE_UINT64(patb_entry, SpaprMachineState), 18919861bb3eSSuraj Jitindar Singh VMSTATE_END_OF_LIST() 18929861bb3eSSuraj Jitindar Singh }, 18939861bb3eSSuraj Jitindar Singh }; 18949861bb3eSSuraj Jitindar Singh 189582cffa2eSCédric Le Goater static bool spapr_irq_map_needed(void *opaque) 189682cffa2eSCédric Le Goater { 1897ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 189882cffa2eSCédric Le Goater 189982cffa2eSCédric Le Goater return spapr->irq_map && !bitmap_empty(spapr->irq_map, spapr->irq_map_nr); 190082cffa2eSCédric Le Goater } 190182cffa2eSCédric Le Goater 190282cffa2eSCédric Le Goater static const VMStateDescription vmstate_spapr_irq_map = { 190382cffa2eSCédric Le Goater .name = "spapr_irq_map", 190482cffa2eSCédric Le Goater .version_id = 1, 190582cffa2eSCédric Le Goater .minimum_version_id = 1, 190682cffa2eSCédric Le Goater .needed = spapr_irq_map_needed, 190782cffa2eSCédric Le Goater .fields = (VMStateField[]) { 1908ce2918cbSDavid Gibson VMSTATE_BITMAP(irq_map, SpaprMachineState, 0, irq_map_nr), 190982cffa2eSCédric Le Goater VMSTATE_END_OF_LIST() 191082cffa2eSCédric Le Goater }, 191182cffa2eSCédric Le Goater }; 191282cffa2eSCédric Le Goater 1913fea35ca4SAlexey Kardashevskiy static bool spapr_dtb_needed(void *opaque) 1914fea35ca4SAlexey Kardashevskiy { 1915ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(opaque); 1916fea35ca4SAlexey Kardashevskiy 1917fea35ca4SAlexey Kardashevskiy return smc->update_dt_enabled; 1918fea35ca4SAlexey Kardashevskiy } 1919fea35ca4SAlexey Kardashevskiy 1920fea35ca4SAlexey Kardashevskiy static int spapr_dtb_pre_load(void *opaque) 1921fea35ca4SAlexey Kardashevskiy { 1922ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 1923fea35ca4SAlexey Kardashevskiy 1924fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob); 1925fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = NULL; 1926fea35ca4SAlexey Kardashevskiy spapr->fdt_size = 0; 1927fea35ca4SAlexey Kardashevskiy 1928fea35ca4SAlexey Kardashevskiy return 0; 1929fea35ca4SAlexey Kardashevskiy } 1930fea35ca4SAlexey Kardashevskiy 1931fea35ca4SAlexey Kardashevskiy static const VMStateDescription vmstate_spapr_dtb = { 1932fea35ca4SAlexey Kardashevskiy .name = "spapr_dtb", 1933fea35ca4SAlexey Kardashevskiy .version_id = 1, 1934fea35ca4SAlexey Kardashevskiy .minimum_version_id = 1, 1935fea35ca4SAlexey Kardashevskiy .needed = spapr_dtb_needed, 1936fea35ca4SAlexey Kardashevskiy .pre_load = spapr_dtb_pre_load, 1937fea35ca4SAlexey Kardashevskiy .fields = (VMStateField[]) { 1938ce2918cbSDavid Gibson VMSTATE_UINT32(fdt_initial_size, SpaprMachineState), 1939ce2918cbSDavid Gibson VMSTATE_UINT32(fdt_size, SpaprMachineState), 1940ce2918cbSDavid Gibson VMSTATE_VBUFFER_ALLOC_UINT32(fdt_blob, SpaprMachineState, 0, NULL, 1941fea35ca4SAlexey Kardashevskiy fdt_size), 1942fea35ca4SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 1943fea35ca4SAlexey Kardashevskiy }, 1944fea35ca4SAlexey Kardashevskiy }; 1945fea35ca4SAlexey Kardashevskiy 19462500fb42SAravinda Prasad static bool spapr_fwnmi_needed(void *opaque) 19472500fb42SAravinda Prasad { 19482500fb42SAravinda Prasad SpaprMachineState *spapr = (SpaprMachineState *)opaque; 19492500fb42SAravinda Prasad 19508af7e1feSNicholas Piggin return spapr->fwnmi_machine_check_addr != -1; 19512500fb42SAravinda Prasad } 19522500fb42SAravinda Prasad 19532500fb42SAravinda Prasad static int spapr_fwnmi_pre_save(void *opaque) 19542500fb42SAravinda Prasad { 19552500fb42SAravinda Prasad SpaprMachineState *spapr = (SpaprMachineState *)opaque; 19562500fb42SAravinda Prasad 19572500fb42SAravinda Prasad /* 19582500fb42SAravinda Prasad * Check if machine check handling is in progress and print a 19592500fb42SAravinda Prasad * warning message. 19602500fb42SAravinda Prasad */ 19618af7e1feSNicholas Piggin if (spapr->fwnmi_machine_check_interlock != -1) { 19622500fb42SAravinda Prasad warn_report("A machine check is being handled during migration. The" 19632500fb42SAravinda Prasad "handler may run and log hardware error on the destination"); 19642500fb42SAravinda Prasad } 19652500fb42SAravinda Prasad 19662500fb42SAravinda Prasad return 0; 19672500fb42SAravinda Prasad } 19682500fb42SAravinda Prasad 19698af7e1feSNicholas Piggin static const VMStateDescription vmstate_spapr_fwnmi = { 19708af7e1feSNicholas Piggin .name = "spapr_fwnmi", 19712500fb42SAravinda Prasad .version_id = 1, 19722500fb42SAravinda Prasad .minimum_version_id = 1, 19732500fb42SAravinda Prasad .needed = spapr_fwnmi_needed, 19742500fb42SAravinda Prasad .pre_save = spapr_fwnmi_pre_save, 19752500fb42SAravinda Prasad .fields = (VMStateField[]) { 1976edfdbf9cSNicholas Piggin VMSTATE_UINT64(fwnmi_system_reset_addr, SpaprMachineState), 19778af7e1feSNicholas Piggin VMSTATE_UINT64(fwnmi_machine_check_addr, SpaprMachineState), 19788af7e1feSNicholas Piggin VMSTATE_INT32(fwnmi_machine_check_interlock, SpaprMachineState), 19792500fb42SAravinda Prasad VMSTATE_END_OF_LIST() 19802500fb42SAravinda Prasad }, 19812500fb42SAravinda Prasad }; 19822500fb42SAravinda Prasad 19834be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = { 19844be21d56SDavid Gibson .name = "spapr", 1985880ae7deSDavid Gibson .version_id = 3, 19864be21d56SDavid Gibson .minimum_version_id = 1, 19874e5fe368SSuraj Jitindar Singh .pre_load = spapr_pre_load, 1988880ae7deSDavid Gibson .post_load = spapr_post_load, 19894e5fe368SSuraj Jitindar Singh .pre_save = spapr_pre_save, 19904be21d56SDavid Gibson .fields = (VMStateField[]) { 1991880ae7deSDavid Gibson /* used to be @next_irq */ 1992880ae7deSDavid Gibson VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4), 19934be21d56SDavid Gibson 19944be21d56SDavid Gibson /* RTC offset */ 1995ce2918cbSDavid Gibson VMSTATE_UINT64_TEST(rtc_offset, SpaprMachineState, version_before_3), 1996880ae7deSDavid Gibson 1997ce2918cbSDavid Gibson VMSTATE_PPC_TIMEBASE_V(tb, SpaprMachineState, 2), 19984be21d56SDavid Gibson VMSTATE_END_OF_LIST() 19994be21d56SDavid Gibson }, 200062ef3760SMichael Roth .subsections = (const VMStateDescription*[]) { 200162ef3760SMichael Roth &vmstate_spapr_ov5_cas, 20029861bb3eSSuraj Jitindar Singh &vmstate_spapr_patb_entry, 2003fd38804bSDaniel Henrique Barboza &vmstate_spapr_pending_events, 20044e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_htm, 20054e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_vsx, 20064e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_dfp, 20078f38eaf8SSuraj Jitindar Singh &vmstate_spapr_cap_cfpc, 200809114fd8SSuraj Jitindar Singh &vmstate_spapr_cap_sbbc, 20094be8d4e7SSuraj Jitindar Singh &vmstate_spapr_cap_ibs, 201064d4a534SDavid Gibson &vmstate_spapr_cap_hpt_maxpagesize, 201182cffa2eSCédric Le Goater &vmstate_spapr_irq_map, 2012b9a477b7SSuraj Jitindar Singh &vmstate_spapr_cap_nested_kvm_hv, 2013fea35ca4SAlexey Kardashevskiy &vmstate_spapr_dtb, 2014c982f5cfSSuraj Jitindar Singh &vmstate_spapr_cap_large_decr, 20158ff43ee4SSuraj Jitindar Singh &vmstate_spapr_cap_ccf_assist, 20169d953ce4SAravinda Prasad &vmstate_spapr_cap_fwnmi, 20178af7e1feSNicholas Piggin &vmstate_spapr_fwnmi, 201862ef3760SMichael Roth NULL 201962ef3760SMichael Roth } 20204be21d56SDavid Gibson }; 20214be21d56SDavid Gibson 20224be21d56SDavid Gibson static int htab_save_setup(QEMUFile *f, void *opaque) 20234be21d56SDavid Gibson { 2024ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 20254be21d56SDavid Gibson 20264be21d56SDavid Gibson /* "Iteration" header */ 20273a384297SBharata B Rao if (!spapr->htab_shift) { 20283a384297SBharata B Rao qemu_put_be32(f, -1); 20293a384297SBharata B Rao } else { 20304be21d56SDavid Gibson qemu_put_be32(f, spapr->htab_shift); 20313a384297SBharata B Rao } 20324be21d56SDavid Gibson 2033e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 2034e68cb8b4SAlexey Kardashevskiy spapr->htab_save_index = 0; 2035e68cb8b4SAlexey Kardashevskiy spapr->htab_first_pass = true; 2036e68cb8b4SAlexey Kardashevskiy } else { 20373a384297SBharata B Rao if (spapr->htab_shift) { 2038e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 20394be21d56SDavid Gibson } 20403a384297SBharata B Rao } 20414be21d56SDavid Gibson 2042e68cb8b4SAlexey Kardashevskiy 2043e68cb8b4SAlexey Kardashevskiy return 0; 2044e68cb8b4SAlexey Kardashevskiy } 20454be21d56SDavid Gibson 2046ce2918cbSDavid Gibson static void htab_save_chunk(QEMUFile *f, SpaprMachineState *spapr, 2047332f7721SGreg Kurz int chunkstart, int n_valid, int n_invalid) 2048332f7721SGreg Kurz { 2049332f7721SGreg Kurz qemu_put_be32(f, chunkstart); 2050332f7721SGreg Kurz qemu_put_be16(f, n_valid); 2051332f7721SGreg Kurz qemu_put_be16(f, n_invalid); 2052332f7721SGreg Kurz qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 2053332f7721SGreg Kurz HASH_PTE_SIZE_64 * n_valid); 2054332f7721SGreg Kurz } 2055332f7721SGreg Kurz 2056332f7721SGreg Kurz static void htab_save_end_marker(QEMUFile *f) 2057332f7721SGreg Kurz { 2058332f7721SGreg Kurz qemu_put_be32(f, 0); 2059332f7721SGreg Kurz qemu_put_be16(f, 0); 2060332f7721SGreg Kurz qemu_put_be16(f, 0); 2061332f7721SGreg Kurz } 2062332f7721SGreg Kurz 2063ce2918cbSDavid Gibson static void htab_save_first_pass(QEMUFile *f, SpaprMachineState *spapr, 20644be21d56SDavid Gibson int64_t max_ns) 20654be21d56SDavid Gibson { 2066378bc217SDavid Gibson bool has_timeout = max_ns != -1; 20674be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 20684be21d56SDavid Gibson int index = spapr->htab_save_index; 2069bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 20704be21d56SDavid Gibson 20714be21d56SDavid Gibson assert(spapr->htab_first_pass); 20724be21d56SDavid Gibson 20734be21d56SDavid Gibson do { 20744be21d56SDavid Gibson int chunkstart; 20754be21d56SDavid Gibson 20764be21d56SDavid Gibson /* Consume invalid HPTEs */ 20774be21d56SDavid Gibson while ((index < htabslots) 20784be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 20794be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 208024ec2863SMarc-André Lureau index++; 20814be21d56SDavid Gibson } 20824be21d56SDavid Gibson 20834be21d56SDavid Gibson /* Consume valid HPTEs */ 20844be21d56SDavid Gibson chunkstart = index; 2085338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 20864be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 20874be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 208824ec2863SMarc-André Lureau index++; 20894be21d56SDavid Gibson } 20904be21d56SDavid Gibson 20914be21d56SDavid Gibson if (index > chunkstart) { 20924be21d56SDavid Gibson int n_valid = index - chunkstart; 20934be21d56SDavid Gibson 2094332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, 0); 20954be21d56SDavid Gibson 2096378bc217SDavid Gibson if (has_timeout && 2097378bc217SDavid Gibson (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 20984be21d56SDavid Gibson break; 20994be21d56SDavid Gibson } 21004be21d56SDavid Gibson } 21014be21d56SDavid Gibson } while ((index < htabslots) && !qemu_file_rate_limit(f)); 21024be21d56SDavid Gibson 21034be21d56SDavid Gibson if (index >= htabslots) { 21044be21d56SDavid Gibson assert(index == htabslots); 21054be21d56SDavid Gibson index = 0; 21064be21d56SDavid Gibson spapr->htab_first_pass = false; 21074be21d56SDavid Gibson } 21084be21d56SDavid Gibson spapr->htab_save_index = index; 21094be21d56SDavid Gibson } 21104be21d56SDavid Gibson 2111ce2918cbSDavid Gibson static int htab_save_later_pass(QEMUFile *f, SpaprMachineState *spapr, 21124be21d56SDavid Gibson int64_t max_ns) 21134be21d56SDavid Gibson { 21144be21d56SDavid Gibson bool final = max_ns < 0; 21154be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 21164be21d56SDavid Gibson int examined = 0, sent = 0; 21174be21d56SDavid Gibson int index = spapr->htab_save_index; 2118bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 21194be21d56SDavid Gibson 21204be21d56SDavid Gibson assert(!spapr->htab_first_pass); 21214be21d56SDavid Gibson 21224be21d56SDavid Gibson do { 21234be21d56SDavid Gibson int chunkstart, invalidstart; 21244be21d56SDavid Gibson 21254be21d56SDavid Gibson /* Consume non-dirty HPTEs */ 21264be21d56SDavid Gibson while ((index < htabslots) 21274be21d56SDavid Gibson && !HPTE_DIRTY(HPTE(spapr->htab, index))) { 21284be21d56SDavid Gibson index++; 21294be21d56SDavid Gibson examined++; 21304be21d56SDavid Gibson } 21314be21d56SDavid Gibson 21324be21d56SDavid Gibson chunkstart = index; 21334be21d56SDavid Gibson /* Consume valid dirty HPTEs */ 2134338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 21354be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 21364be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 21374be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 21384be21d56SDavid Gibson index++; 21394be21d56SDavid Gibson examined++; 21404be21d56SDavid Gibson } 21414be21d56SDavid Gibson 21424be21d56SDavid Gibson invalidstart = index; 21434be21d56SDavid Gibson /* Consume invalid dirty HPTEs */ 2144338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - invalidstart < USHRT_MAX) 21454be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 21464be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 21474be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 21484be21d56SDavid Gibson index++; 21494be21d56SDavid Gibson examined++; 21504be21d56SDavid Gibson } 21514be21d56SDavid Gibson 21524be21d56SDavid Gibson if (index > chunkstart) { 21534be21d56SDavid Gibson int n_valid = invalidstart - chunkstart; 21544be21d56SDavid Gibson int n_invalid = index - invalidstart; 21554be21d56SDavid Gibson 2156332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, n_invalid); 21574be21d56SDavid Gibson sent += index - chunkstart; 21584be21d56SDavid Gibson 2159bc72ad67SAlex Bligh if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 21604be21d56SDavid Gibson break; 21614be21d56SDavid Gibson } 21624be21d56SDavid Gibson } 21634be21d56SDavid Gibson 21644be21d56SDavid Gibson if (examined >= htabslots) { 21654be21d56SDavid Gibson break; 21664be21d56SDavid Gibson } 21674be21d56SDavid Gibson 21684be21d56SDavid Gibson if (index >= htabslots) { 21694be21d56SDavid Gibson assert(index == htabslots); 21704be21d56SDavid Gibson index = 0; 21714be21d56SDavid Gibson } 21724be21d56SDavid Gibson } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final)); 21734be21d56SDavid Gibson 21744be21d56SDavid Gibson if (index >= htabslots) { 21754be21d56SDavid Gibson assert(index == htabslots); 21764be21d56SDavid Gibson index = 0; 21774be21d56SDavid Gibson } 21784be21d56SDavid Gibson 21794be21d56SDavid Gibson spapr->htab_save_index = index; 21804be21d56SDavid Gibson 2181e68cb8b4SAlexey Kardashevskiy return (examined >= htabslots) && (sent == 0) ? 1 : 0; 21824be21d56SDavid Gibson } 21834be21d56SDavid Gibson 2184e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS 5000000 /* 5 ms */ 2185e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE 2048 2186e68cb8b4SAlexey Kardashevskiy 21874be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque) 21884be21d56SDavid Gibson { 2189ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2190715c5407SDavid Gibson int fd; 2191e68cb8b4SAlexey Kardashevskiy int rc = 0; 21924be21d56SDavid Gibson 21934be21d56SDavid Gibson /* Iteration header */ 21943a384297SBharata B Rao if (!spapr->htab_shift) { 21953a384297SBharata B Rao qemu_put_be32(f, -1); 2196e8cd4247SLaurent Vivier return 1; 21973a384297SBharata B Rao } else { 21984be21d56SDavid Gibson qemu_put_be32(f, 0); 21993a384297SBharata B Rao } 22004be21d56SDavid Gibson 2201e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2202e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2203e68cb8b4SAlexey Kardashevskiy 2204715c5407SDavid Gibson fd = get_htab_fd(spapr); 2205715c5407SDavid Gibson if (fd < 0) { 2206715c5407SDavid Gibson return fd; 220701a57972SSamuel Mendoza-Jonas } 220801a57972SSamuel Mendoza-Jonas 2209715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); 2210e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2211e68cb8b4SAlexey Kardashevskiy return rc; 2212e68cb8b4SAlexey Kardashevskiy } 2213e68cb8b4SAlexey Kardashevskiy } else if (spapr->htab_first_pass) { 22144be21d56SDavid Gibson htab_save_first_pass(f, spapr, MAX_ITERATION_NS); 22154be21d56SDavid Gibson } else { 2216e68cb8b4SAlexey Kardashevskiy rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS); 22174be21d56SDavid Gibson } 22184be21d56SDavid Gibson 2219332f7721SGreg Kurz htab_save_end_marker(f); 22204be21d56SDavid Gibson 2221e68cb8b4SAlexey Kardashevskiy return rc; 22224be21d56SDavid Gibson } 22234be21d56SDavid Gibson 22244be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque) 22254be21d56SDavid Gibson { 2226ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2227715c5407SDavid Gibson int fd; 22284be21d56SDavid Gibson 22294be21d56SDavid Gibson /* Iteration header */ 22303a384297SBharata B Rao if (!spapr->htab_shift) { 22313a384297SBharata B Rao qemu_put_be32(f, -1); 22323a384297SBharata B Rao return 0; 22333a384297SBharata B Rao } else { 22344be21d56SDavid Gibson qemu_put_be32(f, 0); 22353a384297SBharata B Rao } 22364be21d56SDavid Gibson 2237e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2238e68cb8b4SAlexey Kardashevskiy int rc; 2239e68cb8b4SAlexey Kardashevskiy 2240e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2241e68cb8b4SAlexey Kardashevskiy 2242715c5407SDavid Gibson fd = get_htab_fd(spapr); 2243715c5407SDavid Gibson if (fd < 0) { 2244715c5407SDavid Gibson return fd; 224501a57972SSamuel Mendoza-Jonas } 224601a57972SSamuel Mendoza-Jonas 2247715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1); 2248e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2249e68cb8b4SAlexey Kardashevskiy return rc; 2250e68cb8b4SAlexey Kardashevskiy } 2251e68cb8b4SAlexey Kardashevskiy } else { 2252378bc217SDavid Gibson if (spapr->htab_first_pass) { 2253378bc217SDavid Gibson htab_save_first_pass(f, spapr, -1); 2254378bc217SDavid Gibson } 22554be21d56SDavid Gibson htab_save_later_pass(f, spapr, -1); 2256e68cb8b4SAlexey Kardashevskiy } 22574be21d56SDavid Gibson 22584be21d56SDavid Gibson /* End marker */ 2259332f7721SGreg Kurz htab_save_end_marker(f); 22604be21d56SDavid Gibson 22614be21d56SDavid Gibson return 0; 22624be21d56SDavid Gibson } 22634be21d56SDavid Gibson 22644be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id) 22654be21d56SDavid Gibson { 2266ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 22674be21d56SDavid Gibson uint32_t section_hdr; 2268e68cb8b4SAlexey Kardashevskiy int fd = -1; 226914b0d748SGreg Kurz Error *local_err = NULL; 22704be21d56SDavid Gibson 22714be21d56SDavid Gibson if (version_id < 1 || version_id > 1) { 227298a5d100SDavid Gibson error_report("htab_load() bad version"); 22734be21d56SDavid Gibson return -EINVAL; 22744be21d56SDavid Gibson } 22754be21d56SDavid Gibson 22764be21d56SDavid Gibson section_hdr = qemu_get_be32(f); 22774be21d56SDavid Gibson 22783a384297SBharata B Rao if (section_hdr == -1) { 22793a384297SBharata B Rao spapr_free_hpt(spapr); 22803a384297SBharata B Rao return 0; 22813a384297SBharata B Rao } 22823a384297SBharata B Rao 22834be21d56SDavid Gibson if (section_hdr) { 2284c5f54f3eSDavid Gibson /* First section gives the htab size */ 2285c5f54f3eSDavid Gibson spapr_reallocate_hpt(spapr, section_hdr, &local_err); 2286c5f54f3eSDavid Gibson if (local_err) { 2287c5f54f3eSDavid Gibson error_report_err(local_err); 22884be21d56SDavid Gibson return -EINVAL; 22894be21d56SDavid Gibson } 22904be21d56SDavid Gibson return 0; 22914be21d56SDavid Gibson } 22924be21d56SDavid Gibson 2293e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2294e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2295e68cb8b4SAlexey Kardashevskiy 229614b0d748SGreg Kurz fd = kvmppc_get_htab_fd(true, 0, &local_err); 2297e68cb8b4SAlexey Kardashevskiy if (fd < 0) { 229814b0d748SGreg Kurz error_report_err(local_err); 229982be8e73SGreg Kurz return fd; 2300e68cb8b4SAlexey Kardashevskiy } 2301e68cb8b4SAlexey Kardashevskiy } 2302e68cb8b4SAlexey Kardashevskiy 23034be21d56SDavid Gibson while (true) { 23044be21d56SDavid Gibson uint32_t index; 23054be21d56SDavid Gibson uint16_t n_valid, n_invalid; 23064be21d56SDavid Gibson 23074be21d56SDavid Gibson index = qemu_get_be32(f); 23084be21d56SDavid Gibson n_valid = qemu_get_be16(f); 23094be21d56SDavid Gibson n_invalid = qemu_get_be16(f); 23104be21d56SDavid Gibson 23114be21d56SDavid Gibson if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) { 23124be21d56SDavid Gibson /* End of Stream */ 23134be21d56SDavid Gibson break; 23144be21d56SDavid Gibson } 23154be21d56SDavid Gibson 2316e68cb8b4SAlexey Kardashevskiy if ((index + n_valid + n_invalid) > 23174be21d56SDavid Gibson (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) { 23184be21d56SDavid Gibson /* Bad index in stream */ 231998a5d100SDavid Gibson error_report( 232098a5d100SDavid Gibson "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)", 232198a5d100SDavid Gibson index, n_valid, n_invalid, spapr->htab_shift); 23224be21d56SDavid Gibson return -EINVAL; 23234be21d56SDavid Gibson } 23244be21d56SDavid Gibson 2325e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 23264be21d56SDavid Gibson if (n_valid) { 23274be21d56SDavid Gibson qemu_get_buffer(f, HPTE(spapr->htab, index), 23284be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 23294be21d56SDavid Gibson } 23304be21d56SDavid Gibson if (n_invalid) { 23314be21d56SDavid Gibson memset(HPTE(spapr->htab, index + n_valid), 0, 23324be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_invalid); 23334be21d56SDavid Gibson } 2334e68cb8b4SAlexey Kardashevskiy } else { 2335e68cb8b4SAlexey Kardashevskiy int rc; 2336e68cb8b4SAlexey Kardashevskiy 2337e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2338e68cb8b4SAlexey Kardashevskiy 2339e68cb8b4SAlexey Kardashevskiy rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid); 2340e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2341e68cb8b4SAlexey Kardashevskiy return rc; 2342e68cb8b4SAlexey Kardashevskiy } 2343e68cb8b4SAlexey Kardashevskiy } 2344e68cb8b4SAlexey Kardashevskiy } 2345e68cb8b4SAlexey Kardashevskiy 2346e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2347e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2348e68cb8b4SAlexey Kardashevskiy close(fd); 23494be21d56SDavid Gibson } 23504be21d56SDavid Gibson 23514be21d56SDavid Gibson return 0; 23524be21d56SDavid Gibson } 23534be21d56SDavid Gibson 235470f794fcSJuan Quintela static void htab_save_cleanup(void *opaque) 2355c573fc03SThomas Huth { 2356ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2357c573fc03SThomas Huth 2358c573fc03SThomas Huth close_htab_fd(spapr); 2359c573fc03SThomas Huth } 2360c573fc03SThomas Huth 23614be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = { 23629907e842SJuan Quintela .save_setup = htab_save_setup, 23634be21d56SDavid Gibson .save_live_iterate = htab_save_iterate, 2364a3e06c3dSDr. David Alan Gilbert .save_live_complete_precopy = htab_save_complete, 236570f794fcSJuan Quintela .save_cleanup = htab_save_cleanup, 23664be21d56SDavid Gibson .load_state = htab_load, 23674be21d56SDavid Gibson }; 23684be21d56SDavid Gibson 23695b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device, 23705b2128d2SAlexander Graf Error **errp) 23715b2128d2SAlexander Graf { 2372c86c1affSDaniel Henrique Barboza MachineState *machine = MACHINE(opaque); 23735b2128d2SAlexander Graf machine->boot_order = g_strdup(boot_device); 23745b2128d2SAlexander Graf } 23755b2128d2SAlexander Graf 2376ce2918cbSDavid Gibson static void spapr_create_lmb_dr_connectors(SpaprMachineState *spapr) 2377224245bfSDavid Gibson { 2378224245bfSDavid Gibson MachineState *machine = MACHINE(spapr); 2379224245bfSDavid Gibson uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 2380e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 2381224245bfSDavid Gibson int i; 2382224245bfSDavid Gibson 2383224245bfSDavid Gibson for (i = 0; i < nr_lmbs; i++) { 2384224245bfSDavid Gibson uint64_t addr; 2385224245bfSDavid Gibson 2386b0c14ec4SDavid Hildenbrand addr = i * lmb_size + machine->device_memory->base; 23876caf3ac6SDavid Gibson spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_LMB, 2388224245bfSDavid Gibson addr / lmb_size); 2389224245bfSDavid Gibson } 2390224245bfSDavid Gibson } 2391224245bfSDavid Gibson 2392224245bfSDavid Gibson /* 2393224245bfSDavid Gibson * If RAM size, maxmem size and individual node mem sizes aren't aligned 2394224245bfSDavid Gibson * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest 2395224245bfSDavid Gibson * since we can't support such unaligned sizes with DRCONF_MEMORY. 2396224245bfSDavid Gibson */ 23977c150d6fSDavid Gibson static void spapr_validate_node_memory(MachineState *machine, Error **errp) 2398224245bfSDavid Gibson { 2399224245bfSDavid Gibson int i; 2400224245bfSDavid Gibson 24017c150d6fSDavid Gibson if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) { 24027c150d6fSDavid Gibson error_setg(errp, "Memory size 0x" RAM_ADDR_FMT 2403ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 24047c150d6fSDavid Gibson machine->ram_size, 2405d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 24067c150d6fSDavid Gibson return; 24077c150d6fSDavid Gibson } 24087c150d6fSDavid Gibson 24097c150d6fSDavid Gibson if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) { 24107c150d6fSDavid Gibson error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT 2411ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 24127c150d6fSDavid Gibson machine->ram_size, 2413d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 24147c150d6fSDavid Gibson return; 2415224245bfSDavid Gibson } 2416224245bfSDavid Gibson 2417aa570207STao Xu for (i = 0; i < machine->numa_state->num_nodes; i++) { 24187e721e7bSTao Xu if (machine->numa_state->nodes[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) { 24197c150d6fSDavid Gibson error_setg(errp, 24207c150d6fSDavid Gibson "Node %d memory size 0x%" PRIx64 2421ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 24227e721e7bSTao Xu i, machine->numa_state->nodes[i].node_mem, 2423d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 24247c150d6fSDavid Gibson return; 2425224245bfSDavid Gibson } 2426224245bfSDavid Gibson } 2427224245bfSDavid Gibson } 2428224245bfSDavid Gibson 2429535455fdSIgor Mammedov /* find cpu slot in machine->possible_cpus by core_id */ 2430535455fdSIgor Mammedov static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx) 2431535455fdSIgor Mammedov { 2432fe6b6346SLike Xu int index = id / ms->smp.threads; 2433535455fdSIgor Mammedov 2434535455fdSIgor Mammedov if (index >= ms->possible_cpus->len) { 2435535455fdSIgor Mammedov return NULL; 2436535455fdSIgor Mammedov } 2437535455fdSIgor Mammedov if (idx) { 2438535455fdSIgor Mammedov *idx = index; 2439535455fdSIgor Mammedov } 2440535455fdSIgor Mammedov return &ms->possible_cpus->cpus[index]; 2441535455fdSIgor Mammedov } 2442535455fdSIgor Mammedov 2443ce2918cbSDavid Gibson static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp) 2444fa98fbfcSSam Bobroff { 2445fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 244629cb4187SGreg Kurz SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 2447fa98fbfcSSam Bobroff Error *local_err = NULL; 2448fa98fbfcSSam Bobroff bool vsmt_user = !!spapr->vsmt; 2449fa98fbfcSSam Bobroff int kvm_smt = kvmppc_smt_threads(); 2450fa98fbfcSSam Bobroff int ret; 2451fe6b6346SLike Xu unsigned int smp_threads = ms->smp.threads; 2452fa98fbfcSSam Bobroff 2453fa98fbfcSSam Bobroff if (!kvm_enabled() && (smp_threads > 1)) { 2454dcfe4805SMarkus Armbruster error_setg(errp, "TCG cannot support more than 1 thread/core " 2455fa98fbfcSSam Bobroff "on a pseries machine"); 2456dcfe4805SMarkus Armbruster return; 2457fa98fbfcSSam Bobroff } 2458fa98fbfcSSam Bobroff if (!is_power_of_2(smp_threads)) { 2459dcfe4805SMarkus Armbruster error_setg(errp, "Cannot support %d threads/core on a pseries " 2460fa98fbfcSSam Bobroff "machine because it must be a power of 2", smp_threads); 2461dcfe4805SMarkus Armbruster return; 2462fa98fbfcSSam Bobroff } 2463fa98fbfcSSam Bobroff 2464fa98fbfcSSam Bobroff /* Detemine the VSMT mode to use: */ 2465fa98fbfcSSam Bobroff if (vsmt_user) { 2466fa98fbfcSSam Bobroff if (spapr->vsmt < smp_threads) { 2467dcfe4805SMarkus Armbruster error_setg(errp, "Cannot support VSMT mode %d" 2468fa98fbfcSSam Bobroff " because it must be >= threads/core (%d)", 2469fa98fbfcSSam Bobroff spapr->vsmt, smp_threads); 2470dcfe4805SMarkus Armbruster return; 2471fa98fbfcSSam Bobroff } 2472fa98fbfcSSam Bobroff /* In this case, spapr->vsmt has been set by the command line */ 247329cb4187SGreg Kurz } else if (!smc->smp_threads_vsmt) { 24748904e5a7SDavid Gibson /* 24758904e5a7SDavid Gibson * Default VSMT value is tricky, because we need it to be as 24768904e5a7SDavid Gibson * consistent as possible (for migration), but this requires 24778904e5a7SDavid Gibson * changing it for at least some existing cases. We pick 8 as 24788904e5a7SDavid Gibson * the value that we'd get with KVM on POWER8, the 24798904e5a7SDavid Gibson * overwhelmingly common case in production systems. 24808904e5a7SDavid Gibson */ 24814ad64cbdSLaurent Vivier spapr->vsmt = MAX(8, smp_threads); 248229cb4187SGreg Kurz } else { 248329cb4187SGreg Kurz spapr->vsmt = smp_threads; 2484fa98fbfcSSam Bobroff } 2485fa98fbfcSSam Bobroff 2486fa98fbfcSSam Bobroff /* KVM: If necessary, set the SMT mode: */ 2487fa98fbfcSSam Bobroff if (kvm_enabled() && (spapr->vsmt != kvm_smt)) { 2488fa98fbfcSSam Bobroff ret = kvmppc_set_smt_threads(spapr->vsmt); 2489fa98fbfcSSam Bobroff if (ret) { 24901f20f2e0SDavid Gibson /* Looks like KVM isn't able to change VSMT mode */ 2491fa98fbfcSSam Bobroff error_setg(&local_err, 2492fa98fbfcSSam Bobroff "Failed to set KVM's VSMT mode to %d (errno %d)", 2493fa98fbfcSSam Bobroff spapr->vsmt, ret); 24941f20f2e0SDavid Gibson /* We can live with that if the default one is big enough 24951f20f2e0SDavid Gibson * for the number of threads, and a submultiple of the one 24961f20f2e0SDavid Gibson * we want. In this case we'll waste some vcpu ids, but 24971f20f2e0SDavid Gibson * behaviour will be correct */ 24981f20f2e0SDavid Gibson if ((kvm_smt >= smp_threads) && ((spapr->vsmt % kvm_smt) == 0)) { 24991f20f2e0SDavid Gibson warn_report_err(local_err); 25001f20f2e0SDavid Gibson } else { 2501fa98fbfcSSam Bobroff if (!vsmt_user) { 25021f20f2e0SDavid Gibson error_append_hint(&local_err, 25031f20f2e0SDavid Gibson "On PPC, a VM with %d threads/core" 25041f20f2e0SDavid Gibson " on a host with %d threads/core" 25051f20f2e0SDavid Gibson " requires the use of VSMT mode %d.\n", 2506fa98fbfcSSam Bobroff smp_threads, kvm_smt, spapr->vsmt); 2507fa98fbfcSSam Bobroff } 2508cdcca22aSVladimir Sementsov-Ogievskiy kvmppc_error_append_smt_possible_hint(&local_err); 2509dcfe4805SMarkus Armbruster error_propagate(errp, local_err); 2510fa98fbfcSSam Bobroff } 2511fa98fbfcSSam Bobroff } 25121f20f2e0SDavid Gibson } 2513fa98fbfcSSam Bobroff /* else TCG: nothing to do currently */ 2514fa98fbfcSSam Bobroff } 2515fa98fbfcSSam Bobroff 2516ce2918cbSDavid Gibson static void spapr_init_cpus(SpaprMachineState *spapr) 25171a5008fcSGreg Kurz { 25181a5008fcSGreg Kurz MachineState *machine = MACHINE(spapr); 25191a5008fcSGreg Kurz MachineClass *mc = MACHINE_GET_CLASS(machine); 2520ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 25211a5008fcSGreg Kurz const char *type = spapr_get_cpu_core_type(machine->cpu_type); 25221a5008fcSGreg Kurz const CPUArchIdList *possible_cpus; 2523fe6b6346SLike Xu unsigned int smp_cpus = machine->smp.cpus; 2524fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 2525fe6b6346SLike Xu unsigned int max_cpus = machine->smp.max_cpus; 25261a5008fcSGreg Kurz int boot_cores_nr = smp_cpus / smp_threads; 25271a5008fcSGreg Kurz int i; 25281a5008fcSGreg Kurz 25291a5008fcSGreg Kurz possible_cpus = mc->possible_cpu_arch_ids(machine); 25301a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 25311a5008fcSGreg Kurz if (smp_cpus % smp_threads) { 25321a5008fcSGreg Kurz error_report("smp_cpus (%u) must be multiple of threads (%u)", 25331a5008fcSGreg Kurz smp_cpus, smp_threads); 25341a5008fcSGreg Kurz exit(1); 25351a5008fcSGreg Kurz } 25361a5008fcSGreg Kurz if (max_cpus % smp_threads) { 25371a5008fcSGreg Kurz error_report("max_cpus (%u) must be multiple of threads (%u)", 25381a5008fcSGreg Kurz max_cpus, smp_threads); 25391a5008fcSGreg Kurz exit(1); 25401a5008fcSGreg Kurz } 25411a5008fcSGreg Kurz } else { 25421a5008fcSGreg Kurz if (max_cpus != smp_cpus) { 25431a5008fcSGreg Kurz error_report("This machine version does not support CPU hotplug"); 25441a5008fcSGreg Kurz exit(1); 25451a5008fcSGreg Kurz } 25461a5008fcSGreg Kurz boot_cores_nr = possible_cpus->len; 25471a5008fcSGreg Kurz } 25481a5008fcSGreg Kurz 25491a5008fcSGreg Kurz if (smc->pre_2_10_has_unused_icps) { 25501a5008fcSGreg Kurz int i; 25511a5008fcSGreg Kurz 25521a518e76SCédric Le Goater for (i = 0; i < spapr_max_server_number(spapr); i++) { 25531a5008fcSGreg Kurz /* Dummy entries get deregistered when real ICPState objects 25541a5008fcSGreg Kurz * are registered during CPU core hotplug. 25551a5008fcSGreg Kurz */ 25561a5008fcSGreg Kurz pre_2_10_vmstate_register_dummy_icp(i); 25571a5008fcSGreg Kurz } 25581a5008fcSGreg Kurz } 25591a5008fcSGreg Kurz 25601a5008fcSGreg Kurz for (i = 0; i < possible_cpus->len; i++) { 25611a5008fcSGreg Kurz int core_id = i * smp_threads; 25621a5008fcSGreg Kurz 25631a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 25641a5008fcSGreg Kurz spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU, 25651a5008fcSGreg Kurz spapr_vcpu_id(spapr, core_id)); 25661a5008fcSGreg Kurz } 25671a5008fcSGreg Kurz 25681a5008fcSGreg Kurz if (i < boot_cores_nr) { 25691a5008fcSGreg Kurz Object *core = object_new(type); 25701a5008fcSGreg Kurz int nr_threads = smp_threads; 25711a5008fcSGreg Kurz 25721a5008fcSGreg Kurz /* Handle the partially filled core for older machine types */ 25731a5008fcSGreg Kurz if ((i + 1) * smp_threads >= smp_cpus) { 25741a5008fcSGreg Kurz nr_threads = smp_cpus - i * smp_threads; 25751a5008fcSGreg Kurz } 25761a5008fcSGreg Kurz 25775325cc34SMarkus Armbruster object_property_set_int(core, "nr-threads", nr_threads, 25781a5008fcSGreg Kurz &error_fatal); 25795325cc34SMarkus Armbruster object_property_set_int(core, CPU_CORE_PROP_CORE_ID, core_id, 25801a5008fcSGreg Kurz &error_fatal); 2581ce189ab2SMarkus Armbruster qdev_realize(DEVICE(core), NULL, &error_fatal); 2582ecda255eSSam Bobroff 2583ecda255eSSam Bobroff object_unref(core); 25841a5008fcSGreg Kurz } 25851a5008fcSGreg Kurz } 25861a5008fcSGreg Kurz } 25871a5008fcSGreg Kurz 2588999c9cafSGreg Kurz static PCIHostState *spapr_create_default_phb(void) 2589999c9cafSGreg Kurz { 2590999c9cafSGreg Kurz DeviceState *dev; 2591999c9cafSGreg Kurz 25923e80f690SMarkus Armbruster dev = qdev_new(TYPE_SPAPR_PCI_HOST_BRIDGE); 2593999c9cafSGreg Kurz qdev_prop_set_uint32(dev, "index", 0); 25943c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); 2595999c9cafSGreg Kurz 2596999c9cafSGreg Kurz return PCI_HOST_BRIDGE(dev); 2597999c9cafSGreg Kurz } 2598999c9cafSGreg Kurz 2599425f0b7aSDavid Gibson static hwaddr spapr_rma_size(SpaprMachineState *spapr, Error **errp) 2600425f0b7aSDavid Gibson { 2601425f0b7aSDavid Gibson MachineState *machine = MACHINE(spapr); 2602425f0b7aSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 2603425f0b7aSDavid Gibson hwaddr rma_size = machine->ram_size; 2604425f0b7aSDavid Gibson hwaddr node0_size = spapr_node0_size(machine); 2605425f0b7aSDavid Gibson 2606425f0b7aSDavid Gibson /* RMA has to fit in the first NUMA node */ 2607425f0b7aSDavid Gibson rma_size = MIN(rma_size, node0_size); 2608425f0b7aSDavid Gibson 2609425f0b7aSDavid Gibson /* 2610425f0b7aSDavid Gibson * VRMA access is via a special 1TiB SLB mapping, so the RMA can 2611425f0b7aSDavid Gibson * never exceed that 2612425f0b7aSDavid Gibson */ 2613425f0b7aSDavid Gibson rma_size = MIN(rma_size, 1 * TiB); 2614425f0b7aSDavid Gibson 2615425f0b7aSDavid Gibson /* 2616425f0b7aSDavid Gibson * Clamp the RMA size based on machine type. This is for 2617425f0b7aSDavid Gibson * migration compatibility with older qemu versions, which limited 2618425f0b7aSDavid Gibson * the RMA size for complicated and mostly bad reasons. 2619425f0b7aSDavid Gibson */ 2620425f0b7aSDavid Gibson if (smc->rma_limit) { 2621425f0b7aSDavid Gibson rma_size = MIN(rma_size, smc->rma_limit); 2622425f0b7aSDavid Gibson } 2623425f0b7aSDavid Gibson 2624425f0b7aSDavid Gibson if (rma_size < MIN_RMA_SLOF) { 2625425f0b7aSDavid Gibson error_setg(errp, 2626425f0b7aSDavid Gibson "pSeries SLOF firmware requires >= %" HWADDR_PRIx 2627425f0b7aSDavid Gibson "ldMiB guest RMA (Real Mode Area memory)", 2628425f0b7aSDavid Gibson MIN_RMA_SLOF / MiB); 2629425f0b7aSDavid Gibson return 0; 2630425f0b7aSDavid Gibson } 2631425f0b7aSDavid Gibson 2632425f0b7aSDavid Gibson return rma_size; 2633425f0b7aSDavid Gibson } 2634425f0b7aSDavid Gibson 263553018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */ 2636bcb5ce08SDavid Gibson static void spapr_machine_init(MachineState *machine) 263753018216SPaolo Bonzini { 2638ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(machine); 2639ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 2640ee3a71e3SShivaprasad G Bhat MachineClass *mc = MACHINE_GET_CLASS(machine); 26413ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 26423ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 264353018216SPaolo Bonzini PCIHostState *phb; 264453018216SPaolo Bonzini int i; 264553018216SPaolo Bonzini MemoryRegion *sysmem = get_system_memory(); 2646b7d1f77aSBenjamin Herrenschmidt long load_limit, fw_size; 264753018216SPaolo Bonzini char *filename; 264830f4b05bSDavid Gibson Error *resize_hpt_err = NULL; 264953018216SPaolo Bonzini 2650226419d6SMichael S. Tsirkin msi_nonbroken = true; 265153018216SPaolo Bonzini 265253018216SPaolo Bonzini QLIST_INIT(&spapr->phbs); 26530cffce56SDavid Gibson QTAILQ_INIT(&spapr->pending_dimm_unplugs); 265453018216SPaolo Bonzini 26559f6edd06SDavid Gibson /* Determine capabilities to run with */ 26569f6edd06SDavid Gibson spapr_caps_init(spapr); 26579f6edd06SDavid Gibson 265830f4b05bSDavid Gibson kvmppc_check_papr_resize_hpt(&resize_hpt_err); 265930f4b05bSDavid Gibson if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) { 266030f4b05bSDavid Gibson /* 266130f4b05bSDavid Gibson * If the user explicitly requested a mode we should either 266230f4b05bSDavid Gibson * supply it, or fail completely (which we do below). But if 266330f4b05bSDavid Gibson * it's not set explicitly, we reset our mode to something 266430f4b05bSDavid Gibson * that works 266530f4b05bSDavid Gibson */ 266630f4b05bSDavid Gibson if (resize_hpt_err) { 266730f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 266830f4b05bSDavid Gibson error_free(resize_hpt_err); 266930f4b05bSDavid Gibson resize_hpt_err = NULL; 267030f4b05bSDavid Gibson } else { 267130f4b05bSDavid Gibson spapr->resize_hpt = smc->resize_hpt_default; 267230f4b05bSDavid Gibson } 267330f4b05bSDavid Gibson } 267430f4b05bSDavid Gibson 267530f4b05bSDavid Gibson assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT); 267630f4b05bSDavid Gibson 267730f4b05bSDavid Gibson if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && resize_hpt_err) { 267830f4b05bSDavid Gibson /* 267930f4b05bSDavid Gibson * User requested HPT resize, but this host can't supply it. Bail out 268030f4b05bSDavid Gibson */ 268130f4b05bSDavid Gibson error_report_err(resize_hpt_err); 268230f4b05bSDavid Gibson exit(1); 268330f4b05bSDavid Gibson } 268414963c34SMarkus Armbruster error_free(resize_hpt_err); 268530f4b05bSDavid Gibson 2686425f0b7aSDavid Gibson spapr->rma_size = spapr_rma_size(spapr, &error_fatal); 2687c4177479SAlexey Kardashevskiy 2688b7d1f77aSBenjamin Herrenschmidt /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */ 2689b7d1f77aSBenjamin Herrenschmidt load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; 269053018216SPaolo Bonzini 2691482969d6SCédric Le Goater /* 2692482969d6SCédric Le Goater * VSMT must be set in order to be able to compute VCPU ids, ie to 26931a518e76SCédric Le Goater * call spapr_max_server_number() or spapr_vcpu_id(). 2694482969d6SCédric Le Goater */ 2695482969d6SCédric Le Goater spapr_set_vsmt_mode(spapr, &error_fatal); 2696482969d6SCédric Le Goater 26977b565160SDavid Gibson /* Set up Interrupt Controller before we create the VCPUs */ 2698fab397d8SCédric Le Goater spapr_irq_init(spapr, &error_fatal); 26997b565160SDavid Gibson 2700dc1b5eeeSGreg Kurz /* Set up containers for ibm,client-architecture-support negotiated options 2701dc1b5eeeSGreg Kurz */ 2702facdb8b6SMichael Roth spapr->ov5 = spapr_ovec_new(); 2703facdb8b6SMichael Roth spapr->ov5_cas = spapr_ovec_new(); 2704facdb8b6SMichael Roth 2705224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2706facdb8b6SMichael Roth spapr_ovec_set(spapr->ov5, OV5_DRCONF_MEMORY); 27077c150d6fSDavid Gibson spapr_validate_node_memory(machine, &error_fatal); 2708224245bfSDavid Gibson } 2709224245bfSDavid Gibson 2710417ece33SMichael Roth spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY); 2711417ece33SMichael Roth 2712ffbb1705SMichael Roth /* advertise support for dedicated HP event source to guests */ 2713ffbb1705SMichael Roth if (spapr->use_hotplug_event_source) { 2714ffbb1705SMichael Roth spapr_ovec_set(spapr->ov5, OV5_HP_EVT); 2715ffbb1705SMichael Roth } 2716ffbb1705SMichael Roth 27172772cf6bSDavid Gibson /* advertise support for HPT resizing */ 27182772cf6bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { 27192772cf6bSDavid Gibson spapr_ovec_set(spapr->ov5, OV5_HPT_RESIZE); 27202772cf6bSDavid Gibson } 27212772cf6bSDavid Gibson 2722a324d6f1SBharata B Rao /* advertise support for ibm,dyamic-memory-v2 */ 2723a324d6f1SBharata B Rao spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2); 2724a324d6f1SBharata B Rao 2725db592b5bSCédric Le Goater /* advertise XIVE on POWER9 machines */ 2726ca62823bSDavid Gibson if (spapr->irq->xive) { 2727db592b5bSCédric Le Goater spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT); 2728db592b5bSCédric Le Goater } 2729db592b5bSCédric Le Goater 273053018216SPaolo Bonzini /* init CPUs */ 27310c86d0fdSDavid Gibson spapr_init_cpus(spapr); 273253018216SPaolo Bonzini 273358c46efaSLaurent Vivier /* 273458c46efaSLaurent Vivier * check we don't have a memory-less/cpu-less NUMA node 273558c46efaSLaurent Vivier * Firmware relies on the existing memory/cpu topology to provide the 273658c46efaSLaurent Vivier * NUMA topology to the kernel. 273758c46efaSLaurent Vivier * And the linux kernel needs to know the NUMA topology at start 273858c46efaSLaurent Vivier * to be able to hotplug CPUs later. 273958c46efaSLaurent Vivier */ 274058c46efaSLaurent Vivier if (machine->numa_state->num_nodes) { 274158c46efaSLaurent Vivier for (i = 0; i < machine->numa_state->num_nodes; ++i) { 274258c46efaSLaurent Vivier /* check for memory-less node */ 274358c46efaSLaurent Vivier if (machine->numa_state->nodes[i].node_mem == 0) { 274458c46efaSLaurent Vivier CPUState *cs; 274558c46efaSLaurent Vivier int found = 0; 274658c46efaSLaurent Vivier /* check for cpu-less node */ 274758c46efaSLaurent Vivier CPU_FOREACH(cs) { 274858c46efaSLaurent Vivier PowerPCCPU *cpu = POWERPC_CPU(cs); 274958c46efaSLaurent Vivier if (cpu->node_id == i) { 275058c46efaSLaurent Vivier found = 1; 275158c46efaSLaurent Vivier break; 275258c46efaSLaurent Vivier } 275358c46efaSLaurent Vivier } 275458c46efaSLaurent Vivier /* memory-less and cpu-less node */ 275558c46efaSLaurent Vivier if (!found) { 275658c46efaSLaurent Vivier error_report( 275758c46efaSLaurent Vivier "Memory-less/cpu-less nodes are not supported (node %d)", 275858c46efaSLaurent Vivier i); 275958c46efaSLaurent Vivier exit(1); 276058c46efaSLaurent Vivier } 276158c46efaSLaurent Vivier } 276258c46efaSLaurent Vivier } 276358c46efaSLaurent Vivier 276458c46efaSLaurent Vivier } 276558c46efaSLaurent Vivier 2766db5127b2SDavid Gibson /* 2767db5127b2SDavid Gibson * NVLink2-connected GPU RAM needs to be placed on a separate NUMA node. 2768db5127b2SDavid Gibson * We assign a new numa ID per GPU in spapr_pci_collect_nvgpu() which is 2769db5127b2SDavid Gibson * called from vPHB reset handler so we initialize the counter here. 2770db5127b2SDavid Gibson * If no NUMA is configured from the QEMU side, we start from 1 as GPU RAM 2771db5127b2SDavid Gibson * must be equally distant from any other node. 2772db5127b2SDavid Gibson * The final value of spapr->gpu_numa_id is going to be written to 2773db5127b2SDavid Gibson * max-associativity-domains in spapr_build_fdt(). 2774db5127b2SDavid Gibson */ 2775db5127b2SDavid Gibson spapr->gpu_numa_id = MAX(1, machine->numa_state->num_nodes); 2776db5127b2SDavid Gibson 2777f1aa45ffSDaniel Henrique Barboza /* Init numa_assoc_array */ 2778f1aa45ffSDaniel Henrique Barboza spapr_numa_associativity_init(spapr, machine); 2779f1aa45ffSDaniel Henrique Barboza 27800550b120SGreg Kurz if ((!kvm_enabled() || kvmppc_has_cap_mmu_radix()) && 2781ad99d04cSDavid Gibson ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, 27820550b120SGreg Kurz spapr->max_compat_pvr)) { 2783b4b83312SGreg Kurz spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_300); 27840550b120SGreg Kurz /* KVM and TCG always allow GTSE with radix... */ 27850550b120SGreg Kurz spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE); 27860550b120SGreg Kurz } 27870550b120SGreg Kurz /* ... but not with hash (currently). */ 27880550b120SGreg Kurz 2789026bfd89SDavid Gibson if (kvm_enabled()) { 2790026bfd89SDavid Gibson /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ 2791026bfd89SDavid Gibson kvmppc_enable_logical_ci_hcalls(); 2792ef9971ddSAlexey Kardashevskiy kvmppc_enable_set_mode_hcall(); 27935145ad4fSNathan Whitehorn 27945145ad4fSNathan Whitehorn /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */ 27955145ad4fSNathan Whitehorn kvmppc_enable_clear_ref_mod_hcalls(); 279668f9f708SSuraj Jitindar Singh 279768f9f708SSuraj Jitindar Singh /* Enable H_PAGE_INIT */ 279868f9f708SSuraj Jitindar Singh kvmppc_enable_h_page_init(); 2799026bfd89SDavid Gibson } 2800026bfd89SDavid Gibson 2801ab74e543SIgor Mammedov /* map RAM */ 2802ab74e543SIgor Mammedov memory_region_add_subregion(sysmem, 0, machine->ram); 280353018216SPaolo Bonzini 2804b0c14ec4SDavid Hildenbrand /* always allocate the device memory information */ 2805b0c14ec4SDavid Hildenbrand machine->device_memory = g_malloc0(sizeof(*machine->device_memory)); 2806b0c14ec4SDavid Hildenbrand 28074a1c9cf0SBharata B Rao /* initialize hotplug memory address space */ 28084a1c9cf0SBharata B Rao if (machine->ram_size < machine->maxram_size) { 28090c9269a5SDavid Hildenbrand ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size; 281071c9a3ddSBharata B Rao /* 281171c9a3ddSBharata B Rao * Limit the number of hotpluggable memory slots to half the number 281271c9a3ddSBharata B Rao * slots that KVM supports, leaving the other half for PCI and other 281371c9a3ddSBharata B Rao * devices. However ensure that number of slots doesn't drop below 32. 281471c9a3ddSBharata B Rao */ 281571c9a3ddSBharata B Rao int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 : 281671c9a3ddSBharata B Rao SPAPR_MAX_RAM_SLOTS; 28174a1c9cf0SBharata B Rao 281871c9a3ddSBharata B Rao if (max_memslots < SPAPR_MAX_RAM_SLOTS) { 281971c9a3ddSBharata B Rao max_memslots = SPAPR_MAX_RAM_SLOTS; 282071c9a3ddSBharata B Rao } 282171c9a3ddSBharata B Rao if (machine->ram_slots > max_memslots) { 2822d54e4d76SDavid Gibson error_report("Specified number of memory slots %" 2823d54e4d76SDavid Gibson PRIu64" exceeds max supported %d", 282471c9a3ddSBharata B Rao machine->ram_slots, max_memslots); 2825d54e4d76SDavid Gibson exit(1); 28264a1c9cf0SBharata B Rao } 28274a1c9cf0SBharata B Rao 2828b0c14ec4SDavid Hildenbrand machine->device_memory->base = ROUND_UP(machine->ram_size, 28290c9269a5SDavid Hildenbrand SPAPR_DEVICE_MEM_ALIGN); 2830b0c14ec4SDavid Hildenbrand memory_region_init(&machine->device_memory->mr, OBJECT(spapr), 28310c9269a5SDavid Hildenbrand "device-memory", device_mem_size); 2832b0c14ec4SDavid Hildenbrand memory_region_add_subregion(sysmem, machine->device_memory->base, 2833b0c14ec4SDavid Hildenbrand &machine->device_memory->mr); 28344a1c9cf0SBharata B Rao } 28354a1c9cf0SBharata B Rao 2836224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2837224245bfSDavid Gibson spapr_create_lmb_dr_connectors(spapr); 2838224245bfSDavid Gibson } 2839224245bfSDavid Gibson 28408af7e1feSNicholas Piggin if (spapr_get_cap(spapr, SPAPR_CAP_FWNMI) == SPAPR_CAP_ON) { 28412500fb42SAravinda Prasad /* Create the error string for live migration blocker */ 28422500fb42SAravinda Prasad error_setg(&spapr->fwnmi_migration_blocker, 28432500fb42SAravinda Prasad "A machine check is being handled during migration. The handler" 28442500fb42SAravinda Prasad "may run and log hardware error on the destination"); 28452500fb42SAravinda Prasad } 28462500fb42SAravinda Prasad 2847ee3a71e3SShivaprasad G Bhat if (mc->nvdimm_supported) { 2848ee3a71e3SShivaprasad G Bhat spapr_create_nvdimm_dr_connectors(spapr); 2849ee3a71e3SShivaprasad G Bhat } 2850ee3a71e3SShivaprasad G Bhat 2851ffbb1705SMichael Roth /* Set up RTAS event infrastructure */ 285253018216SPaolo Bonzini spapr_events_init(spapr); 285353018216SPaolo Bonzini 285412f42174SDavid Gibson /* Set up the RTC RTAS interfaces */ 285528df36a1SDavid Gibson spapr_rtc_create(spapr); 285612f42174SDavid Gibson 285753018216SPaolo Bonzini /* Set up VIO bus */ 285853018216SPaolo Bonzini spapr->vio_bus = spapr_vio_bus_init(); 285953018216SPaolo Bonzini 2860b8846a4dSPeter Maydell for (i = 0; i < serial_max_hds(); i++) { 28619bca0edbSPeter Maydell if (serial_hd(i)) { 28629bca0edbSPeter Maydell spapr_vty_create(spapr->vio_bus, serial_hd(i)); 286353018216SPaolo Bonzini } 286453018216SPaolo Bonzini } 286553018216SPaolo Bonzini 286653018216SPaolo Bonzini /* We always have at least the nvram device on VIO */ 286753018216SPaolo Bonzini spapr_create_nvram(spapr); 286853018216SPaolo Bonzini 2869962b6c36SMichael Roth /* 2870962b6c36SMichael Roth * Setup hotplug / dynamic-reconfiguration connectors. top-level 2871962b6c36SMichael Roth * connectors (described in root DT node's "ibm,drc-types" property) 2872962b6c36SMichael Roth * are pre-initialized here. additional child connectors (such as 2873962b6c36SMichael Roth * connectors for a PHBs PCI slots) are added as needed during their 2874962b6c36SMichael Roth * parent's realization. 2875962b6c36SMichael Roth */ 2876962b6c36SMichael Roth if (smc->dr_phb_enabled) { 2877962b6c36SMichael Roth for (i = 0; i < SPAPR_MAX_PHBS; i++) { 2878962b6c36SMichael Roth spapr_dr_connector_new(OBJECT(machine), TYPE_SPAPR_DRC_PHB, i); 2879962b6c36SMichael Roth } 2880962b6c36SMichael Roth } 2881962b6c36SMichael Roth 288253018216SPaolo Bonzini /* Set up PCI */ 288353018216SPaolo Bonzini spapr_pci_rtas_init(); 288453018216SPaolo Bonzini 2885999c9cafSGreg Kurz phb = spapr_create_default_phb(); 288653018216SPaolo Bonzini 288753018216SPaolo Bonzini for (i = 0; i < nb_nics; i++) { 288853018216SPaolo Bonzini NICInfo *nd = &nd_table[i]; 288953018216SPaolo Bonzini 289053018216SPaolo Bonzini if (!nd->model) { 28913c3a4e7aSThomas Huth nd->model = g_strdup("spapr-vlan"); 289253018216SPaolo Bonzini } 289353018216SPaolo Bonzini 28943c3a4e7aSThomas Huth if (g_str_equal(nd->model, "spapr-vlan") || 28953c3a4e7aSThomas Huth g_str_equal(nd->model, "ibmveth")) { 289653018216SPaolo Bonzini spapr_vlan_create(spapr->vio_bus, nd); 289753018216SPaolo Bonzini } else { 289829b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL); 289953018216SPaolo Bonzini } 290053018216SPaolo Bonzini } 290153018216SPaolo Bonzini 290253018216SPaolo Bonzini for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { 290353018216SPaolo Bonzini spapr_vscsi_create(spapr->vio_bus); 290453018216SPaolo Bonzini } 290553018216SPaolo Bonzini 290653018216SPaolo Bonzini /* Graphics */ 290714c6a894SDavid Gibson if (spapr_vga_init(phb->bus, &error_fatal)) { 290853018216SPaolo Bonzini spapr->has_graphics = true; 2909c6e76503SPaolo Bonzini machine->usb |= defaults_enabled() && !machine->usb_disabled; 291053018216SPaolo Bonzini } 291153018216SPaolo Bonzini 29124ee9ced9SMarcel Apfelbaum if (machine->usb) { 291357040d45SThomas Huth if (smc->use_ohci_by_default) { 291453018216SPaolo Bonzini pci_create_simple(phb->bus, -1, "pci-ohci"); 291557040d45SThomas Huth } else { 291657040d45SThomas Huth pci_create_simple(phb->bus, -1, "nec-usb-xhci"); 291757040d45SThomas Huth } 2918c86580b8SMarkus Armbruster 291953018216SPaolo Bonzini if (spapr->has_graphics) { 2920c86580b8SMarkus Armbruster USBBus *usb_bus = usb_bus_find(-1); 2921c86580b8SMarkus Armbruster 2922c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-kbd"); 2923c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-mouse"); 292453018216SPaolo Bonzini } 292553018216SPaolo Bonzini } 292653018216SPaolo Bonzini 292753018216SPaolo Bonzini if (kernel_filename) { 29284366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL, 292987262806SAlexey Kardashevskiy translate_kernel_address, spapr, 2930617160c9SBALATON Zoltan NULL, NULL, NULL, NULL, 1, 2931a19f7fb0SDavid Gibson PPC_ELF_MACHINE, 0, 0); 2932a19f7fb0SDavid Gibson if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) { 29334366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL, 2934617160c9SBALATON Zoltan translate_kernel_address, spapr, 2935617160c9SBALATON Zoltan NULL, NULL, NULL, NULL, 0, 2936617160c9SBALATON Zoltan PPC_ELF_MACHINE, 0, 0); 2937a19f7fb0SDavid Gibson spapr->kernel_le = spapr->kernel_size > 0; 293816457e7fSBenjamin Herrenschmidt } 2939a19f7fb0SDavid Gibson if (spapr->kernel_size < 0) { 2940a19f7fb0SDavid Gibson error_report("error loading %s: %s", kernel_filename, 2941a19f7fb0SDavid Gibson load_elf_strerror(spapr->kernel_size)); 294253018216SPaolo Bonzini exit(1); 294353018216SPaolo Bonzini } 294453018216SPaolo Bonzini 294553018216SPaolo Bonzini /* load initrd */ 294653018216SPaolo Bonzini if (initrd_filename) { 294753018216SPaolo Bonzini /* Try to locate the initrd in the gap between the kernel 294853018216SPaolo Bonzini * and the firmware. Add a bit of space just in case 294953018216SPaolo Bonzini */ 295087262806SAlexey Kardashevskiy spapr->initrd_base = (spapr->kernel_addr + spapr->kernel_size 2951a19f7fb0SDavid Gibson + 0x1ffff) & ~0xffff; 2952a19f7fb0SDavid Gibson spapr->initrd_size = load_image_targphys(initrd_filename, 2953a19f7fb0SDavid Gibson spapr->initrd_base, 2954a19f7fb0SDavid Gibson load_limit 2955a19f7fb0SDavid Gibson - spapr->initrd_base); 2956a19f7fb0SDavid Gibson if (spapr->initrd_size < 0) { 2957d54e4d76SDavid Gibson error_report("could not load initial ram disk '%s'", 295853018216SPaolo Bonzini initrd_filename); 295953018216SPaolo Bonzini exit(1); 296053018216SPaolo Bonzini } 296153018216SPaolo Bonzini } 296253018216SPaolo Bonzini } 296353018216SPaolo Bonzini 29648e7ea787SAndreas Färber if (bios_name == NULL) { 29658e7ea787SAndreas Färber bios_name = FW_FILE_NAME; 29668e7ea787SAndreas Färber } 29678e7ea787SAndreas Färber filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 29684c56440dSStefan Weil if (!filename) { 296968fea5a0SThomas Huth error_report("Could not find LPAR firmware '%s'", bios_name); 29704c56440dSStefan Weil exit(1); 29714c56440dSStefan Weil } 297253018216SPaolo Bonzini fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); 297368fea5a0SThomas Huth if (fw_size <= 0) { 297468fea5a0SThomas Huth error_report("Could not load LPAR firmware '%s'", filename); 297553018216SPaolo Bonzini exit(1); 297653018216SPaolo Bonzini } 297753018216SPaolo Bonzini g_free(filename); 297853018216SPaolo Bonzini 297928e02042SDavid Gibson /* FIXME: Should register things through the MachineState's qdev 298028e02042SDavid Gibson * interface, this is a legacy from the sPAPREnvironment structure 298128e02042SDavid Gibson * which predated MachineState but had a similar function */ 29824be21d56SDavid Gibson vmstate_register(NULL, 0, &vmstate_spapr, spapr); 29831df2c9a2SPeter Xu register_savevm_live("spapr/htab", VMSTATE_INSTANCE_ID_ANY, 1, 29844be21d56SDavid Gibson &savevm_htab_handlers, spapr); 29854be21d56SDavid Gibson 29869bc6bfdfSMarkus Armbruster qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine)); 2987bb2bdd81SGreg Kurz 29885b2128d2SAlexander Graf qemu_register_boot_set(spapr_boot_set, spapr); 298942043e4fSLaurent Vivier 299093eac7b8SNicholas Piggin /* 299193eac7b8SNicholas Piggin * Nothing needs to be done to resume a suspended guest because 299293eac7b8SNicholas Piggin * suspending does not change the machine state, so no need for 299393eac7b8SNicholas Piggin * a ->wakeup method. 299493eac7b8SNicholas Piggin */ 299593eac7b8SNicholas Piggin qemu_register_wakeup_support(); 299693eac7b8SNicholas Piggin 299742043e4fSLaurent Vivier if (kvm_enabled()) { 29983dc410aeSAlexey Kardashevskiy /* to stop and start vmclock */ 299942043e4fSLaurent Vivier qemu_add_vm_change_state_handler(cpu_ppc_clock_vm_state_change, 300042043e4fSLaurent Vivier &spapr->tb); 30013dc410aeSAlexey Kardashevskiy 30023dc410aeSAlexey Kardashevskiy kvmppc_spapr_enable_inkernel_multitce(); 300342043e4fSLaurent Vivier } 30049ac703acSAravinda Prasad 30058af7e1feSNicholas Piggin qemu_cond_init(&spapr->fwnmi_machine_check_interlock_cond); 300653018216SPaolo Bonzini } 300753018216SPaolo Bonzini 3008dc0ca80eSEric Auger static int spapr_kvm_type(MachineState *machine, const char *vm_type) 3009135a129aSAneesh Kumar K.V { 3010135a129aSAneesh Kumar K.V if (!vm_type) { 3011135a129aSAneesh Kumar K.V return 0; 3012135a129aSAneesh Kumar K.V } 3013135a129aSAneesh Kumar K.V 3014135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "HV")) { 3015135a129aSAneesh Kumar K.V return 1; 3016135a129aSAneesh Kumar K.V } 3017135a129aSAneesh Kumar K.V 3018135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "PR")) { 3019135a129aSAneesh Kumar K.V return 2; 3020135a129aSAneesh Kumar K.V } 3021135a129aSAneesh Kumar K.V 3022135a129aSAneesh Kumar K.V error_report("Unknown kvm-type specified '%s'", vm_type); 3023135a129aSAneesh Kumar K.V exit(1); 3024135a129aSAneesh Kumar K.V } 3025135a129aSAneesh Kumar K.V 302671461b0fSAlexey Kardashevskiy /* 3027627b84f4SGonglei * Implementation of an interface to adjust firmware path 302871461b0fSAlexey Kardashevskiy * for the bootindex property handling. 302971461b0fSAlexey Kardashevskiy */ 303071461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, 303171461b0fSAlexey Kardashevskiy DeviceState *dev) 303271461b0fSAlexey Kardashevskiy { 303371461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \ 303471461b0fSAlexey Kardashevskiy ((type *)object_dynamic_cast(OBJECT(obj), (name))) 303571461b0fSAlexey Kardashevskiy SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); 3036ce2918cbSDavid Gibson SpaprPhbState *phb = CAST(SpaprPhbState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); 3037c4e13492SFelipe Franciosi VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON); 303871461b0fSAlexey Kardashevskiy 303971461b0fSAlexey Kardashevskiy if (d) { 304071461b0fSAlexey Kardashevskiy void *spapr = CAST(void, bus->parent, "spapr-vscsi"); 304171461b0fSAlexey Kardashevskiy VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); 304271461b0fSAlexey Kardashevskiy USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); 304371461b0fSAlexey Kardashevskiy 304471461b0fSAlexey Kardashevskiy if (spapr) { 304571461b0fSAlexey Kardashevskiy /* 304671461b0fSAlexey Kardashevskiy * Replace "channel@0/disk@0,0" with "disk@8000000000000000": 30471ac24c91SThomas Huth * In the top 16 bits of the 64-bit LUN, we use SRP luns of the form 30481ac24c91SThomas Huth * 0x8000 | (target << 8) | (bus << 5) | lun 30491ac24c91SThomas Huth * (see the "Logical unit addressing format" table in SAM5) 305071461b0fSAlexey Kardashevskiy */ 30511ac24c91SThomas Huth unsigned id = 0x8000 | (d->id << 8) | (d->channel << 5) | d->lun; 305271461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 305371461b0fSAlexey Kardashevskiy (uint64_t)id << 48); 305471461b0fSAlexey Kardashevskiy } else if (virtio) { 305571461b0fSAlexey Kardashevskiy /* 305671461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (target << 8) | lun 305771461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 305871461b0fSAlexey Kardashevskiy * Note: the quote above is from SLOF and it is wrong, 305971461b0fSAlexey Kardashevskiy * the actual binding is: 306071461b0fSAlexey Kardashevskiy * swap 0100 or 10 << or 20 << ( target lun-id -- srplun ) 306171461b0fSAlexey Kardashevskiy */ 306271461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (d->id << 16) | d->lun; 3063bac658d1SThomas Huth if (d->lun >= 256) { 3064bac658d1SThomas Huth /* Use the LUN "flat space addressing method" */ 3065bac658d1SThomas Huth id |= 0x4000; 3066bac658d1SThomas Huth } 306771461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 306871461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 306971461b0fSAlexey Kardashevskiy } else if (usb) { 307071461b0fSAlexey Kardashevskiy /* 307171461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (usb-port << 16) | lun 307271461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 307371461b0fSAlexey Kardashevskiy */ 307471461b0fSAlexey Kardashevskiy unsigned usb_port = atoi(usb->port->path); 307571461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (usb_port << 16) | d->lun; 307671461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 307771461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 307871461b0fSAlexey Kardashevskiy } 307971461b0fSAlexey Kardashevskiy } 308071461b0fSAlexey Kardashevskiy 3081b99260ebSThomas Huth /* 3082b99260ebSThomas Huth * SLOF probes the USB devices, and if it recognizes that the device is a 3083b99260ebSThomas Huth * storage device, it changes its name to "storage" instead of "usb-host", 3084b99260ebSThomas Huth * and additionally adds a child node for the SCSI LUN, so the correct 3085b99260ebSThomas Huth * boot path in SLOF is something like .../storage@1/disk@xxx" instead. 3086b99260ebSThomas Huth */ 3087b99260ebSThomas Huth if (strcmp("usb-host", qdev_fw_name(dev)) == 0) { 3088b99260ebSThomas Huth USBDevice *usbdev = CAST(USBDevice, dev, TYPE_USB_DEVICE); 3089b99260ebSThomas Huth if (usb_host_dev_is_scsi_storage(usbdev)) { 3090b99260ebSThomas Huth return g_strdup_printf("storage@%s/disk", usbdev->port->path); 3091b99260ebSThomas Huth } 3092b99260ebSThomas Huth } 3093b99260ebSThomas Huth 309471461b0fSAlexey Kardashevskiy if (phb) { 309571461b0fSAlexey Kardashevskiy /* Replace "pci" with "pci@800000020000000" */ 309671461b0fSAlexey Kardashevskiy return g_strdup_printf("pci@%"PRIX64, phb->buid); 309771461b0fSAlexey Kardashevskiy } 309871461b0fSAlexey Kardashevskiy 3099c4e13492SFelipe Franciosi if (vsc) { 3100c4e13492SFelipe Franciosi /* Same logic as virtio above */ 3101c4e13492SFelipe Franciosi unsigned id = 0x1000000 | (vsc->target << 16) | vsc->lun; 3102c4e13492SFelipe Franciosi return g_strdup_printf("disk@%"PRIX64, (uint64_t)id << 32); 3103c4e13492SFelipe Franciosi } 3104c4e13492SFelipe Franciosi 31054871dd4cSThomas Huth if (g_str_equal("pci-bridge", qdev_fw_name(dev))) { 31064871dd4cSThomas Huth /* SLOF uses "pci" instead of "pci-bridge" for PCI bridges */ 31074871dd4cSThomas Huth PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); 31084871dd4cSThomas Huth return g_strdup_printf("pci@%x", PCI_SLOT(pcidev->devfn)); 31094871dd4cSThomas Huth } 31104871dd4cSThomas Huth 311171461b0fSAlexey Kardashevskiy return NULL; 311271461b0fSAlexey Kardashevskiy } 311371461b0fSAlexey Kardashevskiy 311423825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp) 311523825581SEduardo Habkost { 3116ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 311723825581SEduardo Habkost 311828e02042SDavid Gibson return g_strdup(spapr->kvm_type); 311923825581SEduardo Habkost } 312023825581SEduardo Habkost 312123825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp) 312223825581SEduardo Habkost { 3123ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 312423825581SEduardo Habkost 312528e02042SDavid Gibson g_free(spapr->kvm_type); 312628e02042SDavid Gibson spapr->kvm_type = g_strdup(value); 312723825581SEduardo Habkost } 312823825581SEduardo Habkost 3129f6229214SMichael Roth static bool spapr_get_modern_hotplug_events(Object *obj, Error **errp) 3130f6229214SMichael Roth { 3131ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3132f6229214SMichael Roth 3133f6229214SMichael Roth return spapr->use_hotplug_event_source; 3134f6229214SMichael Roth } 3135f6229214SMichael Roth 3136f6229214SMichael Roth static void spapr_set_modern_hotplug_events(Object *obj, bool value, 3137f6229214SMichael Roth Error **errp) 3138f6229214SMichael Roth { 3139ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3140f6229214SMichael Roth 3141f6229214SMichael Roth spapr->use_hotplug_event_source = value; 3142f6229214SMichael Roth } 3143f6229214SMichael Roth 3144fcad0d21SAlexey Kardashevskiy static bool spapr_get_msix_emulation(Object *obj, Error **errp) 3145fcad0d21SAlexey Kardashevskiy { 3146fcad0d21SAlexey Kardashevskiy return true; 3147fcad0d21SAlexey Kardashevskiy } 3148fcad0d21SAlexey Kardashevskiy 314930f4b05bSDavid Gibson static char *spapr_get_resize_hpt(Object *obj, Error **errp) 315030f4b05bSDavid Gibson { 3151ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 315230f4b05bSDavid Gibson 315330f4b05bSDavid Gibson switch (spapr->resize_hpt) { 315430f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DEFAULT: 315530f4b05bSDavid Gibson return g_strdup("default"); 315630f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DISABLED: 315730f4b05bSDavid Gibson return g_strdup("disabled"); 315830f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_ENABLED: 315930f4b05bSDavid Gibson return g_strdup("enabled"); 316030f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_REQUIRED: 316130f4b05bSDavid Gibson return g_strdup("required"); 316230f4b05bSDavid Gibson } 316330f4b05bSDavid Gibson g_assert_not_reached(); 316430f4b05bSDavid Gibson } 316530f4b05bSDavid Gibson 316630f4b05bSDavid Gibson static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp) 316730f4b05bSDavid Gibson { 3168ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 316930f4b05bSDavid Gibson 317030f4b05bSDavid Gibson if (strcmp(value, "default") == 0) { 317130f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DEFAULT; 317230f4b05bSDavid Gibson } else if (strcmp(value, "disabled") == 0) { 317330f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 317430f4b05bSDavid Gibson } else if (strcmp(value, "enabled") == 0) { 317530f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_ENABLED; 317630f4b05bSDavid Gibson } else if (strcmp(value, "required") == 0) { 317730f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_REQUIRED; 317830f4b05bSDavid Gibson } else { 317930f4b05bSDavid Gibson error_setg(errp, "Bad value for \"resize-hpt\" property"); 318030f4b05bSDavid Gibson } 318130f4b05bSDavid Gibson } 318230f4b05bSDavid Gibson 31833ba3d0bcSCédric Le Goater static char *spapr_get_ic_mode(Object *obj, Error **errp) 31843ba3d0bcSCédric Le Goater { 3185ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 31863ba3d0bcSCédric Le Goater 31873ba3d0bcSCédric Le Goater if (spapr->irq == &spapr_irq_xics_legacy) { 31883ba3d0bcSCédric Le Goater return g_strdup("legacy"); 31893ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xics) { 31903ba3d0bcSCédric Le Goater return g_strdup("xics"); 31913ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xive) { 31923ba3d0bcSCédric Le Goater return g_strdup("xive"); 319313db0cd9SCédric Le Goater } else if (spapr->irq == &spapr_irq_dual) { 319413db0cd9SCédric Le Goater return g_strdup("dual"); 31953ba3d0bcSCédric Le Goater } 31963ba3d0bcSCédric Le Goater g_assert_not_reached(); 31973ba3d0bcSCédric Le Goater } 31983ba3d0bcSCédric Le Goater 31993ba3d0bcSCédric Le Goater static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp) 32003ba3d0bcSCédric Le Goater { 3201ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 32023ba3d0bcSCédric Le Goater 320321df5e4fSGreg Kurz if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { 320421df5e4fSGreg Kurz error_setg(errp, "This machine only uses the legacy XICS backend, don't pass ic-mode"); 320521df5e4fSGreg Kurz return; 320621df5e4fSGreg Kurz } 320721df5e4fSGreg Kurz 32083ba3d0bcSCédric Le Goater /* The legacy IRQ backend can not be set */ 32093ba3d0bcSCédric Le Goater if (strcmp(value, "xics") == 0) { 32103ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xics; 32113ba3d0bcSCédric Le Goater } else if (strcmp(value, "xive") == 0) { 32123ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xive; 321313db0cd9SCédric Le Goater } else if (strcmp(value, "dual") == 0) { 321413db0cd9SCédric Le Goater spapr->irq = &spapr_irq_dual; 32153ba3d0bcSCédric Le Goater } else { 32163ba3d0bcSCédric Le Goater error_setg(errp, "Bad value for \"ic-mode\" property"); 32173ba3d0bcSCédric Le Goater } 32183ba3d0bcSCédric Le Goater } 32193ba3d0bcSCédric Le Goater 322027461d69SPrasad J Pandit static char *spapr_get_host_model(Object *obj, Error **errp) 322127461d69SPrasad J Pandit { 3222ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 322327461d69SPrasad J Pandit 322427461d69SPrasad J Pandit return g_strdup(spapr->host_model); 322527461d69SPrasad J Pandit } 322627461d69SPrasad J Pandit 322727461d69SPrasad J Pandit static void spapr_set_host_model(Object *obj, const char *value, Error **errp) 322827461d69SPrasad J Pandit { 3229ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 323027461d69SPrasad J Pandit 323127461d69SPrasad J Pandit g_free(spapr->host_model); 323227461d69SPrasad J Pandit spapr->host_model = g_strdup(value); 323327461d69SPrasad J Pandit } 323427461d69SPrasad J Pandit 323527461d69SPrasad J Pandit static char *spapr_get_host_serial(Object *obj, Error **errp) 323627461d69SPrasad J Pandit { 3237ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 323827461d69SPrasad J Pandit 323927461d69SPrasad J Pandit return g_strdup(spapr->host_serial); 324027461d69SPrasad J Pandit } 324127461d69SPrasad J Pandit 324227461d69SPrasad J Pandit static void spapr_set_host_serial(Object *obj, const char *value, Error **errp) 324327461d69SPrasad J Pandit { 3244ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 324527461d69SPrasad J Pandit 324627461d69SPrasad J Pandit g_free(spapr->host_serial); 324727461d69SPrasad J Pandit spapr->host_serial = g_strdup(value); 324827461d69SPrasad J Pandit } 324927461d69SPrasad J Pandit 3250bcb5ce08SDavid Gibson static void spapr_instance_init(Object *obj) 325123825581SEduardo Habkost { 3252ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3253ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 3254715c5407SDavid Gibson 3255715c5407SDavid Gibson spapr->htab_fd = -1; 3256f6229214SMichael Roth spapr->use_hotplug_event_source = true; 325723825581SEduardo Habkost object_property_add_str(obj, "kvm-type", 3258d2623129SMarkus Armbruster spapr_get_kvm_type, spapr_set_kvm_type); 325949d2e648SMarcel Apfelbaum object_property_set_description(obj, "kvm-type", 32607eecec7dSMarkus Armbruster "Specifies the KVM virtualization mode (HV, PR)"); 3261f6229214SMichael Roth object_property_add_bool(obj, "modern-hotplug-events", 3262f6229214SMichael Roth spapr_get_modern_hotplug_events, 3263d2623129SMarkus Armbruster spapr_set_modern_hotplug_events); 3264f6229214SMichael Roth object_property_set_description(obj, "modern-hotplug-events", 3265f6229214SMichael Roth "Use dedicated hotplug event mechanism in" 3266f6229214SMichael Roth " place of standard EPOW events when possible" 32677eecec7dSMarkus Armbruster " (required for memory hot-unplug support)"); 32687843c0d6SDavid Gibson ppc_compat_add_property(obj, "max-cpu-compat", &spapr->max_compat_pvr, 326940c2281cSMarkus Armbruster "Maximum permitted CPU compatibility mode"); 327030f4b05bSDavid Gibson 327130f4b05bSDavid Gibson object_property_add_str(obj, "resize-hpt", 3272d2623129SMarkus Armbruster spapr_get_resize_hpt, spapr_set_resize_hpt); 327330f4b05bSDavid Gibson object_property_set_description(obj, "resize-hpt", 32747eecec7dSMarkus Armbruster "Resizing of the Hash Page Table (enabled, disabled, required)"); 327564a7b8deSFelipe Franciosi object_property_add_uint32_ptr(obj, "vsmt", 3276d2623129SMarkus Armbruster &spapr->vsmt, OBJ_PROP_FLAG_READWRITE); 3277fa98fbfcSSam Bobroff object_property_set_description(obj, "vsmt", 3278fa98fbfcSSam Bobroff "Virtual SMT: KVM behaves as if this were" 32797eecec7dSMarkus Armbruster " the host's SMT mode"); 328064a7b8deSFelipe Franciosi 3281fcad0d21SAlexey Kardashevskiy object_property_add_bool(obj, "vfio-no-msix-emulation", 3282d2623129SMarkus Armbruster spapr_get_msix_emulation, NULL); 32833ba3d0bcSCédric Le Goater 328464a7b8deSFelipe Franciosi object_property_add_uint64_ptr(obj, "kernel-addr", 3285d2623129SMarkus Armbruster &spapr->kernel_addr, OBJ_PROP_FLAG_READWRITE); 328687262806SAlexey Kardashevskiy object_property_set_description(obj, "kernel-addr", 328787262806SAlexey Kardashevskiy stringify(KERNEL_LOAD_ADDR) 32887eecec7dSMarkus Armbruster " for -kernel is the default"); 328987262806SAlexey Kardashevskiy spapr->kernel_addr = KERNEL_LOAD_ADDR; 32903ba3d0bcSCédric Le Goater /* The machine class defines the default interrupt controller mode */ 32913ba3d0bcSCédric Le Goater spapr->irq = smc->irq; 32923ba3d0bcSCédric Le Goater object_property_add_str(obj, "ic-mode", spapr_get_ic_mode, 3293d2623129SMarkus Armbruster spapr_set_ic_mode); 32943ba3d0bcSCédric Le Goater object_property_set_description(obj, "ic-mode", 32957eecec7dSMarkus Armbruster "Specifies the interrupt controller mode (xics, xive, dual)"); 329627461d69SPrasad J Pandit 329727461d69SPrasad J Pandit object_property_add_str(obj, "host-model", 3298d2623129SMarkus Armbruster spapr_get_host_model, spapr_set_host_model); 329927461d69SPrasad J Pandit object_property_set_description(obj, "host-model", 33007eecec7dSMarkus Armbruster "Host model to advertise in guest device tree"); 330127461d69SPrasad J Pandit object_property_add_str(obj, "host-serial", 3302d2623129SMarkus Armbruster spapr_get_host_serial, spapr_set_host_serial); 330327461d69SPrasad J Pandit object_property_set_description(obj, "host-serial", 33047eecec7dSMarkus Armbruster "Host serial number to advertise in guest device tree"); 330523825581SEduardo Habkost } 330623825581SEduardo Habkost 330787bbdd9cSDavid Gibson static void spapr_machine_finalizefn(Object *obj) 330887bbdd9cSDavid Gibson { 3309ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 331087bbdd9cSDavid Gibson 331187bbdd9cSDavid Gibson g_free(spapr->kvm_type); 331287bbdd9cSDavid Gibson } 331387bbdd9cSDavid Gibson 33141c7ad77eSNicholas Piggin void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg) 331534316482SAlexey Kardashevskiy { 33160e236d34SNicholas Piggin SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 3317b5b7f391SNicholas Piggin PowerPCCPU *cpu = POWERPC_CPU(cs); 3318b5b7f391SNicholas Piggin CPUPPCState *env = &cpu->env; 33190e236d34SNicholas Piggin 332034316482SAlexey Kardashevskiy cpu_synchronize_state(cs); 33210e236d34SNicholas Piggin /* If FWNMI is inactive, addr will be -1, which will deliver to 0x100 */ 33220e236d34SNicholas Piggin if (spapr->fwnmi_system_reset_addr != -1) { 33230e236d34SNicholas Piggin uint64_t rtas_addr, addr; 33240e236d34SNicholas Piggin 33250e236d34SNicholas Piggin /* get rtas addr from fdt */ 33260e236d34SNicholas Piggin rtas_addr = spapr_get_rtas_addr(); 33270e236d34SNicholas Piggin if (!rtas_addr) { 33280e236d34SNicholas Piggin qemu_system_guest_panicked(NULL); 33290e236d34SNicholas Piggin return; 33300e236d34SNicholas Piggin } 33310e236d34SNicholas Piggin 33320e236d34SNicholas Piggin addr = rtas_addr + RTAS_ERROR_LOG_MAX + cs->cpu_index * sizeof(uint64_t)*2; 33330e236d34SNicholas Piggin stq_be_phys(&address_space_memory, addr, env->gpr[3]); 33340e236d34SNicholas Piggin stq_be_phys(&address_space_memory, addr + sizeof(uint64_t), 0); 33350e236d34SNicholas Piggin env->gpr[3] = addr; 33360e236d34SNicholas Piggin } 3337b5b7f391SNicholas Piggin ppc_cpu_do_system_reset(cs); 3338b5b7f391SNicholas Piggin if (spapr->fwnmi_system_reset_addr != -1) { 3339b5b7f391SNicholas Piggin env->nip = spapr->fwnmi_system_reset_addr; 3340b5b7f391SNicholas Piggin } 334134316482SAlexey Kardashevskiy } 334234316482SAlexey Kardashevskiy 334334316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) 334434316482SAlexey Kardashevskiy { 334534316482SAlexey Kardashevskiy CPUState *cs; 334634316482SAlexey Kardashevskiy 334734316482SAlexey Kardashevskiy CPU_FOREACH(cs) { 33481c7ad77eSNicholas Piggin async_run_on_cpu(cs, spapr_do_system_reset_on_cpu, RUN_ON_CPU_NULL); 334934316482SAlexey Kardashevskiy } 335034316482SAlexey Kardashevskiy } 335134316482SAlexey Kardashevskiy 3352ce2918cbSDavid Gibson int spapr_lmb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 335362d38c9bSGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 335462d38c9bSGreg Kurz { 335562d38c9bSGreg Kurz uint64_t addr; 335662d38c9bSGreg Kurz uint32_t node; 335762d38c9bSGreg Kurz 335862d38c9bSGreg Kurz addr = spapr_drc_index(drc) * SPAPR_MEMORY_BLOCK_SIZE; 335962d38c9bSGreg Kurz node = object_property_get_uint(OBJECT(drc->dev), PC_DIMM_NODE_PROP, 336062d38c9bSGreg Kurz &error_abort); 3361f1aa45ffSDaniel Henrique Barboza *fdt_start_offset = spapr_dt_memory_node(spapr, fdt, node, addr, 336262d38c9bSGreg Kurz SPAPR_MEMORY_BLOCK_SIZE); 336362d38c9bSGreg Kurz return 0; 336462d38c9bSGreg Kurz } 336562d38c9bSGreg Kurz 336679b78a6bSMichael Roth static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, 336762d38c9bSGreg Kurz bool dedicated_hp_event_source, Error **errp) 3368c20d332aSBharata B Rao { 3369ce2918cbSDavid Gibson SpaprDrc *drc; 3370c20d332aSBharata B Rao uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; 337162d38c9bSGreg Kurz int i; 337279b78a6bSMichael Roth uint64_t addr = addr_start; 337394fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 3374c20d332aSBharata B Rao 3375c20d332aSBharata B Rao for (i = 0; i < nr_lmbs; i++) { 3376fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 3377c20d332aSBharata B Rao addr / SPAPR_MEMORY_BLOCK_SIZE); 3378c20d332aSBharata B Rao g_assert(drc); 3379c20d332aSBharata B Rao 3380*17548fe6SGreg Kurz if (!spapr_drc_attach(drc, dev, errp)) { 3381160bb678SGreg Kurz while (addr > addr_start) { 3382160bb678SGreg Kurz addr -= SPAPR_MEMORY_BLOCK_SIZE; 3383160bb678SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 3384160bb678SGreg Kurz addr / SPAPR_MEMORY_BLOCK_SIZE); 3385a8dc47fdSDavid Gibson spapr_drc_detach(drc); 3386160bb678SGreg Kurz } 3387160bb678SGreg Kurz return; 3388160bb678SGreg Kurz } 338994fd9cbaSLaurent Vivier if (!hotplugged) { 339094fd9cbaSLaurent Vivier spapr_drc_reset(drc); 339194fd9cbaSLaurent Vivier } 3392c20d332aSBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE; 3393c20d332aSBharata B Rao } 33945dd5238cSJianjun Duan /* send hotplug notification to the 33955dd5238cSJianjun Duan * guest only in case of hotplugged memory 33965dd5238cSJianjun Duan */ 339794fd9cbaSLaurent Vivier if (hotplugged) { 339879b78a6bSMichael Roth if (dedicated_hp_event_source) { 3399fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 340079b78a6bSMichael Roth addr_start / SPAPR_MEMORY_BLOCK_SIZE); 340179b78a6bSMichael Roth spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 340279b78a6bSMichael Roth nr_lmbs, 34030b55aa91SDavid Gibson spapr_drc_index(drc)); 340479b78a6bSMichael Roth } else { 340579b78a6bSMichael Roth spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, 340679b78a6bSMichael Roth nr_lmbs); 340779b78a6bSMichael Roth } 3408c20d332aSBharata B Rao } 34095dd5238cSJianjun Duan } 3410c20d332aSBharata B Rao 3411c20d332aSBharata B Rao static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 341281985f3bSDavid Hildenbrand Error **errp) 3413c20d332aSBharata B Rao { 3414c20d332aSBharata B Rao Error *local_err = NULL; 3415ce2918cbSDavid Gibson SpaprMachineState *ms = SPAPR_MACHINE(hotplug_dev); 3416c20d332aSBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 3417ee3a71e3SShivaprasad G Bhat uint64_t size, addr, slot; 3418ee3a71e3SShivaprasad G Bhat bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); 341904790978SThomas Huth 3420946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dev), &error_abort); 3421df587133SThomas Huth 3422fd3416f5SDavid Hildenbrand pc_dimm_plug(dimm, MACHINE(ms), &local_err); 3423c20d332aSBharata B Rao if (local_err) { 3424c20d332aSBharata B Rao goto out; 3425c20d332aSBharata B Rao } 3426c20d332aSBharata B Rao 3427ee3a71e3SShivaprasad G Bhat if (!is_nvdimm) { 34289ed442b8SMarc-André Lureau addr = object_property_get_uint(OBJECT(dimm), 34299ed442b8SMarc-André Lureau PC_DIMM_ADDR_PROP, &local_err); 3430c20d332aSBharata B Rao if (local_err) { 3431160bb678SGreg Kurz goto out_unplug; 3432c20d332aSBharata B Rao } 3433ee3a71e3SShivaprasad G Bhat spapr_add_lmbs(dev, addr, size, 3434ee3a71e3SShivaprasad G Bhat spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), 3435160bb678SGreg Kurz &local_err); 3436ee3a71e3SShivaprasad G Bhat } else { 3437ee3a71e3SShivaprasad G Bhat slot = object_property_get_uint(OBJECT(dimm), 3438ee3a71e3SShivaprasad G Bhat PC_DIMM_SLOT_PROP, &local_err); 3439ee3a71e3SShivaprasad G Bhat if (local_err) { 3440ee3a71e3SShivaprasad G Bhat goto out_unplug; 3441ee3a71e3SShivaprasad G Bhat } 3442ee3a71e3SShivaprasad G Bhat spapr_add_nvdimm(dev, slot, &local_err); 3443ee3a71e3SShivaprasad G Bhat } 3444ee3a71e3SShivaprasad G Bhat 3445160bb678SGreg Kurz if (local_err) { 3446160bb678SGreg Kurz goto out_unplug; 3447160bb678SGreg Kurz } 3448c20d332aSBharata B Rao 3449160bb678SGreg Kurz return; 3450160bb678SGreg Kurz 3451160bb678SGreg Kurz out_unplug: 3452fd3416f5SDavid Hildenbrand pc_dimm_unplug(dimm, MACHINE(ms)); 3453c20d332aSBharata B Rao out: 3454c20d332aSBharata B Rao error_propagate(errp, local_err); 3455c20d332aSBharata B Rao } 3456c20d332aSBharata B Rao 3457c871bc70SLaurent Vivier static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3458c871bc70SLaurent Vivier Error **errp) 3459c871bc70SLaurent Vivier { 3460ce2918cbSDavid Gibson const SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev); 3461ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3462ee3a71e3SShivaprasad G Bhat bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); 3463c871bc70SLaurent Vivier PCDIMMDevice *dimm = PC_DIMM(dev); 34648f1ffe5bSDavid Hildenbrand Error *local_err = NULL; 346504790978SThomas Huth uint64_t size; 3466123eec65SDavid Gibson Object *memdev; 3467123eec65SDavid Gibson hwaddr pagesize; 3468c871bc70SLaurent Vivier 34694e8a01bdSDavid Hildenbrand if (!smc->dr_lmb_enabled) { 34704e8a01bdSDavid Hildenbrand error_setg(errp, "Memory hotplug not supported for this machine"); 34714e8a01bdSDavid Hildenbrand return; 34724e8a01bdSDavid Hildenbrand } 34734e8a01bdSDavid Hildenbrand 3474946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &local_err); 3475946d6154SDavid Hildenbrand if (local_err) { 3476946d6154SDavid Hildenbrand error_propagate(errp, local_err); 347704790978SThomas Huth return; 347804790978SThomas Huth } 347904790978SThomas Huth 3480beb6073fSDaniel Henrique Barboza if (is_nvdimm) { 3481beb6073fSDaniel Henrique Barboza spapr_nvdimm_validate(hotplug_dev, NVDIMM(dev), size, &local_err); 3482ee3a71e3SShivaprasad G Bhat if (local_err) { 3483ee3a71e3SShivaprasad G Bhat error_propagate(errp, local_err); 3484ee3a71e3SShivaprasad G Bhat return; 3485ee3a71e3SShivaprasad G Bhat } 3486beb6073fSDaniel Henrique Barboza } else if (size % SPAPR_MEMORY_BLOCK_SIZE) { 3487beb6073fSDaniel Henrique Barboza error_setg(errp, "Hotplugged memory size must be a multiple of " 3488beb6073fSDaniel Henrique Barboza "%" PRIu64 " MB", SPAPR_MEMORY_BLOCK_SIZE / MiB); 3489beb6073fSDaniel Henrique Barboza return; 3490c871bc70SLaurent Vivier } 3491c871bc70SLaurent Vivier 3492123eec65SDavid Gibson memdev = object_property_get_link(OBJECT(dimm), PC_DIMM_MEMDEV_PROP, 3493123eec65SDavid Gibson &error_abort); 3494123eec65SDavid Gibson pagesize = host_memory_backend_pagesize(MEMORY_BACKEND(memdev)); 34958f1ffe5bSDavid Hildenbrand spapr_check_pagesize(spapr, pagesize, &local_err); 34968f1ffe5bSDavid Hildenbrand if (local_err) { 34978f1ffe5bSDavid Hildenbrand error_propagate(errp, local_err); 34988f1ffe5bSDavid Hildenbrand return; 34998f1ffe5bSDavid Hildenbrand } 35008f1ffe5bSDavid Hildenbrand 3501fd3416f5SDavid Hildenbrand pc_dimm_pre_plug(dimm, MACHINE(hotplug_dev), NULL, errp); 3502c871bc70SLaurent Vivier } 3503c871bc70SLaurent Vivier 3504ce2918cbSDavid Gibson struct SpaprDimmState { 35050cffce56SDavid Gibson PCDIMMDevice *dimm; 3506cf632463SBharata B Rao uint32_t nr_lmbs; 3507ce2918cbSDavid Gibson QTAILQ_ENTRY(SpaprDimmState) next; 35080cffce56SDavid Gibson }; 35090cffce56SDavid Gibson 3510ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_find(SpaprMachineState *s, 35110cffce56SDavid Gibson PCDIMMDevice *dimm) 35120cffce56SDavid Gibson { 3513ce2918cbSDavid Gibson SpaprDimmState *dimm_state = NULL; 35140cffce56SDavid Gibson 35150cffce56SDavid Gibson QTAILQ_FOREACH(dimm_state, &s->pending_dimm_unplugs, next) { 35160cffce56SDavid Gibson if (dimm_state->dimm == dimm) { 35170cffce56SDavid Gibson break; 35180cffce56SDavid Gibson } 35190cffce56SDavid Gibson } 35200cffce56SDavid Gibson return dimm_state; 35210cffce56SDavid Gibson } 35220cffce56SDavid Gibson 3523ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_add(SpaprMachineState *spapr, 35248d5981c4SBharata B Rao uint32_t nr_lmbs, 35258d5981c4SBharata B Rao PCDIMMDevice *dimm) 35260cffce56SDavid Gibson { 3527ce2918cbSDavid Gibson SpaprDimmState *ds = NULL; 35288d5981c4SBharata B Rao 35298d5981c4SBharata B Rao /* 35308d5981c4SBharata B Rao * If this request is for a DIMM whose removal had failed earlier 35318d5981c4SBharata B Rao * (due to guest's refusal to remove the LMBs), we would have this 35328d5981c4SBharata B Rao * dimm already in the pending_dimm_unplugs list. In that 35338d5981c4SBharata B Rao * case don't add again. 35348d5981c4SBharata B Rao */ 35358d5981c4SBharata B Rao ds = spapr_pending_dimm_unplugs_find(spapr, dimm); 35368d5981c4SBharata B Rao if (!ds) { 3537ce2918cbSDavid Gibson ds = g_malloc0(sizeof(SpaprDimmState)); 35388d5981c4SBharata B Rao ds->nr_lmbs = nr_lmbs; 35398d5981c4SBharata B Rao ds->dimm = dimm; 35408d5981c4SBharata B Rao QTAILQ_INSERT_HEAD(&spapr->pending_dimm_unplugs, ds, next); 35418d5981c4SBharata B Rao } 35428d5981c4SBharata B Rao return ds; 35430cffce56SDavid Gibson } 35440cffce56SDavid Gibson 3545ce2918cbSDavid Gibson static void spapr_pending_dimm_unplugs_remove(SpaprMachineState *spapr, 3546ce2918cbSDavid Gibson SpaprDimmState *dimm_state) 35470cffce56SDavid Gibson { 35480cffce56SDavid Gibson QTAILQ_REMOVE(&spapr->pending_dimm_unplugs, dimm_state, next); 35490cffce56SDavid Gibson g_free(dimm_state); 35500cffce56SDavid Gibson } 3551cf632463SBharata B Rao 3552ce2918cbSDavid Gibson static SpaprDimmState *spapr_recover_pending_dimm_state(SpaprMachineState *ms, 355316ee9980SDaniel Henrique Barboza PCDIMMDevice *dimm) 355416ee9980SDaniel Henrique Barboza { 3555ce2918cbSDavid Gibson SpaprDrc *drc; 3556946d6154SDavid Hildenbrand uint64_t size = memory_device_get_region_size(MEMORY_DEVICE(dimm), 3557946d6154SDavid Hildenbrand &error_abort); 355816ee9980SDaniel Henrique Barboza uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 355916ee9980SDaniel Henrique Barboza uint32_t avail_lmbs = 0; 356016ee9980SDaniel Henrique Barboza uint64_t addr_start, addr; 356116ee9980SDaniel Henrique Barboza int i; 356216ee9980SDaniel Henrique Barboza 356316ee9980SDaniel Henrique Barboza addr_start = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, 356416ee9980SDaniel Henrique Barboza &error_abort); 356516ee9980SDaniel Henrique Barboza 356616ee9980SDaniel Henrique Barboza addr = addr_start; 356716ee9980SDaniel Henrique Barboza for (i = 0; i < nr_lmbs; i++) { 3568fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 356916ee9980SDaniel Henrique Barboza addr / SPAPR_MEMORY_BLOCK_SIZE); 357016ee9980SDaniel Henrique Barboza g_assert(drc); 3571454b580aSDavid Gibson if (drc->dev) { 357216ee9980SDaniel Henrique Barboza avail_lmbs++; 357316ee9980SDaniel Henrique Barboza } 357416ee9980SDaniel Henrique Barboza addr += SPAPR_MEMORY_BLOCK_SIZE; 357516ee9980SDaniel Henrique Barboza } 357616ee9980SDaniel Henrique Barboza 35778d5981c4SBharata B Rao return spapr_pending_dimm_unplugs_add(ms, avail_lmbs, dimm); 357816ee9980SDaniel Henrique Barboza } 357916ee9980SDaniel Henrique Barboza 358031834723SDaniel Henrique Barboza /* Callback to be called during DRC release. */ 358131834723SDaniel Henrique Barboza void spapr_lmb_release(DeviceState *dev) 3582cf632463SBharata B Rao { 35833ec71474SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3584ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl); 3585ce2918cbSDavid Gibson SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); 3586cf632463SBharata B Rao 358716ee9980SDaniel Henrique Barboza /* This information will get lost if a migration occurs 358816ee9980SDaniel Henrique Barboza * during the unplug process. In this case recover it. */ 358916ee9980SDaniel Henrique Barboza if (ds == NULL) { 359016ee9980SDaniel Henrique Barboza ds = spapr_recover_pending_dimm_state(spapr, PC_DIMM(dev)); 35918d5981c4SBharata B Rao g_assert(ds); 3592454b580aSDavid Gibson /* The DRC being examined by the caller at least must be counted */ 3593454b580aSDavid Gibson g_assert(ds->nr_lmbs); 359416ee9980SDaniel Henrique Barboza } 3595454b580aSDavid Gibson 3596454b580aSDavid Gibson if (--ds->nr_lmbs) { 3597cf632463SBharata B Rao return; 3598cf632463SBharata B Rao } 3599cf632463SBharata B Rao 3600cf632463SBharata B Rao /* 3601cf632463SBharata B Rao * Now that all the LMBs have been removed by the guest, call the 36023ec71474SDavid Hildenbrand * unplug handler chain. This can never fail. 3603cf632463SBharata B Rao */ 36043ec71474SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 360507578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 36063ec71474SDavid Hildenbrand } 36073ec71474SDavid Hildenbrand 36083ec71474SDavid Hildenbrand static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 36093ec71474SDavid Hildenbrand { 3610ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3611ce2918cbSDavid Gibson SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); 36123ec71474SDavid Hildenbrand 3613fd3416f5SDavid Hildenbrand pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev)); 3614981c3dcdSMarkus Armbruster qdev_unrealize(dev); 36152a129767SDaniel Henrique Barboza spapr_pending_dimm_unplugs_remove(spapr, ds); 3616cf632463SBharata B Rao } 3617cf632463SBharata B Rao 3618cf632463SBharata B Rao static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, 3619cf632463SBharata B Rao DeviceState *dev, Error **errp) 3620cf632463SBharata B Rao { 3621ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3622cf632463SBharata B Rao Error *local_err = NULL; 3623cf632463SBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 362404790978SThomas Huth uint32_t nr_lmbs; 362504790978SThomas Huth uint64_t size, addr_start, addr; 36260cffce56SDavid Gibson int i; 3627ce2918cbSDavid Gibson SpaprDrc *drc; 362804790978SThomas Huth 3629ee3a71e3SShivaprasad G Bhat if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { 3630dcfe4805SMarkus Armbruster error_setg(errp, "nvdimm device hot unplug is not supported yet."); 3631dcfe4805SMarkus Armbruster return; 3632ee3a71e3SShivaprasad G Bhat } 3633ee3a71e3SShivaprasad G Bhat 3634946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &error_abort); 363504790978SThomas Huth nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 363604790978SThomas Huth 36379ed442b8SMarc-André Lureau addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, 36380cffce56SDavid Gibson &local_err); 3639cf632463SBharata B Rao if (local_err) { 3640dcfe4805SMarkus Armbruster error_propagate(errp, local_err); 3641dcfe4805SMarkus Armbruster return; 3642cf632463SBharata B Rao } 3643cf632463SBharata B Rao 36442a129767SDaniel Henrique Barboza /* 36452a129767SDaniel Henrique Barboza * An existing pending dimm state for this DIMM means that there is an 36462a129767SDaniel Henrique Barboza * unplug operation in progress, waiting for the spapr_lmb_release 36472a129767SDaniel Henrique Barboza * callback to complete the job (BQL can't cover that far). In this case, 36482a129767SDaniel Henrique Barboza * bail out to avoid detaching DRCs that were already released. 36492a129767SDaniel Henrique Barboza */ 36502a129767SDaniel Henrique Barboza if (spapr_pending_dimm_unplugs_find(spapr, dimm)) { 3651dcfe4805SMarkus Armbruster error_setg(errp, "Memory unplug already in progress for device %s", 36522a129767SDaniel Henrique Barboza dev->id); 3653dcfe4805SMarkus Armbruster return; 36542a129767SDaniel Henrique Barboza } 36552a129767SDaniel Henrique Barboza 36568d5981c4SBharata B Rao spapr_pending_dimm_unplugs_add(spapr, nr_lmbs, dimm); 36570cffce56SDavid Gibson 36580cffce56SDavid Gibson addr = addr_start; 36590cffce56SDavid Gibson for (i = 0; i < nr_lmbs; i++) { 3660fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 36610cffce56SDavid Gibson addr / SPAPR_MEMORY_BLOCK_SIZE); 36620cffce56SDavid Gibson g_assert(drc); 36630cffce56SDavid Gibson 3664a8dc47fdSDavid Gibson spapr_drc_detach(drc); 36650cffce56SDavid Gibson addr += SPAPR_MEMORY_BLOCK_SIZE; 36660cffce56SDavid Gibson } 36670cffce56SDavid Gibson 3668fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 36690cffce56SDavid Gibson addr_start / SPAPR_MEMORY_BLOCK_SIZE); 36700cffce56SDavid Gibson spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 36710b55aa91SDavid Gibson nr_lmbs, spapr_drc_index(drc)); 3672cf632463SBharata B Rao } 3673cf632463SBharata B Rao 3674765d1bddSDavid Gibson /* Callback to be called during DRC release. */ 3675765d1bddSDavid Gibson void spapr_core_release(DeviceState *dev) 3676ff9006ddSIgor Mammedov { 3677a4261be1SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3678a4261be1SDavid Hildenbrand 3679a4261be1SDavid Hildenbrand /* Call the unplug handler chain. This can never fail. */ 3680a4261be1SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 368107578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 3682a4261be1SDavid Hildenbrand } 3683a4261be1SDavid Hildenbrand 3684a4261be1SDavid Hildenbrand static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 3685a4261be1SDavid Hildenbrand { 3686a4261be1SDavid Hildenbrand MachineState *ms = MACHINE(hotplug_dev); 3687ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms); 3688ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3689535455fdSIgor Mammedov CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL); 3690ff9006ddSIgor Mammedov 369146f7afa3SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 3692ce2918cbSDavid Gibson SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); 369346f7afa3SGreg Kurz int i; 369446f7afa3SGreg Kurz 369546f7afa3SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 369694ad93bdSGreg Kurz CPUState *cs = CPU(sc->threads[i]); 369746f7afa3SGreg Kurz 369846f7afa3SGreg Kurz pre_2_10_vmstate_register_dummy_icp(cs->cpu_index); 369946f7afa3SGreg Kurz } 370046f7afa3SGreg Kurz } 370146f7afa3SGreg Kurz 370207572c06SGreg Kurz assert(core_slot); 3703535455fdSIgor Mammedov core_slot->cpu = NULL; 3704981c3dcdSMarkus Armbruster qdev_unrealize(dev); 3705ff9006ddSIgor Mammedov } 3706ff9006ddSIgor Mammedov 3707115debf2SIgor Mammedov static 3708115debf2SIgor Mammedov void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, 3709ff9006ddSIgor Mammedov Error **errp) 3710ff9006ddSIgor Mammedov { 3711ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3712535455fdSIgor Mammedov int index; 3713ce2918cbSDavid Gibson SpaprDrc *drc; 3714535455fdSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3715ff9006ddSIgor Mammedov 3716535455fdSIgor Mammedov if (!spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index)) { 3717535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 3718535455fdSIgor Mammedov cc->core_id); 3719535455fdSIgor Mammedov return; 3720535455fdSIgor Mammedov } 3721ff9006ddSIgor Mammedov if (index == 0) { 3722ff9006ddSIgor Mammedov error_setg(errp, "Boot CPU core may not be unplugged"); 3723ff9006ddSIgor Mammedov return; 3724ff9006ddSIgor Mammedov } 3725ff9006ddSIgor Mammedov 37265d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 37275d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 3728ff9006ddSIgor Mammedov g_assert(drc); 3729ff9006ddSIgor Mammedov 373047c8c915SGreg Kurz if (!spapr_drc_unplug_requested(drc)) { 3731a8dc47fdSDavid Gibson spapr_drc_detach(drc); 3732ff9006ddSIgor Mammedov spapr_hotplug_req_remove_by_index(drc); 3733ff9006ddSIgor Mammedov } 373447c8c915SGreg Kurz } 3735ff9006ddSIgor Mammedov 3736ce2918cbSDavid Gibson int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 3737345b12b9SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 3738345b12b9SGreg Kurz { 3739ce2918cbSDavid Gibson SpaprCpuCore *core = SPAPR_CPU_CORE(drc->dev); 3740345b12b9SGreg Kurz CPUState *cs = CPU(core->threads[0]); 3741345b12b9SGreg Kurz PowerPCCPU *cpu = POWERPC_CPU(cs); 3742345b12b9SGreg Kurz DeviceClass *dc = DEVICE_GET_CLASS(cs); 3743345b12b9SGreg Kurz int id = spapr_get_vcpu_id(cpu); 3744345b12b9SGreg Kurz char *nodename; 3745345b12b9SGreg Kurz int offset; 3746345b12b9SGreg Kurz 3747345b12b9SGreg Kurz nodename = g_strdup_printf("%s@%x", dc->fw_name, id); 3748345b12b9SGreg Kurz offset = fdt_add_subnode(fdt, 0, nodename); 3749345b12b9SGreg Kurz g_free(nodename); 3750345b12b9SGreg Kurz 375191335a5eSDavid Gibson spapr_dt_cpu(cs, fdt, offset, spapr); 3752345b12b9SGreg Kurz 3753345b12b9SGreg Kurz *fdt_start_offset = offset; 3754345b12b9SGreg Kurz return 0; 3755345b12b9SGreg Kurz } 3756345b12b9SGreg Kurz 3757ff9006ddSIgor Mammedov static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3758ff9006ddSIgor Mammedov Error **errp) 3759ff9006ddSIgor Mammedov { 3760ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3761ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(spapr); 3762ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 3763ce2918cbSDavid Gibson SpaprCpuCore *core = SPAPR_CPU_CORE(OBJECT(dev)); 3764ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3765345b12b9SGreg Kurz CPUState *cs; 3766ce2918cbSDavid Gibson SpaprDrc *drc; 3767535455fdSIgor Mammedov CPUArchId *core_slot; 3768535455fdSIgor Mammedov int index; 376994fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 3770b1e81567SGreg Kurz int i; 3771ff9006ddSIgor Mammedov 3772535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 3773535455fdSIgor Mammedov if (!core_slot) { 3774535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 3775535455fdSIgor Mammedov cc->core_id); 3776535455fdSIgor Mammedov return; 3777535455fdSIgor Mammedov } 37785d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 37795d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 3780ff9006ddSIgor Mammedov 3781c5514d0eSIgor Mammedov g_assert(drc || !mc->has_hotpluggable_cpus); 3782ff9006ddSIgor Mammedov 3783e49c63d5SGreg Kurz if (drc) { 3784*17548fe6SGreg Kurz if (!spapr_drc_attach(drc, dev, errp)) { 3785ff9006ddSIgor Mammedov return; 3786ff9006ddSIgor Mammedov } 3787ff9006ddSIgor Mammedov 378894fd9cbaSLaurent Vivier if (hotplugged) { 3789ff9006ddSIgor Mammedov /* 379094fd9cbaSLaurent Vivier * Send hotplug notification interrupt to the guest only 379194fd9cbaSLaurent Vivier * in case of hotplugged CPUs. 3792ff9006ddSIgor Mammedov */ 3793ff9006ddSIgor Mammedov spapr_hotplug_req_add_by_index(drc); 379494fd9cbaSLaurent Vivier } else { 379594fd9cbaSLaurent Vivier spapr_drc_reset(drc); 3796ff9006ddSIgor Mammedov } 379794fd9cbaSLaurent Vivier } 379894fd9cbaSLaurent Vivier 3799535455fdSIgor Mammedov core_slot->cpu = OBJECT(dev); 380046f7afa3SGreg Kurz 380146f7afa3SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 380246f7afa3SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 3803bc877283SGreg Kurz cs = CPU(core->threads[i]); 380446f7afa3SGreg Kurz pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index); 380546f7afa3SGreg Kurz } 380646f7afa3SGreg Kurz } 3807b1e81567SGreg Kurz 3808b1e81567SGreg Kurz /* 3809b1e81567SGreg Kurz * Set compatibility mode to match the boot CPU, which was either set 3810b1e81567SGreg Kurz * by the machine reset code or by CAS. 3811b1e81567SGreg Kurz */ 3812b1e81567SGreg Kurz if (hotplugged) { 3813b1e81567SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 3814a3114923SGreg Kurz if (ppc_set_compat(core->threads[i], 3815a3114923SGreg Kurz POWERPC_CPU(first_cpu)->compat_pvr, 3816a3114923SGreg Kurz errp) < 0) { 3817b1e81567SGreg Kurz return; 3818b1e81567SGreg Kurz } 3819b1e81567SGreg Kurz } 3820b1e81567SGreg Kurz } 3821ff9006ddSIgor Mammedov } 3822ff9006ddSIgor Mammedov 3823ff9006ddSIgor Mammedov static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3824ff9006ddSIgor Mammedov Error **errp) 3825ff9006ddSIgor Mammedov { 3826ff9006ddSIgor Mammedov MachineState *machine = MACHINE(OBJECT(hotplug_dev)); 3827ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); 3828ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 38292e9c10ebSIgor Mammedov const char *base_core_type = spapr_get_cpu_core_type(machine->cpu_type); 3830ff9006ddSIgor Mammedov const char *type = object_get_typename(OBJECT(dev)); 3831535455fdSIgor Mammedov CPUArchId *core_slot; 3832535455fdSIgor Mammedov int index; 3833fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 3834ff9006ddSIgor Mammedov 3835c5514d0eSIgor Mammedov if (dev->hotplugged && !mc->has_hotpluggable_cpus) { 3836dcfe4805SMarkus Armbruster error_setg(errp, "CPU hotplug not supported for this machine"); 3837dcfe4805SMarkus Armbruster return; 3838ff9006ddSIgor Mammedov } 3839ff9006ddSIgor Mammedov 3840ff9006ddSIgor Mammedov if (strcmp(base_core_type, type)) { 3841dcfe4805SMarkus Armbruster error_setg(errp, "CPU core type should be %s", base_core_type); 3842dcfe4805SMarkus Armbruster return; 3843ff9006ddSIgor Mammedov } 3844ff9006ddSIgor Mammedov 3845ff9006ddSIgor Mammedov if (cc->core_id % smp_threads) { 3846dcfe4805SMarkus Armbruster error_setg(errp, "invalid core id %d", cc->core_id); 3847dcfe4805SMarkus Armbruster return; 3848ff9006ddSIgor Mammedov } 3849ff9006ddSIgor Mammedov 3850459264efSDavid Gibson /* 3851459264efSDavid Gibson * In general we should have homogeneous threads-per-core, but old 3852459264efSDavid Gibson * (pre hotplug support) machine types allow the last core to have 3853459264efSDavid Gibson * reduced threads as a compatibility hack for when we allowed 3854459264efSDavid Gibson * total vcpus not a multiple of threads-per-core. 3855459264efSDavid Gibson */ 3856459264efSDavid Gibson if (mc->has_hotpluggable_cpus && (cc->nr_threads != smp_threads)) { 3857dcfe4805SMarkus Armbruster error_setg(errp, "invalid nr-threads %d, must be %d", cc->nr_threads, 3858dcfe4805SMarkus Armbruster smp_threads); 3859dcfe4805SMarkus Armbruster return; 38608149e299SDavid Gibson } 38618149e299SDavid Gibson 3862535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 3863535455fdSIgor Mammedov if (!core_slot) { 3864dcfe4805SMarkus Armbruster error_setg(errp, "core id %d out of range", cc->core_id); 3865dcfe4805SMarkus Armbruster return; 3866ff9006ddSIgor Mammedov } 3867ff9006ddSIgor Mammedov 3868535455fdSIgor Mammedov if (core_slot->cpu) { 3869dcfe4805SMarkus Armbruster error_setg(errp, "core %d already populated", cc->core_id); 3870dcfe4805SMarkus Armbruster return; 3871ff9006ddSIgor Mammedov } 3872ff9006ddSIgor Mammedov 3873dcfe4805SMarkus Armbruster numa_cpu_pre_plug(core_slot, dev, errp); 3874ff9006ddSIgor Mammedov } 3875ff9006ddSIgor Mammedov 3876ce2918cbSDavid Gibson int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 3877bb2bdd81SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 3878bb2bdd81SGreg Kurz { 3879ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(drc->dev); 3880bb2bdd81SGreg Kurz int intc_phandle; 3881bb2bdd81SGreg Kurz 3882bb2bdd81SGreg Kurz intc_phandle = spapr_irq_get_phandle(spapr, spapr->fdt_blob, errp); 3883bb2bdd81SGreg Kurz if (intc_phandle <= 0) { 3884bb2bdd81SGreg Kurz return -1; 3885bb2bdd81SGreg Kurz } 3886bb2bdd81SGreg Kurz 38878cbe71ecSDavid Gibson if (spapr_dt_phb(spapr, sphb, intc_phandle, fdt, fdt_start_offset)) { 3888bb2bdd81SGreg Kurz error_setg(errp, "unable to create FDT node for PHB %d", sphb->index); 3889bb2bdd81SGreg Kurz return -1; 3890bb2bdd81SGreg Kurz } 3891bb2bdd81SGreg Kurz 3892bb2bdd81SGreg Kurz /* generally SLOF creates these, for hotplug it's up to QEMU */ 3893bb2bdd81SGreg Kurz _FDT(fdt_setprop_string(fdt, *fdt_start_offset, "name", "pci")); 3894bb2bdd81SGreg Kurz 3895bb2bdd81SGreg Kurz return 0; 3896bb2bdd81SGreg Kurz } 3897bb2bdd81SGreg Kurz 3898bb2bdd81SGreg Kurz static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3899bb2bdd81SGreg Kurz Error **errp) 3900bb2bdd81SGreg Kurz { 3901ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3902ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 3903ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 3904bb2bdd81SGreg Kurz const unsigned windows_supported = spapr_phb_windows_supported(sphb); 3905bb2bdd81SGreg Kurz 3906bb2bdd81SGreg Kurz if (dev->hotplugged && !smc->dr_phb_enabled) { 3907bb2bdd81SGreg Kurz error_setg(errp, "PHB hotplug not supported for this machine"); 3908bb2bdd81SGreg Kurz return; 3909bb2bdd81SGreg Kurz } 3910bb2bdd81SGreg Kurz 3911bb2bdd81SGreg Kurz if (sphb->index == (uint32_t)-1) { 3912bb2bdd81SGreg Kurz error_setg(errp, "\"index\" for PAPR PHB is mandatory"); 3913bb2bdd81SGreg Kurz return; 3914bb2bdd81SGreg Kurz } 3915bb2bdd81SGreg Kurz 3916bb2bdd81SGreg Kurz /* 3917bb2bdd81SGreg Kurz * This will check that sphb->index doesn't exceed the maximum number of 3918bb2bdd81SGreg Kurz * PHBs for the current machine type. 3919bb2bdd81SGreg Kurz */ 3920bb2bdd81SGreg Kurz smc->phb_placement(spapr, sphb->index, 3921bb2bdd81SGreg Kurz &sphb->buid, &sphb->io_win_addr, 3922bb2bdd81SGreg Kurz &sphb->mem_win_addr, &sphb->mem64_win_addr, 3923ec132efaSAlexey Kardashevskiy windows_supported, sphb->dma_liobn, 3924ec132efaSAlexey Kardashevskiy &sphb->nv2_gpa_win_addr, &sphb->nv2_atsd_win_addr, 3925ec132efaSAlexey Kardashevskiy errp); 3926bb2bdd81SGreg Kurz } 3927bb2bdd81SGreg Kurz 3928bb2bdd81SGreg Kurz static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3929bb2bdd81SGreg Kurz Error **errp) 3930bb2bdd81SGreg Kurz { 3931ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3932ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 3933ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 3934ce2918cbSDavid Gibson SpaprDrc *drc; 3935bb2bdd81SGreg Kurz bool hotplugged = spapr_drc_hotplugged(dev); 3936bb2bdd81SGreg Kurz 3937bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) { 3938bb2bdd81SGreg Kurz return; 3939bb2bdd81SGreg Kurz } 3940bb2bdd81SGreg Kurz 3941bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); 3942bb2bdd81SGreg Kurz /* hotplug hooks should check it's enabled before getting this far */ 3943bb2bdd81SGreg Kurz assert(drc); 3944bb2bdd81SGreg Kurz 3945*17548fe6SGreg Kurz if (!spapr_drc_attach(drc, dev, errp)) { 3946bb2bdd81SGreg Kurz return; 3947bb2bdd81SGreg Kurz } 3948bb2bdd81SGreg Kurz 3949bb2bdd81SGreg Kurz if (hotplugged) { 3950bb2bdd81SGreg Kurz spapr_hotplug_req_add_by_index(drc); 3951bb2bdd81SGreg Kurz } else { 3952bb2bdd81SGreg Kurz spapr_drc_reset(drc); 3953bb2bdd81SGreg Kurz } 3954bb2bdd81SGreg Kurz } 3955bb2bdd81SGreg Kurz 3956bb2bdd81SGreg Kurz void spapr_phb_release(DeviceState *dev) 3957bb2bdd81SGreg Kurz { 3958bb2bdd81SGreg Kurz HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3959bb2bdd81SGreg Kurz 3960bb2bdd81SGreg Kurz hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 396107578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 3962bb2bdd81SGreg Kurz } 3963bb2bdd81SGreg Kurz 3964bb2bdd81SGreg Kurz static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 3965bb2bdd81SGreg Kurz { 3966981c3dcdSMarkus Armbruster qdev_unrealize(dev); 3967bb2bdd81SGreg Kurz } 3968bb2bdd81SGreg Kurz 3969bb2bdd81SGreg Kurz static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev, 3970bb2bdd81SGreg Kurz DeviceState *dev, Error **errp) 3971bb2bdd81SGreg Kurz { 3972ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 3973ce2918cbSDavid Gibson SpaprDrc *drc; 3974bb2bdd81SGreg Kurz 3975bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); 3976bb2bdd81SGreg Kurz assert(drc); 3977bb2bdd81SGreg Kurz 3978bb2bdd81SGreg Kurz if (!spapr_drc_unplug_requested(drc)) { 3979bb2bdd81SGreg Kurz spapr_drc_detach(drc); 3980bb2bdd81SGreg Kurz spapr_hotplug_req_remove_by_index(drc); 3981bb2bdd81SGreg Kurz } 3982bb2bdd81SGreg Kurz } 3983bb2bdd81SGreg Kurz 39840fb6bd07SMichael Roth static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 39850fb6bd07SMichael Roth Error **errp) 39860fb6bd07SMichael Roth { 39870fb6bd07SMichael Roth SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 39880fb6bd07SMichael Roth SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(dev); 39890fb6bd07SMichael Roth 39900fb6bd07SMichael Roth if (spapr->tpm_proxy != NULL) { 39910fb6bd07SMichael Roth error_setg(errp, "Only one TPM proxy can be specified for this machine"); 39920fb6bd07SMichael Roth return; 39930fb6bd07SMichael Roth } 39940fb6bd07SMichael Roth 39950fb6bd07SMichael Roth spapr->tpm_proxy = tpm_proxy; 39960fb6bd07SMichael Roth } 39970fb6bd07SMichael Roth 39980fb6bd07SMichael Roth static void spapr_tpm_proxy_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 39990fb6bd07SMichael Roth { 40000fb6bd07SMichael Roth SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 40010fb6bd07SMichael Roth 4002981c3dcdSMarkus Armbruster qdev_unrealize(dev); 40030fb6bd07SMichael Roth object_unparent(OBJECT(dev)); 40040fb6bd07SMichael Roth spapr->tpm_proxy = NULL; 40050fb6bd07SMichael Roth } 40060fb6bd07SMichael Roth 4007c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, 4008c20d332aSBharata B Rao DeviceState *dev, Error **errp) 4009c20d332aSBharata B Rao { 4010c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 401181985f3bSDavid Hildenbrand spapr_memory_plug(hotplug_dev, dev, errp); 4012af81cf32SBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4013af81cf32SBharata B Rao spapr_core_plug(hotplug_dev, dev, errp); 4014bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4015bb2bdd81SGreg Kurz spapr_phb_plug(hotplug_dev, dev, errp); 40160fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 40170fb6bd07SMichael Roth spapr_tpm_proxy_plug(hotplug_dev, dev, errp); 4018c20d332aSBharata B Rao } 4019c20d332aSBharata B Rao } 4020c20d332aSBharata B Rao 402188432f44SDavid Hildenbrand static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, 402288432f44SDavid Hildenbrand DeviceState *dev, Error **errp) 402388432f44SDavid Hildenbrand { 40243ec71474SDavid Hildenbrand if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 40253ec71474SDavid Hildenbrand spapr_memory_unplug(hotplug_dev, dev); 4026a4261be1SDavid Hildenbrand } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4027a4261be1SDavid Hildenbrand spapr_core_unplug(hotplug_dev, dev); 4028bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4029bb2bdd81SGreg Kurz spapr_phb_unplug(hotplug_dev, dev); 40300fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 40310fb6bd07SMichael Roth spapr_tpm_proxy_unplug(hotplug_dev, dev); 40323ec71474SDavid Hildenbrand } 403388432f44SDavid Hildenbrand } 403488432f44SDavid Hildenbrand 4035cf632463SBharata B Rao static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev, 4036cf632463SBharata B Rao DeviceState *dev, Error **errp) 4037cf632463SBharata B Rao { 4038ce2918cbSDavid Gibson SpaprMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev)); 4039c86c1affSDaniel Henrique Barboza MachineClass *mc = MACHINE_GET_CLASS(sms); 4040ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4041cf632463SBharata B Rao 4042cf632463SBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 4043cf632463SBharata B Rao if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) { 4044cf632463SBharata B Rao spapr_memory_unplug_request(hotplug_dev, dev, errp); 4045cf632463SBharata B Rao } else { 4046cf632463SBharata B Rao /* NOTE: this means there is a window after guest reset, prior to 4047cf632463SBharata B Rao * CAS negotiation, where unplug requests will fail due to the 4048cf632463SBharata B Rao * capability not being detected yet. This is a bit different than 4049cf632463SBharata B Rao * the case with PCI unplug, where the events will be queued and 4050cf632463SBharata B Rao * eventually handled by the guest after boot 4051cf632463SBharata B Rao */ 4052cf632463SBharata B Rao error_setg(errp, "Memory hot unplug not supported for this guest"); 4053cf632463SBharata B Rao } 40546f4b5c3eSBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4055c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 40566f4b5c3eSBharata B Rao error_setg(errp, "CPU hot unplug not supported on this machine"); 40576f4b5c3eSBharata B Rao return; 40586f4b5c3eSBharata B Rao } 4059115debf2SIgor Mammedov spapr_core_unplug_request(hotplug_dev, dev, errp); 4060bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4061bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) { 4062bb2bdd81SGreg Kurz error_setg(errp, "PHB hot unplug not supported on this machine"); 4063bb2bdd81SGreg Kurz return; 4064bb2bdd81SGreg Kurz } 4065bb2bdd81SGreg Kurz spapr_phb_unplug_request(hotplug_dev, dev, errp); 40660fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 40670fb6bd07SMichael Roth spapr_tpm_proxy_unplug(hotplug_dev, dev); 4068c20d332aSBharata B Rao } 4069c20d332aSBharata B Rao } 4070c20d332aSBharata B Rao 407194a94e4cSBharata B Rao static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, 407294a94e4cSBharata B Rao DeviceState *dev, Error **errp) 407394a94e4cSBharata B Rao { 4074c871bc70SLaurent Vivier if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 4075c871bc70SLaurent Vivier spapr_memory_pre_plug(hotplug_dev, dev, errp); 4076c871bc70SLaurent Vivier } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 407794a94e4cSBharata B Rao spapr_core_pre_plug(hotplug_dev, dev, errp); 4078bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4079bb2bdd81SGreg Kurz spapr_phb_pre_plug(hotplug_dev, dev, errp); 408094a94e4cSBharata B Rao } 408194a94e4cSBharata B Rao } 408294a94e4cSBharata B Rao 40837ebaf795SBharata B Rao static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine, 4084c20d332aSBharata B Rao DeviceState *dev) 4085c20d332aSBharata B Rao { 408694a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || 4087bb2bdd81SGreg Kurz object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE) || 40880fb6bd07SMichael Roth object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE) || 40890fb6bd07SMichael Roth object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 4090c20d332aSBharata B Rao return HOTPLUG_HANDLER(machine); 4091c20d332aSBharata B Rao } 4092cb600087SDavid Gibson if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { 4093cb600087SDavid Gibson PCIDevice *pcidev = PCI_DEVICE(dev); 4094cb600087SDavid Gibson PCIBus *root = pci_device_root_bus(pcidev); 4095cb600087SDavid Gibson SpaprPhbState *phb = 4096cb600087SDavid Gibson (SpaprPhbState *)object_dynamic_cast(OBJECT(BUS(root)->parent), 4097cb600087SDavid Gibson TYPE_SPAPR_PCI_HOST_BRIDGE); 4098cb600087SDavid Gibson 4099cb600087SDavid Gibson if (phb) { 4100cb600087SDavid Gibson return HOTPLUG_HANDLER(phb); 4101cb600087SDavid Gibson } 4102cb600087SDavid Gibson } 4103c20d332aSBharata B Rao return NULL; 4104c20d332aSBharata B Rao } 4105c20d332aSBharata B Rao 4106ea089eebSIgor Mammedov static CpuInstanceProperties 4107ea089eebSIgor Mammedov spapr_cpu_index_to_props(MachineState *machine, unsigned cpu_index) 410820bb648dSDavid Gibson { 4109ea089eebSIgor Mammedov CPUArchId *core_slot; 4110ea089eebSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 4111ea089eebSIgor Mammedov 4112ea089eebSIgor Mammedov /* make sure possible_cpu are intialized */ 4113ea089eebSIgor Mammedov mc->possible_cpu_arch_ids(machine); 4114ea089eebSIgor Mammedov /* get CPU core slot containing thread that matches cpu_index */ 4115ea089eebSIgor Mammedov core_slot = spapr_find_cpu_slot(machine, cpu_index, NULL); 4116ea089eebSIgor Mammedov assert(core_slot); 4117ea089eebSIgor Mammedov return core_slot->props; 411820bb648dSDavid Gibson } 411920bb648dSDavid Gibson 412079e07936SIgor Mammedov static int64_t spapr_get_default_cpu_node_id(const MachineState *ms, int idx) 412179e07936SIgor Mammedov { 4122aa570207STao Xu return idx / ms->smp.cores % ms->numa_state->num_nodes; 412379e07936SIgor Mammedov } 412479e07936SIgor Mammedov 4125535455fdSIgor Mammedov static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine) 4126535455fdSIgor Mammedov { 4127535455fdSIgor Mammedov int i; 4128fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 4129fe6b6346SLike Xu unsigned int smp_cpus = machine->smp.cpus; 4130d342eb76SIgor Mammedov const char *core_type; 4131fe6b6346SLike Xu int spapr_max_cores = machine->smp.max_cpus / smp_threads; 4132535455fdSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 4133535455fdSIgor Mammedov 4134c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 4135535455fdSIgor Mammedov spapr_max_cores = QEMU_ALIGN_UP(smp_cpus, smp_threads) / smp_threads; 4136535455fdSIgor Mammedov } 4137535455fdSIgor Mammedov if (machine->possible_cpus) { 4138535455fdSIgor Mammedov assert(machine->possible_cpus->len == spapr_max_cores); 4139535455fdSIgor Mammedov return machine->possible_cpus; 4140535455fdSIgor Mammedov } 4141535455fdSIgor Mammedov 4142d342eb76SIgor Mammedov core_type = spapr_get_cpu_core_type(machine->cpu_type); 4143d342eb76SIgor Mammedov if (!core_type) { 4144d342eb76SIgor Mammedov error_report("Unable to find sPAPR CPU Core definition"); 4145d342eb76SIgor Mammedov exit(1); 4146d342eb76SIgor Mammedov } 4147d342eb76SIgor Mammedov 4148535455fdSIgor Mammedov machine->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + 4149535455fdSIgor Mammedov sizeof(CPUArchId) * spapr_max_cores); 4150535455fdSIgor Mammedov machine->possible_cpus->len = spapr_max_cores; 4151535455fdSIgor Mammedov for (i = 0; i < machine->possible_cpus->len; i++) { 4152535455fdSIgor Mammedov int core_id = i * smp_threads; 4153535455fdSIgor Mammedov 4154d342eb76SIgor Mammedov machine->possible_cpus->cpus[i].type = core_type; 4155f2d672c2SIgor Mammedov machine->possible_cpus->cpus[i].vcpus_count = smp_threads; 4156535455fdSIgor Mammedov machine->possible_cpus->cpus[i].arch_id = core_id; 4157535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.has_core_id = true; 4158535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.core_id = core_id; 4159535455fdSIgor Mammedov } 4160535455fdSIgor Mammedov return machine->possible_cpus; 4161535455fdSIgor Mammedov } 4162535455fdSIgor Mammedov 4163ce2918cbSDavid Gibson static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index, 4164daa23699SDavid Gibson uint64_t *buid, hwaddr *pio, 4165daa23699SDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 4166ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4167ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 41686737d9adSDavid Gibson { 4169357d1e3bSDavid Gibson /* 4170357d1e3bSDavid Gibson * New-style PHB window placement. 4171357d1e3bSDavid Gibson * 4172357d1e3bSDavid Gibson * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window 4173357d1e3bSDavid Gibson * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO 4174357d1e3bSDavid Gibson * windows. 4175357d1e3bSDavid Gibson * 4176357d1e3bSDavid Gibson * Some guest kernels can't work with MMIO windows above 1<<46 4177357d1e3bSDavid Gibson * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB 4178357d1e3bSDavid Gibson * 4179357d1e3bSDavid Gibson * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each 4180357d1e3bSDavid Gibson * PHB stacked together. (32TiB+2GiB)..(32TiB+64GiB) contains the 4181357d1e3bSDavid Gibson * 2GiB 32-bit MMIO windows for each PHB. Then 33..64TiB has the 4182357d1e3bSDavid Gibson * 1TiB 64-bit MMIO windows for each PHB. 4183357d1e3bSDavid Gibson */ 41846737d9adSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 41856737d9adSDavid Gibson int i; 41866737d9adSDavid Gibson 4187357d1e3bSDavid Gibson /* Sanity check natural alignments */ 4188357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 4189357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 4190357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0); 4191357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0); 4192357d1e3bSDavid Gibson /* Sanity check bounds */ 419325e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_IO_WIN_SIZE) > 419425e6a118SMichael S. Tsirkin SPAPR_PCI_MEM32_WIN_SIZE); 419525e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_MEM32_WIN_SIZE) > 419625e6a118SMichael S. Tsirkin SPAPR_PCI_MEM64_WIN_SIZE); 41972efff1c0SDavid Gibson 419825e6a118SMichael S. Tsirkin if (index >= SPAPR_MAX_PHBS) { 419925e6a118SMichael S. Tsirkin error_setg(errp, "\"index\" for PAPR PHB is too large (max %llu)", 420025e6a118SMichael S. Tsirkin SPAPR_MAX_PHBS - 1); 42016737d9adSDavid Gibson return; 42026737d9adSDavid Gibson } 42036737d9adSDavid Gibson 42046737d9adSDavid Gibson *buid = base_buid + index; 42056737d9adSDavid Gibson for (i = 0; i < n_dma; ++i) { 42066737d9adSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 42076737d9adSDavid Gibson } 42086737d9adSDavid Gibson 4209357d1e3bSDavid Gibson *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE; 4210357d1e3bSDavid Gibson *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE; 4211357d1e3bSDavid Gibson *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE; 4212ec132efaSAlexey Kardashevskiy 4213ec132efaSAlexey Kardashevskiy *nv2gpa = SPAPR_PCI_NV2RAM64_WIN_BASE + index * SPAPR_PCI_NV2RAM64_WIN_SIZE; 4214ec132efaSAlexey Kardashevskiy *nv2atsd = SPAPR_PCI_NV2ATSD_WIN_BASE + index * SPAPR_PCI_NV2ATSD_WIN_SIZE; 42156737d9adSDavid Gibson } 42166737d9adSDavid Gibson 42177844e12bSCédric Le Goater static ICSState *spapr_ics_get(XICSFabric *dev, int irq) 42187844e12bSCédric Le Goater { 4219ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(dev); 42207844e12bSCédric Le Goater 42217844e12bSCédric Le Goater return ics_valid_irq(spapr->ics, irq) ? spapr->ics : NULL; 42227844e12bSCédric Le Goater } 42237844e12bSCédric Le Goater 42247844e12bSCédric Le Goater static void spapr_ics_resend(XICSFabric *dev) 42257844e12bSCédric Le Goater { 4226ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(dev); 42277844e12bSCédric Le Goater 42287844e12bSCédric Le Goater ics_resend(spapr->ics); 42297844e12bSCédric Le Goater } 42307844e12bSCédric Le Goater 423181210c20SSam Bobroff static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id) 4232b2fc59aaSCédric Le Goater { 42332e886fb3SSam Bobroff PowerPCCPU *cpu = spapr_find_cpu(vcpu_id); 4234b2fc59aaSCédric Le Goater 4235a28b9a5aSCédric Le Goater return cpu ? spapr_cpu_state(cpu)->icp : NULL; 4236b2fc59aaSCédric Le Goater } 4237b2fc59aaSCédric Le Goater 42386449da45SCédric Le Goater static void spapr_pic_print_info(InterruptStatsProvider *obj, 42396449da45SCédric Le Goater Monitor *mon) 42406449da45SCédric Le Goater { 4241ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 42426449da45SCédric Le Goater 4243328d8eb2SDavid Gibson spapr_irq_print_info(spapr, mon); 4244f041d6afSGreg Kurz monitor_printf(mon, "irqchip: %s\n", 4245f041d6afSGreg Kurz kvm_irqchip_in_kernel() ? "in-kernel" : "emulated"); 42466449da45SCédric Le Goater } 42476449da45SCédric Le Goater 4248baa45b17SCédric Le Goater /* 4249baa45b17SCédric Le Goater * This is a XIVE only operation 4250baa45b17SCédric Le Goater */ 4251932de7aeSCédric Le Goater static int spapr_match_nvt(XiveFabric *xfb, uint8_t format, 4252932de7aeSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 4253932de7aeSCédric Le Goater bool cam_ignore, uint8_t priority, 4254932de7aeSCédric Le Goater uint32_t logic_serv, XiveTCTXMatch *match) 4255932de7aeSCédric Le Goater { 4256932de7aeSCédric Le Goater SpaprMachineState *spapr = SPAPR_MACHINE(xfb); 4257baa45b17SCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(spapr->active_intc); 4258932de7aeSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 4259932de7aeSCédric Le Goater int count; 4260932de7aeSCédric Le Goater 4261932de7aeSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 4262932de7aeSCédric Le Goater priority, logic_serv, match); 4263932de7aeSCédric Le Goater if (count < 0) { 4264932de7aeSCédric Le Goater return count; 4265932de7aeSCédric Le Goater } 4266932de7aeSCédric Le Goater 4267932de7aeSCédric Le Goater /* 4268932de7aeSCédric Le Goater * When we implement the save and restore of the thread interrupt 4269932de7aeSCédric Le Goater * contexts in the enter/exit CPU handlers of the machine and the 4270932de7aeSCédric Le Goater * escalations in QEMU, we should be able to handle non dispatched 4271932de7aeSCédric Le Goater * vCPUs. 4272932de7aeSCédric Le Goater * 4273932de7aeSCédric Le Goater * Until this is done, the sPAPR machine should find at least one 4274932de7aeSCédric Le Goater * matching context always. 4275932de7aeSCédric Le Goater */ 4276932de7aeSCédric Le Goater if (count == 0) { 4277932de7aeSCédric Le Goater qemu_log_mask(LOG_GUEST_ERROR, "XIVE: NVT %x/%x is not dispatched\n", 4278932de7aeSCédric Le Goater nvt_blk, nvt_idx); 4279932de7aeSCédric Le Goater } 4280932de7aeSCédric Le Goater 4281932de7aeSCédric Le Goater return count; 4282932de7aeSCédric Le Goater } 4283932de7aeSCédric Le Goater 428414bb4486SGreg Kurz int spapr_get_vcpu_id(PowerPCCPU *cpu) 42852e886fb3SSam Bobroff { 4286b1a568c1SGreg Kurz return cpu->vcpu_id; 42872e886fb3SSam Bobroff } 42882e886fb3SSam Bobroff 4289648edb64SGreg Kurz void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp) 4290648edb64SGreg Kurz { 4291ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 4292fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 4293648edb64SGreg Kurz int vcpu_id; 4294648edb64SGreg Kurz 42955d0fb150SGreg Kurz vcpu_id = spapr_vcpu_id(spapr, cpu_index); 4296648edb64SGreg Kurz 4297648edb64SGreg Kurz if (kvm_enabled() && !kvm_vcpu_id_is_valid(vcpu_id)) { 4298648edb64SGreg Kurz error_setg(errp, "Can't create CPU with id %d in KVM", vcpu_id); 4299648edb64SGreg Kurz error_append_hint(errp, "Adjust the number of cpus to %d " 4300648edb64SGreg Kurz "or try to raise the number of threads per core\n", 4301fe6b6346SLike Xu vcpu_id * ms->smp.threads / spapr->vsmt); 4302648edb64SGreg Kurz return; 4303648edb64SGreg Kurz } 4304648edb64SGreg Kurz 4305648edb64SGreg Kurz cpu->vcpu_id = vcpu_id; 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 /* 45113ff3c5d3SCornelia Huck * pseries-5.2 45123eb74d20SCornelia Huck */ 45133ff3c5d3SCornelia Huck static void spapr_machine_5_2_class_options(MachineClass *mc) 45143eb74d20SCornelia Huck { 45153eb74d20SCornelia Huck /* Defaults for the latest behaviour inherited from the base class */ 45163eb74d20SCornelia Huck } 45173eb74d20SCornelia Huck 45183ff3c5d3SCornelia Huck DEFINE_SPAPR_MACHINE(5_2, "5.2", true); 45193ff3c5d3SCornelia Huck 45203ff3c5d3SCornelia Huck /* 45213ff3c5d3SCornelia Huck * pseries-5.1 45223ff3c5d3SCornelia Huck */ 45233ff3c5d3SCornelia Huck static void spapr_machine_5_1_class_options(MachineClass *mc) 45243ff3c5d3SCornelia Huck { 45253ff3c5d3SCornelia Huck spapr_machine_5_2_class_options(mc); 45263ff3c5d3SCornelia Huck compat_props_add(mc->compat_props, hw_compat_5_1, hw_compat_5_1_len); 45273ff3c5d3SCornelia Huck } 45283ff3c5d3SCornelia Huck 45293ff3c5d3SCornelia Huck DEFINE_SPAPR_MACHINE(5_1, "5.1", false); 4530541aaa1dSCornelia Huck 4531541aaa1dSCornelia Huck /* 4532541aaa1dSCornelia Huck * pseries-5.0 4533541aaa1dSCornelia Huck */ 4534541aaa1dSCornelia Huck static void spapr_machine_5_0_class_options(MachineClass *mc) 4535541aaa1dSCornelia Huck { 4536a6030d7eSReza Arbab SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4537a6030d7eSReza Arbab static GlobalProperty compat[] = { 4538a6030d7eSReza Arbab { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-5.1-associativity", "on" }, 4539a6030d7eSReza Arbab }; 4540a6030d7eSReza Arbab 4541541aaa1dSCornelia Huck spapr_machine_5_1_class_options(mc); 4542541aaa1dSCornelia Huck compat_props_add(mc->compat_props, hw_compat_5_0, hw_compat_5_0_len); 4543a6030d7eSReza Arbab compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 454432a354dcSIgor Mammedov mc->numa_mem_supported = true; 4545a6030d7eSReza Arbab smc->pre_5_1_assoc_refpoints = true; 4546541aaa1dSCornelia Huck } 4547541aaa1dSCornelia Huck 4548541aaa1dSCornelia Huck DEFINE_SPAPR_MACHINE(5_0, "5.0", false); 45493eb74d20SCornelia Huck 45503eb74d20SCornelia Huck /* 45519aec2e52SCornelia Huck * pseries-4.2 4552e2676b16SGreg Kurz */ 45539aec2e52SCornelia Huck static void spapr_machine_4_2_class_options(MachineClass *mc) 4554e2676b16SGreg Kurz { 455537965dfeSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 455637965dfeSDavid Gibson 45573eb74d20SCornelia Huck spapr_machine_5_0_class_options(mc); 45585f258577SEvgeny Yakovlev compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len); 455937965dfeSDavid Gibson smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF; 45608af7e1feSNicholas Piggin smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_OFF; 45611052ab67SDavid Gibson smc->rma_limit = 16 * GiB; 4562ee3a71e3SShivaprasad G Bhat mc->nvdimm_supported = false; 4563e2676b16SGreg Kurz } 4564e2676b16SGreg Kurz 45653eb74d20SCornelia Huck DEFINE_SPAPR_MACHINE(4_2, "4.2", false); 45669aec2e52SCornelia Huck 45679aec2e52SCornelia Huck /* 45689aec2e52SCornelia Huck * pseries-4.1 45699aec2e52SCornelia Huck */ 45709aec2e52SCornelia Huck static void spapr_machine_4_1_class_options(MachineClass *mc) 45719aec2e52SCornelia Huck { 45726c3829a2SAlexey Kardashevskiy SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4573d15d4ad6SDavid Gibson static GlobalProperty compat[] = { 4574d15d4ad6SDavid Gibson /* Only allow 4kiB and 64kiB IOMMU pagesizes */ 4575d15d4ad6SDavid Gibson { TYPE_SPAPR_PCI_HOST_BRIDGE, "pgsz", "0x11000" }, 4576d15d4ad6SDavid Gibson }; 4577d15d4ad6SDavid Gibson 45789aec2e52SCornelia Huck spapr_machine_4_2_class_options(mc); 45796c3829a2SAlexey Kardashevskiy smc->linux_pci_probe = false; 458029cb4187SGreg Kurz smc->smp_threads_vsmt = false; 45819aec2e52SCornelia Huck compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len); 4582d15d4ad6SDavid Gibson compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 45839aec2e52SCornelia Huck } 45849aec2e52SCornelia Huck 45859aec2e52SCornelia Huck DEFINE_SPAPR_MACHINE(4_1, "4.1", false); 45869bf2650bSCornelia Huck 45879bf2650bSCornelia Huck /* 45889bf2650bSCornelia Huck * pseries-4.0 45899bf2650bSCornelia Huck */ 4590eb3cba82SDavid Gibson static void phb_placement_4_0(SpaprMachineState *spapr, uint32_t index, 4591ec132efaSAlexey Kardashevskiy uint64_t *buid, hwaddr *pio, 4592ec132efaSAlexey Kardashevskiy hwaddr *mmio32, hwaddr *mmio64, 4593ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4594ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 4595ec132efaSAlexey Kardashevskiy { 4596ec132efaSAlexey Kardashevskiy spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma, liobns, 4597ec132efaSAlexey Kardashevskiy nv2gpa, nv2atsd, errp); 4598ec132efaSAlexey Kardashevskiy *nv2gpa = 0; 4599ec132efaSAlexey Kardashevskiy *nv2atsd = 0; 4600ec132efaSAlexey Kardashevskiy } 4601ec132efaSAlexey Kardashevskiy 4602eb3cba82SDavid Gibson static void spapr_machine_4_0_class_options(MachineClass *mc) 4603eb3cba82SDavid Gibson { 4604eb3cba82SDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4605eb3cba82SDavid Gibson 4606eb3cba82SDavid Gibson spapr_machine_4_1_class_options(mc); 4607eb3cba82SDavid Gibson compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); 4608eb3cba82SDavid Gibson smc->phb_placement = phb_placement_4_0; 4609bd94bc06SCédric Le Goater smc->irq = &spapr_irq_xics; 46103725ef1aSGreg Kurz smc->pre_4_1_migration = true; 4611eb3cba82SDavid Gibson } 4612eb3cba82SDavid Gibson 4613eb3cba82SDavid Gibson DEFINE_SPAPR_MACHINE(4_0, "4.0", false); 4614eb3cba82SDavid Gibson 4615eb3cba82SDavid Gibson /* 4616eb3cba82SDavid Gibson * pseries-3.1 4617eb3cba82SDavid Gibson */ 461888cbe073SMarc-André Lureau static void spapr_machine_3_1_class_options(MachineClass *mc) 461988cbe073SMarc-André Lureau { 4620ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4621fea35ca4SAlexey Kardashevskiy 462284e060bfSAlex Williamson spapr_machine_4_0_class_options(mc); 4623abd93cc7SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len); 462427461d69SPrasad J Pandit 462534a6b015SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 4626fea35ca4SAlexey Kardashevskiy smc->update_dt_enabled = false; 4627dae5e39aSMichael Roth smc->dr_phb_enabled = false; 46280a794529SDavid Gibson smc->broken_host_serial_model = true; 46292782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN; 46302782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN; 46312782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN; 4632edaa7995SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF; 463384e060bfSAlex Williamson } 463484e060bfSAlex Williamson 463584e060bfSAlex Williamson DEFINE_SPAPR_MACHINE(3_1, "3.1", false); 4636d45360d9SCédric Le Goater 4637d45360d9SCédric Le Goater /* 4638d45360d9SCédric Le Goater * pseries-3.0 4639d45360d9SCédric Le Goater */ 4640d45360d9SCédric Le Goater 4641d45360d9SCédric Le Goater static void spapr_machine_3_0_class_options(MachineClass *mc) 4642d45360d9SCédric Le Goater { 4643ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 464482cffa2eSCédric Le Goater 4645d45360d9SCédric Le Goater spapr_machine_3_1_class_options(mc); 4646ddb3235dSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len); 464782cffa2eSCédric Le Goater 464882cffa2eSCédric Le Goater smc->legacy_irq_allocation = true; 464954255c1fSDavid Gibson smc->nr_xirqs = 0x400; 4650ae837402SCédric Le Goater smc->irq = &spapr_irq_xics_legacy; 4651d45360d9SCédric Le Goater } 4652d45360d9SCédric Le Goater 4653d45360d9SCédric Le Goater DEFINE_SPAPR_MACHINE(3_0, "3.0", false); 46548a4fd427SDavid Gibson 46558a4fd427SDavid Gibson /* 46568a4fd427SDavid Gibson * pseries-2.12 46578a4fd427SDavid Gibson */ 465888cbe073SMarc-André Lureau static void spapr_machine_2_12_class_options(MachineClass *mc) 465988cbe073SMarc-André Lureau { 4660ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 466188cbe073SMarc-André Lureau static GlobalProperty compat[] = { 46626c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-3.0-migration", "on" }, 46636c36bddfSEduardo Habkost { TYPE_SPAPR_CPU_CORE, "pre-3.0-migration", "on" }, 4664fa386d98SMarc-André Lureau }; 46658a4fd427SDavid Gibson 4666d8c0c7afSPeter Maydell spapr_machine_3_0_class_options(mc); 46670d47310bSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_12, hw_compat_2_12_len); 466888cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 46692309832aSDavid Gibson 4670e8937295SGreg Kurz /* We depend on kvm_enabled() to choose a default value for the 4671e8937295SGreg Kurz * hpt-max-page-size capability. Of course we can't do it here 4672e8937295SGreg Kurz * because this is too early and the HW accelerator isn't initialzed 4673e8937295SGreg Kurz * yet. Postpone this to machine init (see default_caps_with_cpu()). 4674e8937295SGreg Kurz */ 4675e8937295SGreg Kurz smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 0; 46768a4fd427SDavid Gibson } 46778a4fd427SDavid Gibson 46788a4fd427SDavid Gibson DEFINE_SPAPR_MACHINE(2_12, "2.12", false); 46792b615412SDavid Gibson 4680813f3cf6SSuraj Jitindar Singh static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc) 4681813f3cf6SSuraj Jitindar Singh { 4682ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4683813f3cf6SSuraj Jitindar Singh 4684813f3cf6SSuraj Jitindar Singh spapr_machine_2_12_class_options(mc); 4685813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND; 4686813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND; 4687813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_FIXED_CCD; 4688813f3cf6SSuraj Jitindar Singh } 4689813f3cf6SSuraj Jitindar Singh 4690813f3cf6SSuraj Jitindar Singh DEFINE_SPAPR_MACHINE(2_12_sxxm, "2.12-sxxm", false); 4691813f3cf6SSuraj Jitindar Singh 46922b615412SDavid Gibson /* 46932b615412SDavid Gibson * pseries-2.11 46942b615412SDavid Gibson */ 46952b615412SDavid Gibson 46962b615412SDavid Gibson static void spapr_machine_2_11_class_options(MachineClass *mc) 46972b615412SDavid Gibson { 4698ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4699ee76a09fSDavid Gibson 47002b615412SDavid Gibson spapr_machine_2_12_class_options(mc); 47014e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON; 470243df70a9SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len); 47032b615412SDavid Gibson } 47042b615412SDavid Gibson 47052b615412SDavid Gibson DEFINE_SPAPR_MACHINE(2_11, "2.11", false); 4706e2676b16SGreg Kurz 4707e2676b16SGreg Kurz /* 47083fa14fbeSDavid Gibson * pseries-2.10 4709db800b21SDavid Gibson */ 4710e2676b16SGreg Kurz 47113fa14fbeSDavid Gibson static void spapr_machine_2_10_class_options(MachineClass *mc) 4712db800b21SDavid Gibson { 4713e2676b16SGreg Kurz spapr_machine_2_11_class_options(mc); 4714503224f4SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_10, hw_compat_2_10_len); 4715db800b21SDavid Gibson } 4716db800b21SDavid Gibson 4717e2676b16SGreg Kurz DEFINE_SPAPR_MACHINE(2_10, "2.10", false); 47183fa14fbeSDavid Gibson 47193fa14fbeSDavid Gibson /* 47203fa14fbeSDavid Gibson * pseries-2.9 47213fa14fbeSDavid Gibson */ 472288cbe073SMarc-André Lureau 472388cbe073SMarc-André Lureau static void spapr_machine_2_9_class_options(MachineClass *mc) 472488cbe073SMarc-André Lureau { 4725ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 472688cbe073SMarc-André Lureau static GlobalProperty compat[] = { 47276c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-2.10-migration", "on" }, 4728fa386d98SMarc-André Lureau }; 47293fa14fbeSDavid Gibson 47303fa14fbeSDavid Gibson spapr_machine_2_10_class_options(mc); 47313e803152SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len); 473288cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 473346f7afa3SGreg Kurz smc->pre_2_10_has_unused_icps = true; 473452b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED; 47353fa14fbeSDavid Gibson } 47363fa14fbeSDavid Gibson 47373fa14fbeSDavid Gibson DEFINE_SPAPR_MACHINE(2_9, "2.9", false); 4738fa325e6cSDavid Gibson 4739fa325e6cSDavid Gibson /* 4740fa325e6cSDavid Gibson * pseries-2.8 4741fa325e6cSDavid Gibson */ 474288cbe073SMarc-André Lureau 474388cbe073SMarc-André Lureau static void spapr_machine_2_8_class_options(MachineClass *mc) 474488cbe073SMarc-André Lureau { 474588cbe073SMarc-André Lureau static GlobalProperty compat[] = { 47466c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "pcie-extended-configuration-space", "off" }, 4747fa386d98SMarc-André Lureau }; 4748fa325e6cSDavid Gibson 4749fa325e6cSDavid Gibson spapr_machine_2_9_class_options(mc); 4750edc24ccdSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len); 475188cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 475255641213SLaurent Vivier mc->numa_mem_align_shift = 23; 4753fa325e6cSDavid Gibson } 4754fa325e6cSDavid Gibson 4755fa325e6cSDavid Gibson DEFINE_SPAPR_MACHINE(2_8, "2.8", false); 4756db800b21SDavid Gibson 4757db800b21SDavid Gibson /* 47581ea1eefcSBharata B Rao * pseries-2.7 47591ea1eefcSBharata B Rao */ 4760357d1e3bSDavid Gibson 4761ce2918cbSDavid Gibson static void phb_placement_2_7(SpaprMachineState *spapr, uint32_t index, 4762357d1e3bSDavid Gibson uint64_t *buid, hwaddr *pio, 4763357d1e3bSDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 4764ec132efaSAlexey Kardashevskiy unsigned n_dma, uint32_t *liobns, 4765ec132efaSAlexey Kardashevskiy hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) 4766357d1e3bSDavid Gibson { 4767357d1e3bSDavid Gibson /* Legacy PHB placement for pseries-2.7 and earlier machine types */ 4768357d1e3bSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 4769357d1e3bSDavid Gibson const hwaddr phb_spacing = 0x1000000000ULL; /* 64 GiB */ 4770357d1e3bSDavid Gibson const hwaddr mmio_offset = 0xa0000000; /* 2 GiB + 512 MiB */ 4771357d1e3bSDavid Gibson const hwaddr pio_offset = 0x80000000; /* 2 GiB */ 4772357d1e3bSDavid Gibson const uint32_t max_index = 255; 4773357d1e3bSDavid Gibson const hwaddr phb0_alignment = 0x10000000000ULL; /* 1 TiB */ 4774357d1e3bSDavid Gibson 4775357d1e3bSDavid Gibson uint64_t ram_top = MACHINE(spapr)->ram_size; 4776357d1e3bSDavid Gibson hwaddr phb0_base, phb_base; 4777357d1e3bSDavid Gibson int i; 4778357d1e3bSDavid Gibson 47790c9269a5SDavid Hildenbrand /* Do we have device memory? */ 4780357d1e3bSDavid Gibson if (MACHINE(spapr)->maxram_size > ram_top) { 4781357d1e3bSDavid Gibson /* Can't just use maxram_size, because there may be an 47820c9269a5SDavid Hildenbrand * alignment gap between normal and device memory regions 47830c9269a5SDavid Hildenbrand */ 4784b0c14ec4SDavid Hildenbrand ram_top = MACHINE(spapr)->device_memory->base + 4785b0c14ec4SDavid Hildenbrand memory_region_size(&MACHINE(spapr)->device_memory->mr); 4786357d1e3bSDavid Gibson } 4787357d1e3bSDavid Gibson 4788357d1e3bSDavid Gibson phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment); 4789357d1e3bSDavid Gibson 4790357d1e3bSDavid Gibson if (index > max_index) { 4791357d1e3bSDavid Gibson error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", 4792357d1e3bSDavid Gibson max_index); 4793357d1e3bSDavid Gibson return; 4794357d1e3bSDavid Gibson } 4795357d1e3bSDavid Gibson 4796357d1e3bSDavid Gibson *buid = base_buid + index; 4797357d1e3bSDavid Gibson for (i = 0; i < n_dma; ++i) { 4798357d1e3bSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 4799357d1e3bSDavid Gibson } 4800357d1e3bSDavid Gibson 4801357d1e3bSDavid Gibson phb_base = phb0_base + index * phb_spacing; 4802357d1e3bSDavid Gibson *pio = phb_base + pio_offset; 4803357d1e3bSDavid Gibson *mmio32 = phb_base + mmio_offset; 4804357d1e3bSDavid Gibson /* 4805357d1e3bSDavid Gibson * We don't set the 64-bit MMIO window, relying on the PHB's 4806357d1e3bSDavid Gibson * fallback behaviour of automatically splitting a large "32-bit" 4807357d1e3bSDavid Gibson * window into contiguous 32-bit and 64-bit windows 4808357d1e3bSDavid Gibson */ 4809ec132efaSAlexey Kardashevskiy 4810ec132efaSAlexey Kardashevskiy *nv2gpa = 0; 4811ec132efaSAlexey Kardashevskiy *nv2atsd = 0; 4812357d1e3bSDavid Gibson } 4813db800b21SDavid Gibson 48141ea1eefcSBharata B Rao static void spapr_machine_2_7_class_options(MachineClass *mc) 48151ea1eefcSBharata B Rao { 4816ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 481788cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48186c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0xf80000000", }, 48196c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem64_win_size", "0", }, 48206c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-2.8-migration", "on", }, 48216c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-2.8-migration", "on", }, 482288cbe073SMarc-André Lureau }; 48233daa4a9fSThomas Huth 4824db800b21SDavid Gibson spapr_machine_2_8_class_options(mc); 48252e9c10ebSIgor Mammedov mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power7_v2.3"); 4826a140c199SEduardo Habkost mc->default_machine_opts = "modern-hotplug-events=off"; 48275a995064SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_7, hw_compat_2_7_len); 482888cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 4829357d1e3bSDavid Gibson smc->phb_placement = phb_placement_2_7; 48301ea1eefcSBharata B Rao } 48311ea1eefcSBharata B Rao 4832db800b21SDavid Gibson DEFINE_SPAPR_MACHINE(2_7, "2.7", false); 48331ea1eefcSBharata B Rao 48341ea1eefcSBharata B Rao /* 48354b23699cSDavid Gibson * pseries-2.6 48364b23699cSDavid Gibson */ 483788cbe073SMarc-André Lureau 483888cbe073SMarc-André Lureau static void spapr_machine_2_6_class_options(MachineClass *mc) 483988cbe073SMarc-André Lureau { 484088cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48416c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "ddw", "off" }, 4842fa386d98SMarc-André Lureau }; 48431ea1eefcSBharata B Rao 48441ea1eefcSBharata B Rao spapr_machine_2_7_class_options(mc); 4845c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = false; 4846ff8f261fSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_6, hw_compat_2_6_len); 484788cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 48484b23699cSDavid Gibson } 48494b23699cSDavid Gibson 48501ea1eefcSBharata B Rao DEFINE_SPAPR_MACHINE(2_6, "2.6", false); 48514b23699cSDavid Gibson 48524b23699cSDavid Gibson /* 48531c5f29bbSDavid Gibson * pseries-2.5 48541c5f29bbSDavid Gibson */ 485588cbe073SMarc-André Lureau 485688cbe073SMarc-André Lureau static void spapr_machine_2_5_class_options(MachineClass *mc) 485788cbe073SMarc-André Lureau { 4858ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 485988cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48606c36bddfSEduardo Habkost { "spapr-vlan", "use-rx-buffer-pools", "off" }, 4861fa386d98SMarc-André Lureau }; 48624b23699cSDavid Gibson 48634b23699cSDavid Gibson spapr_machine_2_6_class_options(mc); 486457040d45SThomas Huth smc->use_ohci_by_default = true; 4865fe759610SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_5, hw_compat_2_5_len); 486688cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 48671c5f29bbSDavid Gibson } 48681c5f29bbSDavid Gibson 48694b23699cSDavid Gibson DEFINE_SPAPR_MACHINE(2_5, "2.5", false); 48701c5f29bbSDavid Gibson 48711c5f29bbSDavid Gibson /* 48721c5f29bbSDavid Gibson * pseries-2.4 48731c5f29bbSDavid Gibson */ 487480fd50f9SCornelia Huck 48755013c547SDavid Gibson static void spapr_machine_2_4_class_options(MachineClass *mc) 48765013c547SDavid Gibson { 4877ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4878fc9f38c3SDavid Gibson 4879fc9f38c3SDavid Gibson spapr_machine_2_5_class_options(mc); 4880fc9f38c3SDavid Gibson smc->dr_lmb_enabled = false; 48812f99b9c2SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_4, hw_compat_2_4_len); 48821c5f29bbSDavid Gibson } 48831c5f29bbSDavid Gibson 4884fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_4, "2.4", false); 48851c5f29bbSDavid Gibson 48861c5f29bbSDavid Gibson /* 48871c5f29bbSDavid Gibson * pseries-2.3 48881c5f29bbSDavid Gibson */ 488988cbe073SMarc-André Lureau 489088cbe073SMarc-André Lureau static void spapr_machine_2_3_class_options(MachineClass *mc) 489188cbe073SMarc-André Lureau { 489288cbe073SMarc-André Lureau static GlobalProperty compat[] = { 48936c36bddfSEduardo Habkost { "spapr-pci-host-bridge", "dynamic-reconfiguration", "off" }, 4894fa386d98SMarc-André Lureau }; 4895fc9f38c3SDavid Gibson spapr_machine_2_4_class_options(mc); 48968995dd90SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_3, hw_compat_2_3_len); 489788cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 48981c5f29bbSDavid Gibson } 4899fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_3, "2.3", false); 49001c5f29bbSDavid Gibson 49011c5f29bbSDavid Gibson /* 49021c5f29bbSDavid Gibson * pseries-2.2 49031c5f29bbSDavid Gibson */ 490488cbe073SMarc-André Lureau 490588cbe073SMarc-André Lureau static void spapr_machine_2_2_class_options(MachineClass *mc) 490688cbe073SMarc-André Lureau { 490788cbe073SMarc-André Lureau static GlobalProperty compat[] = { 49086c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0x20000000" }, 4909fa386d98SMarc-André Lureau }; 4910b194df47SAlexey Kardashevskiy 4911fc9f38c3SDavid Gibson spapr_machine_2_3_class_options(mc); 49121c30044eSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_2, hw_compat_2_2_len); 491388cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 4914f6d0656bSEduardo Habkost mc->default_machine_opts = "modern-hotplug-events=off,suppress-vmdesc=on"; 49151c5f29bbSDavid Gibson } 4916fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_2, "2.2", false); 49171c5f29bbSDavid Gibson 49181c5f29bbSDavid Gibson /* 49191c5f29bbSDavid Gibson * pseries-2.1 49201c5f29bbSDavid Gibson */ 49211c5f29bbSDavid Gibson 49225013c547SDavid Gibson static void spapr_machine_2_1_class_options(MachineClass *mc) 4923b0e966d0SJason Wang { 4924fc9f38c3SDavid Gibson spapr_machine_2_2_class_options(mc); 4925c4fc5695SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_1, hw_compat_2_1_len); 49266026db45SAlexey Kardashevskiy } 4927fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_1, "2.1", false); 49286026db45SAlexey Kardashevskiy 492929ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void) 493029ee3247SAlexey Kardashevskiy { 493129ee3247SAlexey Kardashevskiy type_register_static(&spapr_machine_info); 493229ee3247SAlexey Kardashevskiy } 493329ee3247SAlexey Kardashevskiy 493429ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types) 4935