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" 282c65db5eSPaolo Bonzini #include "qemu/datadir.h" 295df022cfSPeter Maydell #include "qemu/memalign.h" 30c4b07531SJason A. Donenfeld #include "qemu/guest-random.h" 31da34e65cSMarkus Armbruster #include "qapi/error.h" 32eb7f80fdSDaniel Henrique Barboza #include "qapi/qapi-events-machine.h" 334b08cd56SDaniel Henrique Barboza #include "qapi/qapi-events-qdev.h" 34fa98fbfcSSam Bobroff #include "qapi/visitor.h" 3553018216SPaolo Bonzini #include "sysemu/sysemu.h" 36b58c5c2dSMarkus Armbruster #include "sysemu/hostmem.h" 37e35704baSEduardo Habkost #include "sysemu/numa.h" 3823ff81bdSGreg Kurz #include "sysemu/qtest.h" 3971e8a915SMarkus Armbruster #include "sysemu/reset.h" 4054d31236SMarkus Armbruster #include "sysemu/runstate.h" 4103dd024fSPaolo Bonzini #include "qemu/log.h" 4271461b0fSAlexey Kardashevskiy #include "hw/fw-path-provider.h" 4353018216SPaolo Bonzini #include "elf.h" 4453018216SPaolo Bonzini #include "net/net.h" 45ad440b4aSAndrew Jones #include "sysemu/device_tree.h" 4653018216SPaolo Bonzini #include "sysemu/cpus.h" 47b3946626SVincent Palatin #include "sysemu/hw_accel.h" 4853018216SPaolo Bonzini #include "kvm_ppc.h" 49c4b63b7cSJuan Quintela #include "migration/misc.h" 50ca77ee28SMarkus Armbruster #include "migration/qemu-file-types.h" 5184a899deSJuan Quintela #include "migration/global_state.h" 52f2a8f0a6SJuan Quintela #include "migration/register.h" 532500fb42SAravinda Prasad #include "migration/blocker.h" 544be21d56SDavid Gibson #include "mmu-hash64.h" 55b4db5413SSuraj Jitindar Singh #include "mmu-book3s-v3.h" 567abd43baSSuraj Jitindar Singh #include "cpu-models.h" 572e5b09fdSMarkus Armbruster #include "hw/core/cpu.h" 5853018216SPaolo Bonzini 590d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h" 6053018216SPaolo Bonzini #include "hw/loader.h" 6153018216SPaolo Bonzini 627804c353SCédric Le Goater #include "hw/ppc/fdt.h" 630d09e41aSPaolo Bonzini #include "hw/ppc/spapr.h" 646b8a0537SNicholas Piggin #include "hw/ppc/spapr_nested.h" 650d09e41aSPaolo Bonzini #include "hw/ppc/spapr_vio.h" 6646d80a56SPhilippe Mathieu-Daudé #include "hw/ppc/vof.h" 67a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 680d09e41aSPaolo Bonzini #include "hw/pci-host/spapr.h" 6953018216SPaolo Bonzini #include "hw/pci/msi.h" 7053018216SPaolo Bonzini 7153018216SPaolo Bonzini #include "hw/pci/pci.h" 7271461b0fSAlexey Kardashevskiy #include "hw/scsi/scsi.h" 7371461b0fSAlexey Kardashevskiy #include "hw/virtio/virtio-scsi.h" 74c4e13492SFelipe Franciosi #include "hw/virtio/vhost-scsi-common.h" 7553018216SPaolo Bonzini 762309832aSDavid Gibson #include "exec/ram_addr.h" 7753018216SPaolo Bonzini #include "hw/usb.h" 7853018216SPaolo Bonzini #include "qemu/config-file.h" 79135a129aSAneesh Kumar K.V #include "qemu/error-report.h" 802a6593cbSAlexey Kardashevskiy #include "trace.h" 8134316482SAlexey Kardashevskiy #include "hw/nmi.h" 826449da45SCédric Le Goater #include "hw/intc/intc.h" 8353018216SPaolo Bonzini 8494a94e4cSBharata B Rao #include "hw/ppc/spapr_cpu_core.h" 852cc0e2e8SDavid Hildenbrand #include "hw/mem/memory-device.h" 860fb6bd07SMichael Roth #include "hw/ppc/spapr_tpm_proxy.h" 87ee3a71e3SShivaprasad G Bhat #include "hw/ppc/spapr_nvdimm.h" 881eee9950SDaniel Henrique Barboza #include "hw/ppc/spapr_numa.h" 896c8ebe30SDavid Gibson #include "hw/ppc/pef.h" 9068a27b20SMichael S. Tsirkin 91f041d6afSGreg Kurz #include "monitor/monitor.h" 92f041d6afSGreg Kurz 9353018216SPaolo Bonzini #include <libfdt.h> 9453018216SPaolo Bonzini 9553018216SPaolo Bonzini /* SLOF memory layout: 9653018216SPaolo Bonzini * 9753018216SPaolo Bonzini * SLOF raw image loaded at 0, copies its romfs right below the flat 9853018216SPaolo Bonzini * device-tree, then position SLOF itself 31M below that 9953018216SPaolo Bonzini * 10053018216SPaolo Bonzini * So we set FW_OVERHEAD to 40MB which should account for all of that 10153018216SPaolo Bonzini * and more 10253018216SPaolo Bonzini * 10353018216SPaolo Bonzini * We load our kernel at 4M, leaving space for SLOF initial image 10453018216SPaolo Bonzini */ 1054b98e72dSAlexey Kardashevskiy #define FDT_MAX_ADDR 0x80000000 /* FDT must stay below that */ 10653018216SPaolo Bonzini #define FW_MAX_SIZE 0x400000 10753018216SPaolo Bonzini #define FW_FILE_NAME "slof.bin" 108fc8c745dSAlexey Kardashevskiy #define FW_FILE_NAME_VOF "vof.bin" 10953018216SPaolo Bonzini #define FW_OVERHEAD 0x2800000 11053018216SPaolo Bonzini #define KERNEL_LOAD_ADDR FW_MAX_SIZE 11153018216SPaolo Bonzini 1129943266eSDavid Gibson #define MIN_RMA_SLOF (128 * MiB) 11353018216SPaolo Bonzini 1145c7adcf4SGreg Kurz #define PHANDLE_INTC 0x00001111 11553018216SPaolo Bonzini 1165d0fb150SGreg Kurz /* These two functions implement the VCPU id numbering: one to compute them 1175d0fb150SGreg Kurz * all and one to identify thread 0 of a VCORE. Any change to the first one 1185d0fb150SGreg Kurz * is likely to have an impact on the second one, so let's keep them close. 1195d0fb150SGreg Kurz */ 120ce2918cbSDavid Gibson static int spapr_vcpu_id(SpaprMachineState *spapr, int cpu_index) 1215d0fb150SGreg Kurz { 122fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 123fe6b6346SLike Xu unsigned int smp_threads = ms->smp.threads; 124fe6b6346SLike Xu 1251a5008fcSGreg Kurz assert(spapr->vsmt); 1265d0fb150SGreg Kurz return 1275d0fb150SGreg Kurz (cpu_index / smp_threads) * spapr->vsmt + cpu_index % smp_threads; 1285d0fb150SGreg Kurz } 129ce2918cbSDavid Gibson static bool spapr_is_thread0_in_vcore(SpaprMachineState *spapr, 1305d0fb150SGreg Kurz PowerPCCPU *cpu) 1315d0fb150SGreg Kurz { 1321a5008fcSGreg Kurz assert(spapr->vsmt); 1335d0fb150SGreg Kurz return spapr_get_vcpu_id(cpu) % spapr->vsmt == 0; 1345d0fb150SGreg Kurz } 1355d0fb150SGreg Kurz 13646f7afa3SGreg Kurz static bool pre_2_10_vmstate_dummy_icp_needed(void *opaque) 13746f7afa3SGreg Kurz { 13846f7afa3SGreg Kurz /* Dummy entries correspond to unused ICPState objects in older QEMUs, 13946f7afa3SGreg Kurz * and newer QEMUs don't even have them. In both cases, we don't want 14046f7afa3SGreg Kurz * to send anything on the wire. 14146f7afa3SGreg Kurz */ 14246f7afa3SGreg Kurz return false; 14346f7afa3SGreg Kurz } 14446f7afa3SGreg Kurz 14546f7afa3SGreg Kurz static const VMStateDescription pre_2_10_vmstate_dummy_icp = { 146*485fb955SJuan Quintela /* 147*485fb955SJuan Quintela * Hack ahead. We can't have two devices with the same name and 148*485fb955SJuan Quintela * instance id. So I rename this to pass make check. 149*485fb955SJuan Quintela * Real help from people who knows the hardware is needed. 150*485fb955SJuan Quintela */ 15146f7afa3SGreg Kurz .name = "icp/server", 15246f7afa3SGreg Kurz .version_id = 1, 15346f7afa3SGreg Kurz .minimum_version_id = 1, 15446f7afa3SGreg Kurz .needed = pre_2_10_vmstate_dummy_icp_needed, 15546f7afa3SGreg Kurz .fields = (VMStateField[]) { 15646f7afa3SGreg Kurz VMSTATE_UNUSED(4), /* uint32_t xirr */ 15746f7afa3SGreg Kurz VMSTATE_UNUSED(1), /* uint8_t pending_priority */ 15846f7afa3SGreg Kurz VMSTATE_UNUSED(1), /* uint8_t mfrr */ 15946f7afa3SGreg Kurz VMSTATE_END_OF_LIST() 16046f7afa3SGreg Kurz }, 16146f7afa3SGreg Kurz }; 16246f7afa3SGreg Kurz 163*485fb955SJuan Quintela /* 164*485fb955SJuan Quintela * See comment in hw/intc/xics.c:icp_realize() 165*485fb955SJuan Quintela * 166*485fb955SJuan Quintela * You have to remove vmstate_replace_hack_for_ppc() when you remove 167*485fb955SJuan Quintela * the machine types that need the following function. 168*485fb955SJuan Quintela */ 16946f7afa3SGreg Kurz static void pre_2_10_vmstate_register_dummy_icp(int i) 17046f7afa3SGreg Kurz { 17146f7afa3SGreg Kurz vmstate_register(NULL, i, &pre_2_10_vmstate_dummy_icp, 17246f7afa3SGreg Kurz (void *)(uintptr_t) i); 17346f7afa3SGreg Kurz } 17446f7afa3SGreg Kurz 175*485fb955SJuan Quintela /* 176*485fb955SJuan Quintela * See comment in hw/intc/xics.c:icp_realize() 177*485fb955SJuan Quintela * 178*485fb955SJuan Quintela * You have to remove vmstate_replace_hack_for_ppc() when you remove 179*485fb955SJuan Quintela * the machine types that need the following function. 180*485fb955SJuan Quintela */ 18146f7afa3SGreg Kurz static void pre_2_10_vmstate_unregister_dummy_icp(int i) 18246f7afa3SGreg Kurz { 183*485fb955SJuan Quintela /* 184*485fb955SJuan Quintela * This used to be: 185*485fb955SJuan Quintela * 186*485fb955SJuan Quintela * vmstate_unregister(NULL, &pre_2_10_vmstate_dummy_icp, 187*485fb955SJuan Quintela * (void *)(uintptr_t) i); 188*485fb955SJuan Quintela */ 18946f7afa3SGreg Kurz } 19046f7afa3SGreg Kurz 191ce2918cbSDavid Gibson int spapr_max_server_number(SpaprMachineState *spapr) 19246f7afa3SGreg Kurz { 193fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 194fe6b6346SLike Xu 1951a5008fcSGreg Kurz assert(spapr->vsmt); 196fe6b6346SLike Xu return DIV_ROUND_UP(ms->smp.max_cpus * spapr->vsmt, ms->smp.threads); 19746f7afa3SGreg Kurz } 19846f7afa3SGreg Kurz 199833d4668SAlexey Kardashevskiy static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, 200833d4668SAlexey Kardashevskiy int smt_threads) 201833d4668SAlexey Kardashevskiy { 202833d4668SAlexey Kardashevskiy int i, ret = 0; 203a580fdcdSPhilippe Mathieu-Daudé g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads); 204a580fdcdSPhilippe Mathieu-Daudé g_autofree uint32_t *gservers_prop = g_new(uint32_t, smt_threads * 2); 20514bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 206833d4668SAlexey Kardashevskiy 207d6e166c0SDavid Gibson if (cpu->compat_pvr) { 208d6e166c0SDavid Gibson ret = fdt_setprop_cell(fdt, offset, "cpu-version", cpu->compat_pvr); 2096d9412eaSAlexey Kardashevskiy if (ret < 0) { 2106d9412eaSAlexey Kardashevskiy return ret; 2116d9412eaSAlexey Kardashevskiy } 2126d9412eaSAlexey Kardashevskiy } 2136d9412eaSAlexey Kardashevskiy 214833d4668SAlexey Kardashevskiy /* Build interrupt servers and gservers properties */ 215833d4668SAlexey Kardashevskiy for (i = 0; i < smt_threads; i++) { 216833d4668SAlexey Kardashevskiy servers_prop[i] = cpu_to_be32(index + i); 217833d4668SAlexey Kardashevskiy /* Hack, direct the group queues back to cpu 0 */ 218833d4668SAlexey Kardashevskiy gservers_prop[i*2] = cpu_to_be32(index + i); 219833d4668SAlexey Kardashevskiy gservers_prop[i*2 + 1] = 0; 220833d4668SAlexey Kardashevskiy } 221833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 222a580fdcdSPhilippe Mathieu-Daudé servers_prop, sizeof(*servers_prop) * smt_threads); 223833d4668SAlexey Kardashevskiy if (ret < 0) { 224833d4668SAlexey Kardashevskiy return ret; 225833d4668SAlexey Kardashevskiy } 226833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-gserver#s", 227a580fdcdSPhilippe Mathieu-Daudé gservers_prop, sizeof(*gservers_prop) * smt_threads * 2); 228833d4668SAlexey Kardashevskiy 229833d4668SAlexey Kardashevskiy return ret; 230833d4668SAlexey Kardashevskiy } 231833d4668SAlexey Kardashevskiy 23291335a5eSDavid Gibson static void spapr_dt_pa_features(SpaprMachineState *spapr, 233ee76a09fSDavid Gibson PowerPCCPU *cpu, 234daa36379SDavid Gibson void *fdt, int offset) 23586d5771aSSam Bobroff { 23686d5771aSSam Bobroff uint8_t pa_features_206[] = { 6, 0, 23786d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 }; 23886d5771aSSam Bobroff uint8_t pa_features_207[] = { 24, 0, 23986d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, 24086d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 24186d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 24286d5771aSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 }; 2439fb4541fSSam Bobroff uint8_t pa_features_300[] = { 66, 0, 2449fb4541fSSam Bobroff /* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */ 2459fb4541fSSam Bobroff /* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, SSO, 5: LE|CFAR|EB|LSQ */ 24686d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, /* 0 - 5 */ 2479fb4541fSSam Bobroff /* 6: DS207 */ 24886d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */ 2499fb4541fSSam Bobroff /* 16: Vector */ 25086d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */ 2519fb4541fSSam Bobroff /* 18: Vec. Scalar, 20: Vec. XOR, 22: HTM */ 2529bf502feSDavid Gibson 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */ 2539fb4541fSSam Bobroff /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */ 2549fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */ 2559fb4541fSSam Bobroff /* 30: MMR, 32: LE atomic, 34: EBB + ext EBB */ 2569fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */ 2579fb4541fSSam Bobroff /* 36: SPR SO, 38: Copy/Paste, 40: Radix MMU */ 2589fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 36 - 41 */ 2599fb4541fSSam Bobroff /* 42: PM, 44: PC RA, 46: SC vec'd */ 2609fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */ 2619fb4541fSSam Bobroff /* 48: SIMD, 50: QP BFP, 52: String */ 2629fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */ 2639fb4541fSSam Bobroff /* 54: DecFP, 56: DecI, 58: SHA */ 2649fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */ 2659fb4541fSSam Bobroff /* 60: NM atomic, 62: RNG */ 2669fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */ 2679fb4541fSSam Bobroff }; 2687abd43baSSuraj Jitindar Singh uint8_t *pa_features = NULL; 26986d5771aSSam Bobroff size_t pa_size; 27086d5771aSSam Bobroff 2717abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06, 0, cpu->compat_pvr)) { 27286d5771aSSam Bobroff pa_features = pa_features_206; 27386d5771aSSam Bobroff pa_size = sizeof(pa_features_206); 2747abd43baSSuraj Jitindar Singh } 2757abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07, 0, cpu->compat_pvr)) { 27686d5771aSSam Bobroff pa_features = pa_features_207; 27786d5771aSSam Bobroff pa_size = sizeof(pa_features_207); 2787abd43baSSuraj Jitindar Singh } 2797abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0, cpu->compat_pvr)) { 28086d5771aSSam Bobroff pa_features = pa_features_300; 28186d5771aSSam Bobroff pa_size = sizeof(pa_features_300); 2827abd43baSSuraj Jitindar Singh } 2837abd43baSSuraj Jitindar Singh if (!pa_features) { 28486d5771aSSam Bobroff return; 28586d5771aSSam Bobroff } 28686d5771aSSam Bobroff 28726cd35b8SDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_CI_LARGEPAGE)) { 28886d5771aSSam Bobroff /* 28986d5771aSSam Bobroff * Note: we keep CI large pages off by default because a 64K capable 29086d5771aSSam Bobroff * guest provisioned with large pages might otherwise try to map a qemu 29186d5771aSSam Bobroff * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages 29286d5771aSSam Bobroff * even if that qemu runs on a 4k host. 29386d5771aSSam Bobroff * We dd this bit back here if we are confident this is not an issue 29486d5771aSSam Bobroff */ 29586d5771aSSam Bobroff pa_features[3] |= 0x20; 29686d5771aSSam Bobroff } 2974e5fe368SSuraj Jitindar Singh if ((spapr_get_cap(spapr, SPAPR_CAP_HTM) != 0) && pa_size > 24) { 29886d5771aSSam Bobroff pa_features[24] |= 0x80; /* Transactional memory support */ 29986d5771aSSam Bobroff } 300daa36379SDavid Gibson if (spapr->cas_pre_isa3_guest && pa_size > 40) { 301e957f6a9SSam Bobroff /* Workaround for broken kernels that attempt (guest) radix 302e957f6a9SSam Bobroff * mode when they can't handle it, if they see the radix bit set 303e957f6a9SSam Bobroff * in pa-features. So hide it from them. */ 304e957f6a9SSam Bobroff pa_features[40 + 2] &= ~0x80; /* Radix MMU */ 305e957f6a9SSam Bobroff } 30686d5771aSSam Bobroff 30786d5771aSSam Bobroff _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size))); 30886d5771aSSam Bobroff } 30986d5771aSSam Bobroff 310c86c1affSDaniel Henrique Barboza static hwaddr spapr_node0_size(MachineState *machine) 311b082d65aSAlexey Kardashevskiy { 312aa570207STao Xu if (machine->numa_state->num_nodes) { 313b082d65aSAlexey Kardashevskiy int i; 314aa570207STao Xu for (i = 0; i < machine->numa_state->num_nodes; ++i) { 3157e721e7bSTao Xu if (machine->numa_state->nodes[i].node_mem) { 3167e721e7bSTao Xu return MIN(pow2floor(machine->numa_state->nodes[i].node_mem), 317fb164994SDavid Gibson machine->ram_size); 318b082d65aSAlexey Kardashevskiy } 319b082d65aSAlexey Kardashevskiy } 320b082d65aSAlexey Kardashevskiy } 321fb164994SDavid Gibson return machine->ram_size; 322b082d65aSAlexey Kardashevskiy } 323b082d65aSAlexey Kardashevskiy 324a1d59c0fSAlexey Kardashevskiy static void add_str(GString *s, const gchar *s1) 325a1d59c0fSAlexey Kardashevskiy { 326a1d59c0fSAlexey Kardashevskiy g_string_append_len(s, s1, strlen(s1) + 1); 327a1d59c0fSAlexey Kardashevskiy } 32853018216SPaolo Bonzini 329f1aa45ffSDaniel Henrique Barboza static int spapr_dt_memory_node(SpaprMachineState *spapr, void *fdt, int nodeid, 330f1aa45ffSDaniel Henrique Barboza hwaddr start, hwaddr size) 33126a8c353SAlexey Kardashevskiy { 33226a8c353SAlexey Kardashevskiy char mem_name[32]; 33326a8c353SAlexey Kardashevskiy uint64_t mem_reg_property[2]; 33426a8c353SAlexey Kardashevskiy int off; 33526a8c353SAlexey Kardashevskiy 33626a8c353SAlexey Kardashevskiy mem_reg_property[0] = cpu_to_be64(start); 33726a8c353SAlexey Kardashevskiy mem_reg_property[1] = cpu_to_be64(size); 33826a8c353SAlexey Kardashevskiy 3393a17e38fSAlexey Kardashevskiy sprintf(mem_name, "memory@%" HWADDR_PRIx, start); 34026a8c353SAlexey Kardashevskiy off = fdt_add_subnode(fdt, 0, mem_name); 34126a8c353SAlexey Kardashevskiy _FDT(off); 34226a8c353SAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 34326a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 34426a8c353SAlexey Kardashevskiy sizeof(mem_reg_property)))); 345f1aa45ffSDaniel Henrique Barboza spapr_numa_write_associativity_dt(spapr, fdt, off, nodeid); 34603d196b7SBharata B Rao return off; 34726a8c353SAlexey Kardashevskiy } 34826a8c353SAlexey Kardashevskiy 349f47bd1c8SIgor Mammedov static uint32_t spapr_pc_dimm_node(MemoryDeviceInfoList *list, ram_addr_t addr) 350f47bd1c8SIgor Mammedov { 351f47bd1c8SIgor Mammedov MemoryDeviceInfoList *info; 352f47bd1c8SIgor Mammedov 353f47bd1c8SIgor Mammedov for (info = list; info; info = info->next) { 354f47bd1c8SIgor Mammedov MemoryDeviceInfo *value = info->value; 355f47bd1c8SIgor Mammedov 356f47bd1c8SIgor Mammedov if (value && value->type == MEMORY_DEVICE_INFO_KIND_DIMM) { 357f47bd1c8SIgor Mammedov PCDIMMDeviceInfo *pcdimm_info = value->u.dimm.data; 358f47bd1c8SIgor Mammedov 359ccc2cef8SDavid Gibson if (addr >= pcdimm_info->addr && 360f47bd1c8SIgor Mammedov addr < (pcdimm_info->addr + pcdimm_info->size)) { 361f47bd1c8SIgor Mammedov return pcdimm_info->node; 362f47bd1c8SIgor Mammedov } 363f47bd1c8SIgor Mammedov } 364f47bd1c8SIgor Mammedov } 365f47bd1c8SIgor Mammedov 366f47bd1c8SIgor Mammedov return -1; 367f47bd1c8SIgor Mammedov } 368f47bd1c8SIgor Mammedov 369a324d6f1SBharata B Rao struct sPAPRDrconfCellV2 { 370a324d6f1SBharata B Rao uint32_t seq_lmbs; 371a324d6f1SBharata B Rao uint64_t base_addr; 372a324d6f1SBharata B Rao uint32_t drc_index; 373a324d6f1SBharata B Rao uint32_t aa_index; 374a324d6f1SBharata B Rao uint32_t flags; 375a324d6f1SBharata B Rao } QEMU_PACKED; 376a324d6f1SBharata B Rao 377a324d6f1SBharata B Rao typedef struct DrconfCellQueue { 378a324d6f1SBharata B Rao struct sPAPRDrconfCellV2 cell; 379a324d6f1SBharata B Rao QSIMPLEQ_ENTRY(DrconfCellQueue) entry; 380a324d6f1SBharata B Rao } DrconfCellQueue; 381a324d6f1SBharata B Rao 382a324d6f1SBharata B Rao static DrconfCellQueue * 383a324d6f1SBharata B Rao spapr_get_drconf_cell(uint32_t seq_lmbs, uint64_t base_addr, 384a324d6f1SBharata B Rao uint32_t drc_index, uint32_t aa_index, 385a324d6f1SBharata B Rao uint32_t flags) 38603d196b7SBharata B Rao { 387a324d6f1SBharata B Rao DrconfCellQueue *elem; 388a324d6f1SBharata B Rao 389a324d6f1SBharata B Rao elem = g_malloc0(sizeof(*elem)); 390a324d6f1SBharata B Rao elem->cell.seq_lmbs = cpu_to_be32(seq_lmbs); 391a324d6f1SBharata B Rao elem->cell.base_addr = cpu_to_be64(base_addr); 392a324d6f1SBharata B Rao elem->cell.drc_index = cpu_to_be32(drc_index); 393a324d6f1SBharata B Rao elem->cell.aa_index = cpu_to_be32(aa_index); 394a324d6f1SBharata B Rao elem->cell.flags = cpu_to_be32(flags); 395a324d6f1SBharata B Rao 396a324d6f1SBharata B Rao return elem; 397a324d6f1SBharata B Rao } 398a324d6f1SBharata B Rao 39991335a5eSDavid Gibson static int spapr_dt_dynamic_memory_v2(SpaprMachineState *spapr, void *fdt, 400a324d6f1SBharata B Rao int offset, MemoryDeviceInfoList *dimms) 4012a6593cbSAlexey Kardashevskiy { 4022a6593cbSAlexey Kardashevskiy MachineState *machine = MACHINE(spapr); 403cc941111SFabiano Rosas uint8_t *int_buf, *cur_index; 404a324d6f1SBharata B Rao int ret; 40503d196b7SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 406a324d6f1SBharata B Rao uint64_t addr, cur_addr, size; 407b0c14ec4SDavid Hildenbrand uint32_t nr_boot_lmbs = (machine->device_memory->base / lmb_size); 408b0c14ec4SDavid Hildenbrand uint64_t mem_end = machine->device_memory->base + 409b0c14ec4SDavid Hildenbrand memory_region_size(&machine->device_memory->mr); 410cc941111SFabiano Rosas uint32_t node, buf_len, nr_entries = 0; 411ce2918cbSDavid Gibson SpaprDrc *drc; 412a324d6f1SBharata B Rao DrconfCellQueue *elem, *next; 413a324d6f1SBharata B Rao MemoryDeviceInfoList *info; 414a324d6f1SBharata B Rao QSIMPLEQ_HEAD(, DrconfCellQueue) drconf_queue 415a324d6f1SBharata B Rao = QSIMPLEQ_HEAD_INITIALIZER(drconf_queue); 416a324d6f1SBharata B Rao 417a324d6f1SBharata B Rao /* Entry to cover RAM and the gap area */ 418a324d6f1SBharata B Rao elem = spapr_get_drconf_cell(nr_boot_lmbs, 0, 0, -1, 419a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_RESERVED | 420a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 421a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 422a324d6f1SBharata B Rao nr_entries++; 423a324d6f1SBharata B Rao 424b0c14ec4SDavid Hildenbrand cur_addr = machine->device_memory->base; 425a324d6f1SBharata B Rao for (info = dimms; info; info = info->next) { 426a324d6f1SBharata B Rao PCDIMMDeviceInfo *di = info->value->u.dimm.data; 427a324d6f1SBharata B Rao 428a324d6f1SBharata B Rao addr = di->addr; 429a324d6f1SBharata B Rao size = di->size; 430a324d6f1SBharata B Rao node = di->node; 431a324d6f1SBharata B Rao 432ee3a71e3SShivaprasad G Bhat /* 433ee3a71e3SShivaprasad G Bhat * The NVDIMM area is hotpluggable after the NVDIMM is unplugged. The 434ee3a71e3SShivaprasad G Bhat * area is marked hotpluggable in the next iteration for the bigger 435ee3a71e3SShivaprasad G Bhat * chunk including the NVDIMM occupied area. 436ee3a71e3SShivaprasad G Bhat */ 437ee3a71e3SShivaprasad G Bhat if (info->value->type == MEMORY_DEVICE_INFO_KIND_NVDIMM) 438ee3a71e3SShivaprasad G Bhat continue; 439ee3a71e3SShivaprasad G Bhat 440a324d6f1SBharata B Rao /* Entry for hot-pluggable area */ 441a324d6f1SBharata B Rao if (cur_addr < addr) { 442a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size); 443a324d6f1SBharata B Rao g_assert(drc); 444a324d6f1SBharata B Rao elem = spapr_get_drconf_cell((addr - cur_addr) / lmb_size, 445a324d6f1SBharata B Rao cur_addr, spapr_drc_index(drc), -1, 0); 446a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 447a324d6f1SBharata B Rao nr_entries++; 448a324d6f1SBharata B Rao } 449a324d6f1SBharata B Rao 450a324d6f1SBharata B Rao /* Entry for DIMM */ 451a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr / lmb_size); 452a324d6f1SBharata B Rao g_assert(drc); 453a324d6f1SBharata B Rao elem = spapr_get_drconf_cell(size / lmb_size, addr, 454a324d6f1SBharata B Rao spapr_drc_index(drc), node, 4550911a60cSLeonardo Bras (SPAPR_LMB_FLAGS_ASSIGNED | 4560911a60cSLeonardo Bras SPAPR_LMB_FLAGS_HOTREMOVABLE)); 457a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 458a324d6f1SBharata B Rao nr_entries++; 459a324d6f1SBharata B Rao cur_addr = addr + size; 460a324d6f1SBharata B Rao } 461a324d6f1SBharata B Rao 462a324d6f1SBharata B Rao /* Entry for remaining hotpluggable area */ 463a324d6f1SBharata B Rao if (cur_addr < mem_end) { 464a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size); 465a324d6f1SBharata B Rao g_assert(drc); 466a324d6f1SBharata B Rao elem = spapr_get_drconf_cell((mem_end - cur_addr) / lmb_size, 467a324d6f1SBharata B Rao cur_addr, spapr_drc_index(drc), -1, 0); 468a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); 469a324d6f1SBharata B Rao nr_entries++; 470a324d6f1SBharata B Rao } 471a324d6f1SBharata B Rao 472a324d6f1SBharata B Rao buf_len = nr_entries * sizeof(struct sPAPRDrconfCellV2) + sizeof(uint32_t); 473a324d6f1SBharata B Rao int_buf = cur_index = g_malloc0(buf_len); 474a324d6f1SBharata B Rao *(uint32_t *)int_buf = cpu_to_be32(nr_entries); 475a324d6f1SBharata B Rao cur_index += sizeof(nr_entries); 476a324d6f1SBharata B Rao 477a324d6f1SBharata B Rao QSIMPLEQ_FOREACH_SAFE(elem, &drconf_queue, entry, next) { 478a324d6f1SBharata B Rao memcpy(cur_index, &elem->cell, sizeof(elem->cell)); 479a324d6f1SBharata B Rao cur_index += sizeof(elem->cell); 480a324d6f1SBharata B Rao QSIMPLEQ_REMOVE(&drconf_queue, elem, DrconfCellQueue, entry); 481a324d6f1SBharata B Rao g_free(elem); 482a324d6f1SBharata B Rao } 483a324d6f1SBharata B Rao 484a324d6f1SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory-v2", int_buf, buf_len); 485a324d6f1SBharata B Rao g_free(int_buf); 486a324d6f1SBharata B Rao if (ret < 0) { 487a324d6f1SBharata B Rao return -1; 488a324d6f1SBharata B Rao } 489a324d6f1SBharata B Rao return 0; 490a324d6f1SBharata B Rao } 491a324d6f1SBharata B Rao 49291335a5eSDavid Gibson static int spapr_dt_dynamic_memory(SpaprMachineState *spapr, void *fdt, 493a324d6f1SBharata B Rao int offset, MemoryDeviceInfoList *dimms) 494a324d6f1SBharata B Rao { 495b0c14ec4SDavid Hildenbrand MachineState *machine = MACHINE(spapr); 496a324d6f1SBharata B Rao int i, ret; 497a324d6f1SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 4980c9269a5SDavid Hildenbrand uint32_t device_lmb_start = machine->device_memory->base / lmb_size; 499b0c14ec4SDavid Hildenbrand uint32_t nr_lmbs = (machine->device_memory->base + 500b0c14ec4SDavid Hildenbrand memory_region_size(&machine->device_memory->mr)) / 501d0e5a8f2SBharata B Rao lmb_size; 50203d196b7SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 50316c25aefSBharata B Rao 50416c25aefSBharata B Rao /* 505ef001f06SThomas Huth * Allocate enough buffer size to fit in ibm,dynamic-memory 506ef001f06SThomas Huth */ 507a324d6f1SBharata B Rao buf_len = (nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1) * sizeof(uint32_t); 50803d196b7SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 50903d196b7SBharata B Rao int_buf[0] = cpu_to_be32(nr_lmbs); 51003d196b7SBharata B Rao cur_index++; 51103d196b7SBharata B Rao for (i = 0; i < nr_lmbs; i++) { 512d0e5a8f2SBharata B Rao uint64_t addr = i * lmb_size; 51303d196b7SBharata B Rao uint32_t *dynamic_memory = cur_index; 51403d196b7SBharata B Rao 5150c9269a5SDavid Hildenbrand if (i >= device_lmb_start) { 516ce2918cbSDavid Gibson SpaprDrc *drc; 517d0e5a8f2SBharata B Rao 518fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, i); 51903d196b7SBharata B Rao g_assert(drc); 52003d196b7SBharata B Rao 52103d196b7SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 52203d196b7SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 5230b55aa91SDavid Gibson dynamic_memory[2] = cpu_to_be32(spapr_drc_index(drc)); 52403d196b7SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 525f47bd1c8SIgor Mammedov dynamic_memory[4] = cpu_to_be32(spapr_pc_dimm_node(dimms, addr)); 526d0e5a8f2SBharata B Rao if (memory_region_present(get_system_memory(), addr)) { 52703d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); 52803d196b7SBharata B Rao } else { 52903d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(0); 53003d196b7SBharata B Rao } 531d0e5a8f2SBharata B Rao } else { 532d0e5a8f2SBharata B Rao /* 533d0e5a8f2SBharata B Rao * LMB information for RMA, boot time RAM and gap b/n RAM and 5340c9269a5SDavid Hildenbrand * device memory region -- all these are marked as reserved 535d0e5a8f2SBharata B Rao * and as having no valid DRC. 536d0e5a8f2SBharata B Rao */ 537d0e5a8f2SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 538d0e5a8f2SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 539d0e5a8f2SBharata B Rao dynamic_memory[2] = cpu_to_be32(0); 540d0e5a8f2SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 541d0e5a8f2SBharata B Rao dynamic_memory[4] = cpu_to_be32(-1); 542d0e5a8f2SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED | 543d0e5a8f2SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 544d0e5a8f2SBharata B Rao } 54503d196b7SBharata B Rao 54603d196b7SBharata B Rao cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; 54703d196b7SBharata B Rao } 54803d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len); 549a324d6f1SBharata B Rao g_free(int_buf); 55003d196b7SBharata B Rao if (ret < 0) { 551a324d6f1SBharata B Rao return -1; 552a324d6f1SBharata B Rao } 553a324d6f1SBharata B Rao return 0; 554a324d6f1SBharata B Rao } 555a324d6f1SBharata B Rao 556a324d6f1SBharata B Rao /* 557a324d6f1SBharata B Rao * Adds ibm,dynamic-reconfiguration-memory node. 558a324d6f1SBharata B Rao * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation 559a324d6f1SBharata B Rao * of this device tree node. 560a324d6f1SBharata B Rao */ 56191335a5eSDavid Gibson static int spapr_dt_dynamic_reconfiguration_memory(SpaprMachineState *spapr, 56291335a5eSDavid Gibson void *fdt) 563a324d6f1SBharata B Rao { 564a324d6f1SBharata B Rao MachineState *machine = MACHINE(spapr); 5650ee52012SDaniel Henrique Barboza int ret, offset; 566a324d6f1SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 5677abf9797SAnton Blanchard uint32_t prop_lmb_size[] = {cpu_to_be32(lmb_size >> 32), 5687abf9797SAnton Blanchard cpu_to_be32(lmb_size & 0xffffffff)}; 569a324d6f1SBharata B Rao MemoryDeviceInfoList *dimms = NULL; 570a324d6f1SBharata B Rao 571c0ce7b4aSDavid Hildenbrand /* Don't create the node if there is no device memory. */ 572c0ce7b4aSDavid Hildenbrand if (!machine->device_memory) { 573a324d6f1SBharata B Rao return 0; 574a324d6f1SBharata B Rao } 575a324d6f1SBharata B Rao 576a324d6f1SBharata B Rao offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory"); 577a324d6f1SBharata B Rao 578a324d6f1SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size, 579a324d6f1SBharata B Rao sizeof(prop_lmb_size)); 580a324d6f1SBharata B Rao if (ret < 0) { 581a324d6f1SBharata B Rao return ret; 582a324d6f1SBharata B Rao } 583a324d6f1SBharata B Rao 584a324d6f1SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff); 585a324d6f1SBharata B Rao if (ret < 0) { 586a324d6f1SBharata B Rao return ret; 587a324d6f1SBharata B Rao } 588a324d6f1SBharata B Rao 589a324d6f1SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0); 590a324d6f1SBharata B Rao if (ret < 0) { 591a324d6f1SBharata B Rao return ret; 592a324d6f1SBharata B Rao } 593a324d6f1SBharata B Rao 594a324d6f1SBharata B Rao /* ibm,dynamic-memory or ibm,dynamic-memory-v2 */ 5952cc0e2e8SDavid Hildenbrand dimms = qmp_memory_device_list(); 596a324d6f1SBharata B Rao if (spapr_ovec_test(spapr->ov5_cas, OV5_DRMEM_V2)) { 59791335a5eSDavid Gibson ret = spapr_dt_dynamic_memory_v2(spapr, fdt, offset, dimms); 598a324d6f1SBharata B Rao } else { 59991335a5eSDavid Gibson ret = spapr_dt_dynamic_memory(spapr, fdt, offset, dimms); 600a324d6f1SBharata B Rao } 601a324d6f1SBharata B Rao qapi_free_MemoryDeviceInfoList(dimms); 602a324d6f1SBharata B Rao 603a324d6f1SBharata B Rao if (ret < 0) { 604a324d6f1SBharata B Rao return ret; 60503d196b7SBharata B Rao } 60603d196b7SBharata B Rao 6070ee52012SDaniel Henrique Barboza ret = spapr_numa_write_assoc_lookup_arrays(spapr, fdt, offset); 608a324d6f1SBharata B Rao 60903d196b7SBharata B Rao return ret; 61003d196b7SBharata B Rao } 61103d196b7SBharata B Rao 61291335a5eSDavid Gibson static int spapr_dt_memory(SpaprMachineState *spapr, void *fdt) 6136787d27bSMichael Roth { 614fa523f0dSDavid Gibson MachineState *machine = MACHINE(spapr); 615ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 61653018216SPaolo Bonzini hwaddr mem_start, node_size; 61753018216SPaolo Bonzini int i, nb_nodes = machine->numa_state->num_nodes; 61853018216SPaolo Bonzini NodeInfo *nodes = machine->numa_state->nodes; 61953018216SPaolo Bonzini 62053018216SPaolo Bonzini for (i = 0, mem_start = 0; i < nb_nodes; ++i) { 62153018216SPaolo Bonzini if (!nodes[i].node_mem) { 62253018216SPaolo Bonzini continue; 62353018216SPaolo Bonzini } 62453018216SPaolo Bonzini if (mem_start >= machine->ram_size) { 62553018216SPaolo Bonzini node_size = 0; 62653018216SPaolo Bonzini } else { 62753018216SPaolo Bonzini node_size = nodes[i].node_mem; 62853018216SPaolo Bonzini if (node_size > machine->ram_size - mem_start) { 62953018216SPaolo Bonzini node_size = machine->ram_size - mem_start; 63053018216SPaolo Bonzini } 63153018216SPaolo Bonzini } 63253018216SPaolo Bonzini if (!mem_start) { 63353018216SPaolo Bonzini /* spapr_machine_init() checks for rma_size <= node0_size 63453018216SPaolo Bonzini * already */ 635f1aa45ffSDaniel Henrique Barboza spapr_dt_memory_node(spapr, fdt, i, 0, spapr->rma_size); 63653018216SPaolo Bonzini mem_start += spapr->rma_size; 63753018216SPaolo Bonzini node_size -= spapr->rma_size; 63853018216SPaolo Bonzini } 63953018216SPaolo Bonzini for ( ; node_size; ) { 64053018216SPaolo Bonzini hwaddr sizetmp = pow2floor(node_size); 64153018216SPaolo Bonzini 64253018216SPaolo Bonzini /* mem_start != 0 here */ 64353018216SPaolo Bonzini if (ctzl(mem_start) < ctzl(sizetmp)) { 64453018216SPaolo Bonzini sizetmp = 1ULL << ctzl(mem_start); 64553018216SPaolo Bonzini } 64653018216SPaolo Bonzini 647f1aa45ffSDaniel Henrique Barboza spapr_dt_memory_node(spapr, fdt, i, mem_start, sizetmp); 64853018216SPaolo Bonzini node_size -= sizetmp; 64953018216SPaolo Bonzini mem_start += sizetmp; 65053018216SPaolo Bonzini } 65153018216SPaolo Bonzini } 65253018216SPaolo Bonzini 6536787d27bSMichael Roth /* Generate ibm,dynamic-reconfiguration-memory node if required */ 654fa523f0dSDavid Gibson if (spapr_ovec_test(spapr->ov5_cas, OV5_DRCONF_MEMORY)) { 655fa523f0dSDavid Gibson int ret; 656fa523f0dSDavid Gibson 6576787d27bSMichael Roth g_assert(smc->dr_lmb_enabled); 65891335a5eSDavid Gibson ret = spapr_dt_dynamic_reconfiguration_memory(spapr, fdt); 659417ece33SMichael Roth if (ret) { 6609b6c1da5SDaniel Henrique Barboza return ret; 661417ece33SMichael Roth } 6626787d27bSMichael Roth } 6636787d27bSMichael Roth 66453018216SPaolo Bonzini return 0; 66553018216SPaolo Bonzini } 66653018216SPaolo Bonzini 66791335a5eSDavid Gibson static void spapr_dt_cpu(CPUState *cs, void *fdt, int offset, 66853018216SPaolo Bonzini SpaprMachineState *spapr) 66953018216SPaolo Bonzini { 67053018216SPaolo Bonzini MachineState *ms = MACHINE(spapr); 67153018216SPaolo Bonzini PowerPCCPU *cpu = POWERPC_CPU(cs); 67253018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 67353018216SPaolo Bonzini PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 67453018216SPaolo Bonzini int index = spapr_get_vcpu_id(cpu); 67553018216SPaolo Bonzini uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 67653018216SPaolo Bonzini 0xffffffff, 0xffffffff}; 67753018216SPaolo Bonzini uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() 67853018216SPaolo Bonzini : SPAPR_TIMEBASE_FREQ; 67953018216SPaolo Bonzini uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; 68053018216SPaolo Bonzini uint32_t page_sizes_prop[64]; 68153018216SPaolo Bonzini size_t page_sizes_prop_size; 68253018216SPaolo Bonzini unsigned int smp_threads = ms->smp.threads; 68353018216SPaolo Bonzini uint32_t vcpus_per_socket = smp_threads * ms->smp.cores; 68453018216SPaolo Bonzini uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 68553018216SPaolo Bonzini int compat_smt = MIN(smp_threads, ppc_compat_max_vthreads(cpu)); 68653018216SPaolo Bonzini SpaprDrc *drc; 68753018216SPaolo Bonzini int drc_index; 68853018216SPaolo Bonzini uint32_t radix_AP_encodings[PPC_PAGE_SIZES_MAX_SZ]; 68953018216SPaolo Bonzini int i; 69053018216SPaolo Bonzini 69153018216SPaolo Bonzini drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index); 69253018216SPaolo Bonzini if (drc) { 69353018216SPaolo Bonzini drc_index = spapr_drc_index(drc); 69453018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index))); 6952a6593cbSAlexey Kardashevskiy } 6962a6593cbSAlexey Kardashevskiy 6972a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); 6982a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 6992a6593cbSAlexey Kardashevskiy 7002a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 7012a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 7022a6593cbSAlexey Kardashevskiy env->dcache_line_size))); 7032a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 7042a6593cbSAlexey Kardashevskiy env->dcache_line_size))); 7052a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 7062a6593cbSAlexey Kardashevskiy env->icache_line_size))); 7072a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 7082a6593cbSAlexey Kardashevskiy env->icache_line_size))); 7092a6593cbSAlexey Kardashevskiy 7102a6593cbSAlexey Kardashevskiy if (pcc->l1_dcache_size) { 7112a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 7122a6593cbSAlexey Kardashevskiy pcc->l1_dcache_size))); 7132a6593cbSAlexey Kardashevskiy } else { 7142a6593cbSAlexey Kardashevskiy warn_report("Unknown L1 dcache size for cpu"); 7152a6593cbSAlexey Kardashevskiy } 7162a6593cbSAlexey Kardashevskiy if (pcc->l1_icache_size) { 7172a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 7182a6593cbSAlexey Kardashevskiy pcc->l1_icache_size))); 7192a6593cbSAlexey Kardashevskiy } else { 7202a6593cbSAlexey Kardashevskiy warn_report("Unknown L1 icache size for cpu"); 7212a6593cbSAlexey Kardashevskiy } 7222a6593cbSAlexey Kardashevskiy 7232a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 7242a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 7252a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "slb-size", cpu->hash64_opts->slb_size))); 7262a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", cpu->hash64_opts->slb_size))); 7272a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 7282a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 7292a6593cbSAlexey Kardashevskiy 73003282a3aSLucas Mateus Castro (alqotel) if (ppc_has_spr(cpu, SPR_PURR)) { 73153018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,purr", 1))); 73253018216SPaolo Bonzini } 73303282a3aSLucas Mateus Castro (alqotel) if (ppc_has_spr(cpu, SPR_PURR)) { 73453018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,spurr", 1))); 73553018216SPaolo Bonzini } 73653018216SPaolo Bonzini 73753018216SPaolo Bonzini if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 73853018216SPaolo Bonzini _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 73953018216SPaolo Bonzini segs, sizeof(segs)))); 74053018216SPaolo Bonzini } 74153018216SPaolo Bonzini 74253018216SPaolo Bonzini /* Advertise VSX (vector extensions) if available 74353018216SPaolo Bonzini * 1 == VMX / Altivec available 74453018216SPaolo Bonzini * 2 == VSX available 74553018216SPaolo Bonzini * 74653018216SPaolo Bonzini * Only CPUs for which we create core types in spapr_cpu_core.c 74753018216SPaolo Bonzini * are possible, and all of those have VMX */ 7482460e1d7SCédric Le Goater if (env->insns_flags & PPC_ALTIVEC) { 74953018216SPaolo Bonzini if (spapr_get_cap(spapr, SPAPR_CAP_VSX) != 0) { 75053018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2))); 75153018216SPaolo Bonzini } else { 75253018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1))); 75353018216SPaolo Bonzini } 7542460e1d7SCédric Le Goater } 75553018216SPaolo Bonzini 75653018216SPaolo Bonzini /* Advertise DFP (Decimal Floating Point) if available 75728e02042SDavid Gibson * 0 / no property == no DFP 75853018216SPaolo Bonzini * 1 == DFP available */ 759fb164994SDavid Gibson if (spapr_get_cap(spapr, SPAPR_CAP_DFP) != 0) { 7607db8a127SAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 7617db8a127SAlexey Kardashevskiy } 7627db8a127SAlexey Kardashevskiy 7637db8a127SAlexey Kardashevskiy page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 76453018216SPaolo Bonzini sizeof(page_sizes_prop)); 7657db8a127SAlexey Kardashevskiy if (page_sizes_prop_size) { 7667db8a127SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 7677db8a127SAlexey Kardashevskiy page_sizes_prop, page_sizes_prop_size))); 768fb164994SDavid Gibson } 7697db8a127SAlexey Kardashevskiy 77091335a5eSDavid Gibson spapr_dt_pa_features(spapr, cpu, fdt, offset); 77153018216SPaolo Bonzini 7727db8a127SAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", 7737db8a127SAlexey Kardashevskiy cs->cpu_index / vcpus_per_socket))); 7747db8a127SAlexey Kardashevskiy 77553018216SPaolo Bonzini _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", 776fb164994SDavid Gibson pft_size_prop, sizeof(pft_size_prop)))); 7775fe269b1SPaul Mackerras 7785fe269b1SPaul Mackerras if (ms->numa_state->num_nodes > 1) { 7798f86a408SDaniel Henrique Barboza _FDT(spapr_numa_fixup_cpu_dt(spapr, fdt, offset, cpu)); 7805fe269b1SPaul Mackerras } 7815fe269b1SPaul Mackerras 7827db8a127SAlexey Kardashevskiy _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt)); 7837db8a127SAlexey Kardashevskiy 7847db8a127SAlexey Kardashevskiy if (pcc->radix_page_info) { 7857db8a127SAlexey Kardashevskiy for (i = 0; i < pcc->radix_page_info->count; i++) { 7867db8a127SAlexey Kardashevskiy radix_AP_encodings[i] = 7877db8a127SAlexey Kardashevskiy cpu_to_be32(pcc->radix_page_info->entries[i]); 7886010818cSAlexey Kardashevskiy } 7896010818cSAlexey Kardashevskiy _FDT((fdt_setprop(fdt, offset, "ibm,processor-radix-AP-encodings", 7906010818cSAlexey Kardashevskiy radix_AP_encodings, 7916010818cSAlexey Kardashevskiy pcc->radix_page_info->count * 7926010818cSAlexey Kardashevskiy sizeof(radix_AP_encodings[0])))); 7936010818cSAlexey Kardashevskiy } 7946010818cSAlexey Kardashevskiy 7956010818cSAlexey Kardashevskiy /* 7966010818cSAlexey Kardashevskiy * We set this property to let the guest know that it can use the large 7976010818cSAlexey Kardashevskiy * decrementer and its width in bits. 7986010818cSAlexey Kardashevskiy */ 7996010818cSAlexey Kardashevskiy if (spapr_get_cap(spapr, SPAPR_CAP_LARGE_DECREMENTER) != SPAPR_CAP_OFF) 80053018216SPaolo Bonzini _FDT((fdt_setprop_u32(fdt, offset, "ibm,dec-bits", 80153018216SPaolo Bonzini pcc->lrg_decr_bits))); 80253018216SPaolo Bonzini } 80353018216SPaolo Bonzini 804bd87a59fSCédric Le Goater static void spapr_dt_one_cpu(void *fdt, SpaprMachineState *spapr, CPUState *cs, 805bd87a59fSCédric Le Goater int cpus_offset) 806bd87a59fSCédric Le Goater { 807bd87a59fSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 808bd87a59fSCédric Le Goater int index = spapr_get_vcpu_id(cpu); 809bd87a59fSCédric Le Goater DeviceClass *dc = DEVICE_GET_CLASS(cs); 810bd87a59fSCédric Le Goater g_autofree char *nodename = NULL; 811bd87a59fSCédric Le Goater int offset; 812bd87a59fSCédric Le Goater 813bd87a59fSCédric Le Goater if (!spapr_is_thread0_in_vcore(spapr, cpu)) { 814bd87a59fSCédric Le Goater return; 815bd87a59fSCédric Le Goater } 816bd87a59fSCédric Le Goater 817bd87a59fSCédric Le Goater nodename = g_strdup_printf("%s@%x", dc->fw_name, index); 818bd87a59fSCédric Le Goater offset = fdt_add_subnode(fdt, cpus_offset, nodename); 819bd87a59fSCédric Le Goater _FDT(offset); 820bd87a59fSCédric Le Goater spapr_dt_cpu(cs, fdt, offset, spapr); 821bd87a59fSCédric Le Goater } 822bd87a59fSCédric Le Goater 823bd87a59fSCédric Le Goater 82491335a5eSDavid Gibson static void spapr_dt_cpus(void *fdt, SpaprMachineState *spapr) 82553018216SPaolo Bonzini { 82653018216SPaolo Bonzini CPUState **rev; 82753018216SPaolo Bonzini CPUState *cs; 82853018216SPaolo Bonzini int n_cpus; 82953018216SPaolo Bonzini int cpus_offset; 83053018216SPaolo Bonzini int i; 83153018216SPaolo Bonzini 83253018216SPaolo Bonzini cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 83353018216SPaolo Bonzini _FDT(cpus_offset); 83453018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 83553018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 83653018216SPaolo Bonzini 83753018216SPaolo Bonzini /* 83853018216SPaolo Bonzini * We walk the CPUs in reverse order to ensure that CPU DT nodes 83953018216SPaolo Bonzini * created by fdt_add_subnode() end up in the right order in FDT 84053018216SPaolo Bonzini * for the guest kernel the enumerate the CPUs correctly. 84153018216SPaolo Bonzini * 84253018216SPaolo Bonzini * The CPU list cannot be traversed in reverse order, so we need 84353018216SPaolo Bonzini * to do extra work. 84453018216SPaolo Bonzini */ 84553018216SPaolo Bonzini n_cpus = 0; 84653018216SPaolo Bonzini rev = NULL; 84753018216SPaolo Bonzini CPU_FOREACH(cs) { 84853018216SPaolo Bonzini rev = g_renew(CPUState *, rev, n_cpus + 1); 84953018216SPaolo Bonzini rev[n_cpus++] = cs; 85053018216SPaolo Bonzini } 85153018216SPaolo Bonzini 85253018216SPaolo Bonzini for (i = n_cpus - 1; i >= 0; i--) { 853bd87a59fSCédric Le Goater spapr_dt_one_cpu(fdt, spapr, rev[i], cpus_offset); 8540da6f3feSBharata B Rao } 8550da6f3feSBharata B Rao 8560da6f3feSBharata B Rao g_free(rev); 8570da6f3feSBharata B Rao } 85822419c2aSDavid Gibson 85991335a5eSDavid Gibson static int spapr_dt_rng(void *fdt) 8600da6f3feSBharata B Rao { 8610da6f3feSBharata B Rao int node; 8620da6f3feSBharata B Rao int ret; 8630da6f3feSBharata B Rao 8640da6f3feSBharata B Rao node = qemu_fdt_add_subnode(fdt, "/ibm,platform-facilities"); 8650da6f3feSBharata B Rao if (node <= 0) { 8660da6f3feSBharata B Rao return -1; 8670da6f3feSBharata B Rao } 8680da6f3feSBharata B Rao ret = fdt_setprop_string(fdt, node, "device_type", 8690da6f3feSBharata B Rao "ibm,platform-facilities"); 8700da6f3feSBharata B Rao ret |= fdt_setprop_cell(fdt, node, "#address-cells", 0x1); 8710da6f3feSBharata B Rao ret |= fdt_setprop_cell(fdt, node, "#size-cells", 0x0); 8720da6f3feSBharata B Rao 8730da6f3feSBharata B Rao node = fdt_add_subnode(fdt, node, "ibm,random-v1"); 8740da6f3feSBharata B Rao if (node <= 0) { 8750da6f3feSBharata B Rao return -1; 8760da6f3feSBharata B Rao } 8770da6f3feSBharata B Rao ret |= fdt_setprop_string(fdt, node, "compatible", "ibm,random"); 8780da6f3feSBharata B Rao 8790da6f3feSBharata B Rao return ret ? -1 : 0; 8800da6f3feSBharata B Rao } 8810da6f3feSBharata B Rao 882ce2918cbSDavid Gibson static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt) 8833f5dabceSDavid Gibson { 884fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 8853f5dabceSDavid Gibson int rtas; 8863f5dabceSDavid Gibson GString *hypertas = g_string_sized_new(256); 8873f5dabceSDavid Gibson GString *qemu_hypertas = g_string_sized_new(256); 8883f5dabceSDavid Gibson uint32_t lrdr_capacity[] = { 889c0ce7b4aSDavid Hildenbrand 0, 890c0ce7b4aSDavid Hildenbrand 0, 8917abf9797SAnton Blanchard cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE >> 32), 8927abf9797SAnton Blanchard cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE & 0xffffffff), 893fe6b6346SLike Xu cpu_to_be32(ms->smp.max_cpus / ms->smp.threads), 8943f5dabceSDavid Gibson }; 8953f5dabceSDavid Gibson 896c0ce7b4aSDavid Hildenbrand /* Do we have device memory? */ 897c0ce7b4aSDavid Hildenbrand if (MACHINE(spapr)->device_memory) { 898c0ce7b4aSDavid Hildenbrand uint64_t max_device_addr = MACHINE(spapr)->device_memory->base + 899c0ce7b4aSDavid Hildenbrand memory_region_size(&MACHINE(spapr)->device_memory->mr); 900c0ce7b4aSDavid Hildenbrand 901c0ce7b4aSDavid Hildenbrand lrdr_capacity[0] = cpu_to_be32(max_device_addr >> 32); 902c0ce7b4aSDavid Hildenbrand lrdr_capacity[1] = cpu_to_be32(max_device_addr & 0xffffffff); 903c0ce7b4aSDavid Hildenbrand } 904c0ce7b4aSDavid Hildenbrand 9053f5dabceSDavid Gibson _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas")); 9063f5dabceSDavid Gibson 9073f5dabceSDavid Gibson /* hypertas */ 9083f5dabceSDavid Gibson add_str(hypertas, "hcall-pft"); 9093f5dabceSDavid Gibson add_str(hypertas, "hcall-term"); 9103f5dabceSDavid Gibson add_str(hypertas, "hcall-dabr"); 9113f5dabceSDavid Gibson add_str(hypertas, "hcall-interrupt"); 9123f5dabceSDavid Gibson add_str(hypertas, "hcall-tce"); 9133f5dabceSDavid Gibson add_str(hypertas, "hcall-vio"); 9143f5dabceSDavid Gibson add_str(hypertas, "hcall-splpar"); 91510741314SNicholas Piggin add_str(hypertas, "hcall-join"); 9163f5dabceSDavid Gibson add_str(hypertas, "hcall-bulk"); 9173f5dabceSDavid Gibson add_str(hypertas, "hcall-set-mode"); 9183f5dabceSDavid Gibson add_str(hypertas, "hcall-sprg0"); 9193f5dabceSDavid Gibson add_str(hypertas, "hcall-copy"); 9203f5dabceSDavid Gibson add_str(hypertas, "hcall-debug"); 921c24ba3d0SLaurent Vivier add_str(hypertas, "hcall-vphn"); 92282123b75SBharata B Rao if (spapr_get_cap(spapr, SPAPR_CAP_RPT_INVALIDATE) == SPAPR_CAP_ON) { 92382123b75SBharata B Rao add_str(hypertas, "hcall-rpt-invalidate"); 92482123b75SBharata B Rao } 92582123b75SBharata B Rao 9263f5dabceSDavid Gibson add_str(qemu_hypertas, "hcall-memop1"); 9273f5dabceSDavid Gibson 9283f5dabceSDavid Gibson if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { 9293f5dabceSDavid Gibson add_str(hypertas, "hcall-multi-tce"); 9303f5dabceSDavid Gibson } 93130f4b05bSDavid Gibson 93230f4b05bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { 93330f4b05bSDavid Gibson add_str(hypertas, "hcall-hpt-resize"); 93430f4b05bSDavid Gibson } 93530f4b05bSDavid Gibson 93681b205ceSAlexey Kardashevskiy add_str(hypertas, "hcall-watchdog"); 93781b205ceSAlexey Kardashevskiy 9383f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions", 9393f5dabceSDavid Gibson hypertas->str, hypertas->len)); 9403f5dabceSDavid Gibson g_string_free(hypertas, TRUE); 9413f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "qemu,hypertas-functions", 9423f5dabceSDavid Gibson qemu_hypertas->str, qemu_hypertas->len)); 9433f5dabceSDavid Gibson g_string_free(qemu_hypertas, TRUE); 9443f5dabceSDavid Gibson 9451eee9950SDaniel Henrique Barboza spapr_numa_write_rtas_dt(spapr, fdt, rtas); 946da9f80fbSSerhii Popovych 9470e236d34SNicholas Piggin /* 9480e236d34SNicholas Piggin * FWNMI reserves RTAS_ERROR_LOG_MAX for the machine check error log, 9490e236d34SNicholas Piggin * and 16 bytes per CPU for system reset error log plus an extra 8 bytes. 9500e236d34SNicholas Piggin * 9510e236d34SNicholas Piggin * The system reset requirements are driven by existing Linux and PowerVM 9520e236d34SNicholas Piggin * implementation which (contrary to PAPR) saves r3 in the error log 9530e236d34SNicholas Piggin * structure like machine check, so Linux expects to find the saved r3 9540e236d34SNicholas Piggin * value at the address in r3 upon FWNMI-enabled sreset interrupt (and 9550e236d34SNicholas Piggin * does not look at the error value). 9560e236d34SNicholas Piggin * 9570e236d34SNicholas Piggin * System reset interrupts are not subject to interlock like machine 9580e236d34SNicholas Piggin * check, so this memory area could be corrupted if the sreset is 9590e236d34SNicholas Piggin * interrupted by a machine check (or vice versa) if it was shared. To 9600e236d34SNicholas Piggin * prevent this, system reset uses per-CPU areas for the sreset save 9610e236d34SNicholas Piggin * area. A system reset that interrupts a system reset handler could 9620e236d34SNicholas Piggin * still overwrite this area, but Linux doesn't try to recover in that 9630e236d34SNicholas Piggin * case anyway. 9640e236d34SNicholas Piggin * 9650e236d34SNicholas Piggin * The extra 8 bytes is required because Linux's FWNMI error log check 9660e236d34SNicholas Piggin * is off-by-one. 9677381c5d1SAlexey Kardashevskiy * 9687381c5d1SAlexey Kardashevskiy * RTAS_MIN_SIZE is required for the RTAS blob itself. 9690e236d34SNicholas Piggin */ 9707381c5d1SAlexey Kardashevskiy _FDT(fdt_setprop_cell(fdt, rtas, "rtas-size", RTAS_MIN_SIZE + 9717381c5d1SAlexey Kardashevskiy RTAS_ERROR_LOG_MAX + 9727381c5d1SAlexey Kardashevskiy ms->smp.max_cpus * sizeof(uint64_t) * 2 + 9737381c5d1SAlexey Kardashevskiy sizeof(uint64_t))); 9743f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-error-log-max", 9753f5dabceSDavid Gibson RTAS_ERROR_LOG_MAX)); 9763f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-event-scan-rate", 9773f5dabceSDavid Gibson RTAS_EVENT_SCAN_RATE)); 9783f5dabceSDavid Gibson 9794f441474SDavid Gibson g_assert(msi_nonbroken); 9803f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,change-msix-capable", NULL, 0)); 9813f5dabceSDavid Gibson 9823f5dabceSDavid Gibson /* 9833f5dabceSDavid Gibson * According to PAPR, rtas ibm,os-term does not guarantee a return 9843f5dabceSDavid Gibson * back to the guest cpu. 9853f5dabceSDavid Gibson * 9863f5dabceSDavid Gibson * While an additional ibm,extended-os-term property indicates 9873f5dabceSDavid Gibson * that rtas call return will always occur. Set this property. 9883f5dabceSDavid Gibson */ 9893f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,extended-os-term", NULL, 0)); 9903f5dabceSDavid Gibson 9913f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,lrdr-capacity", 9923f5dabceSDavid Gibson lrdr_capacity, sizeof(lrdr_capacity))); 9933f5dabceSDavid Gibson 9943f5dabceSDavid Gibson spapr_dt_rtas_tokens(fdt, rtas); 9953f5dabceSDavid Gibson } 9963f5dabceSDavid Gibson 997db592b5bSCédric Le Goater /* 998db592b5bSCédric Le Goater * Prepare ibm,arch-vec-5-platform-support, which indicates the MMU 999db592b5bSCédric Le Goater * and the XIVE features that the guest may request and thus the valid 1000db592b5bSCédric Le Goater * values for bytes 23..26 of option vector 5: 1001db592b5bSCédric Le Goater */ 1002ce2918cbSDavid Gibson static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt, 1003db592b5bSCédric Le Goater int chosen) 10049fb4541fSSam Bobroff { 1005545d6e2bSSuraj Jitindar Singh PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); 1006545d6e2bSSuraj Jitindar Singh 1007f2b14e3aSCédric Le Goater char val[2 * 4] = { 1008ca62823bSDavid Gibson 23, 0x00, /* XICS / XIVE mode */ 10099fb4541fSSam Bobroff 24, 0x00, /* Hash/Radix, filled in below. */ 10109fb4541fSSam Bobroff 25, 0x00, /* Hash options: Segment Tables == no, GTSE == no. */ 10119fb4541fSSam Bobroff 26, 0x40, /* Radix options: GTSE == yes. */ 10129fb4541fSSam Bobroff }; 10139fb4541fSSam Bobroff 1014ca62823bSDavid Gibson if (spapr->irq->xics && spapr->irq->xive) { 1015ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_BOTH; 1016ca62823bSDavid Gibson } else if (spapr->irq->xive) { 1017ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_EXPLOIT; 1018ca62823bSDavid Gibson } else { 1019ca62823bSDavid Gibson assert(spapr->irq->xics); 1020ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_LEGACY; 1021ca62823bSDavid Gibson } 1022ca62823bSDavid Gibson 10237abd43baSSuraj Jitindar Singh if (!ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0, 10247abd43baSSuraj Jitindar Singh first_ppc_cpu->compat_pvr)) { 1025db592b5bSCédric Le Goater /* 1026db592b5bSCédric Le Goater * If we're in a pre POWER9 compat mode then the guest should 1027db592b5bSCédric Le Goater * do hash and use the legacy interrupt mode 1028db592b5bSCédric Le Goater */ 1029ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_LEGACY; /* XICS */ 10307abd43baSSuraj Jitindar Singh val[3] = 0x00; /* Hash */ 1031ab5add4cSFabiano Rosas spapr_check_mmu_mode(false); 10327abd43baSSuraj Jitindar Singh } else if (kvm_enabled()) { 10339fb4541fSSam Bobroff if (kvmppc_has_cap_mmu_radix() && kvmppc_has_cap_mmu_hash_v3()) { 1034f2b14e3aSCédric Le Goater val[3] = 0x80; /* OV5_MMU_BOTH */ 10359fb4541fSSam Bobroff } else if (kvmppc_has_cap_mmu_radix()) { 1036f2b14e3aSCédric Le Goater val[3] = 0x40; /* OV5_MMU_RADIX_300 */ 10379fb4541fSSam Bobroff } else { 1038f2b14e3aSCédric Le Goater val[3] = 0x00; /* Hash */ 10399fb4541fSSam Bobroff } 10409fb4541fSSam Bobroff } else { 10417abd43baSSuraj Jitindar Singh /* V3 MMU supports both hash and radix in tcg (with dynamic switching) */ 1042f2b14e3aSCédric Le Goater val[3] = 0xC0; 1043545d6e2bSSuraj Jitindar Singh } 10449fb4541fSSam Bobroff _FDT(fdt_setprop(fdt, chosen, "ibm,arch-vec-5-platform-support", 10459fb4541fSSam Bobroff val, sizeof(val))); 10469fb4541fSSam Bobroff } 10479fb4541fSSam Bobroff 10481e0e1108SDavid Gibson static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt, bool reset) 10497c866c6aSDavid Gibson { 10507c866c6aSDavid Gibson MachineState *machine = MACHINE(spapr); 10516c3829a2SAlexey Kardashevskiy SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 10527c866c6aSDavid Gibson int chosen; 10531e0e1108SDavid Gibson 10541e0e1108SDavid Gibson _FDT(chosen = fdt_add_subnode(fdt, 0, "chosen")); 10551e0e1108SDavid Gibson 10561e0e1108SDavid Gibson if (reset) { 10573bf0844fSGreg Kurz const char *boot_device = spapr->boot_device; 1058aebb9b9cSDaniel Henrique Barboza g_autofree char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus); 10597c866c6aSDavid Gibson size_t cb = 0; 1060aebb9b9cSDaniel Henrique Barboza g_autofree char *bootlist = get_boot_devices_list(&cb); 10617c866c6aSDavid Gibson 10625ced7895SAlexey Kardashevskiy if (machine->kernel_cmdline && machine->kernel_cmdline[0]) { 10635ced7895SAlexey Kardashevskiy _FDT(fdt_setprop_string(fdt, chosen, "bootargs", 10645ced7895SAlexey Kardashevskiy machine->kernel_cmdline)); 10655ced7895SAlexey Kardashevskiy } 10661e0e1108SDavid Gibson 10675ced7895SAlexey Kardashevskiy if (spapr->initrd_size) { 10687c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-start", 10697c866c6aSDavid Gibson spapr->initrd_base)); 10707c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-end", 10717c866c6aSDavid Gibson spapr->initrd_base + spapr->initrd_size)); 10725ced7895SAlexey Kardashevskiy } 10737c866c6aSDavid Gibson 10747c866c6aSDavid Gibson if (spapr->kernel_size) { 107587262806SAlexey Kardashevskiy uint64_t kprop[2] = { cpu_to_be64(spapr->kernel_addr), 10767c866c6aSDavid Gibson cpu_to_be64(spapr->kernel_size) }; 10777c866c6aSDavid Gibson 10787c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel", 10797c866c6aSDavid Gibson &kprop, sizeof(kprop))); 10807c866c6aSDavid Gibson if (spapr->kernel_le) { 10817c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel-le", NULL, 0)); 10827c866c6aSDavid Gibson } 10837c866c6aSDavid Gibson } 108497ec4d21SPaolo Bonzini if (machine->boot_config.has_menu && machine->boot_config.menu) { 108597ec4d21SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, chosen, "qemu,boot-menu", true))); 10867c866c6aSDavid Gibson } 10877c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-width", graphic_width)); 10887c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-height", graphic_height)); 10897c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-depth", graphic_depth)); 10907c866c6aSDavid Gibson 10917c866c6aSDavid Gibson if (cb && bootlist) { 10927c866c6aSDavid Gibson int i; 10937c866c6aSDavid Gibson 10947c866c6aSDavid Gibson for (i = 0; i < cb; i++) { 10957c866c6aSDavid Gibson if (bootlist[i] == '\n') { 10967c866c6aSDavid Gibson bootlist[i] = ' '; 10977c866c6aSDavid Gibson } 10987c866c6aSDavid Gibson } 10997c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-list", bootlist)); 11007c866c6aSDavid Gibson } 11017c866c6aSDavid Gibson 11027c866c6aSDavid Gibson if (boot_device && strlen(boot_device)) { 11037c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-device", boot_device)); 11047c866c6aSDavid Gibson } 11057c866c6aSDavid Gibson 1106f73eb948SPaolo Bonzini if (spapr->want_stdout_path && stdout_path) { 110790ee4e01SNikunj A Dadhania /* 11081e0e1108SDavid Gibson * "linux,stdout-path" and "stdout" properties are 11091e0e1108SDavid Gibson * deprecated by linux kernel. New platforms should only 11101e0e1108SDavid Gibson * use the "stdout-path" property. Set the new property 11111e0e1108SDavid Gibson * and continue using older property to remain compatible 11121e0e1108SDavid Gibson * with the existing firmware. 111390ee4e01SNikunj A Dadhania */ 11147c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "linux,stdout-path", stdout_path)); 111590ee4e01SNikunj A Dadhania _FDT(fdt_setprop_string(fdt, chosen, "stdout-path", stdout_path)); 11167c866c6aSDavid Gibson } 11177c866c6aSDavid Gibson 11181e0e1108SDavid Gibson /* 11191e0e1108SDavid Gibson * We can deal with BAR reallocation just fine, advertise it 11201e0e1108SDavid Gibson * to the guest 11211e0e1108SDavid Gibson */ 11226c3829a2SAlexey Kardashevskiy if (smc->linux_pci_probe) { 11236c3829a2SAlexey Kardashevskiy _FDT(fdt_setprop_cell(fdt, chosen, "linux,pci-probe-only", 0)); 11246c3829a2SAlexey Kardashevskiy } 11256c3829a2SAlexey Kardashevskiy 1126db592b5bSCédric Le Goater spapr_dt_ov5_platform_support(spapr, fdt, chosen); 11277c866c6aSDavid Gibson } 11287c866c6aSDavid Gibson 1129b27fcb28SNicholas Piggin _FDT(fdt_setprop(fdt, chosen, "rng-seed", spapr->fdt_rng_seed, 32)); 1130c4b07531SJason A. Donenfeld 113191335a5eSDavid Gibson _FDT(spapr_dt_ovec(fdt, chosen, spapr->ov5_cas, "ibm,architecture-vec-5")); 11321e0e1108SDavid Gibson } 11331e0e1108SDavid Gibson 1134ce2918cbSDavid Gibson static void spapr_dt_hypervisor(SpaprMachineState *spapr, void *fdt) 1135fca5f2dcSDavid Gibson { 1136fca5f2dcSDavid Gibson /* The /hypervisor node isn't in PAPR - this is a hack to allow PR 1137fca5f2dcSDavid Gibson * KVM to work under pHyp with some guest co-operation */ 1138fca5f2dcSDavid Gibson int hypervisor; 1139fca5f2dcSDavid Gibson uint8_t hypercall[16]; 1140fca5f2dcSDavid Gibson 1141fca5f2dcSDavid Gibson _FDT(hypervisor = fdt_add_subnode(fdt, 0, "hypervisor")); 1142fca5f2dcSDavid Gibson /* indicate KVM hypercall interface */ 1143fca5f2dcSDavid Gibson _FDT(fdt_setprop_string(fdt, hypervisor, "compatible", "linux,kvm")); 1144fca5f2dcSDavid Gibson if (kvmppc_has_cap_fixup_hcalls()) { 1145fca5f2dcSDavid Gibson /* 1146fca5f2dcSDavid Gibson * Older KVM versions with older guest kernels were broken 1147fca5f2dcSDavid Gibson * with the magic page, don't allow the guest to map it. 1148fca5f2dcSDavid Gibson */ 1149b77af26eSRichard Henderson if (!kvmppc_get_hypercall(cpu_env(first_cpu), hypercall, 1150fca5f2dcSDavid Gibson sizeof(hypercall))) { 1151fca5f2dcSDavid Gibson _FDT(fdt_setprop(fdt, hypervisor, "hcall-instructions", 1152fca5f2dcSDavid Gibson hypercall, sizeof(hypercall))); 1153fca5f2dcSDavid Gibson } 1154fca5f2dcSDavid Gibson } 1155fca5f2dcSDavid Gibson } 1156fca5f2dcSDavid Gibson 11570c21e073SDavid Gibson void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space) 115853018216SPaolo Bonzini { 1159c86c1affSDaniel Henrique Barboza MachineState *machine = MACHINE(spapr); 11603c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 1161ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 1162776e887fSGreg Kurz uint32_t root_drc_type_mask = 0; 11637c866c6aSDavid Gibson int ret; 116453018216SPaolo Bonzini void *fdt; 1165ce2918cbSDavid Gibson SpaprPhbState *phb; 1166398a0bd5SDavid Gibson char *buf; 116753018216SPaolo Bonzini 116897b32a6aSDavid Gibson fdt = g_malloc0(space); 116997b32a6aSDavid Gibson _FDT((fdt_create_empty_tree(fdt, space))); 117053018216SPaolo Bonzini 1171398a0bd5SDavid Gibson /* Root node */ 1172398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "device_type", "chrp")); 1173398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "model", "IBM pSeries (emulated by qemu)")); 1174398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "compatible", "qemu,pseries")); 1175398a0bd5SDavid Gibson 11760a794529SDavid Gibson /* Guest UUID & Name*/ 1177398a0bd5SDavid Gibson buf = qemu_uuid_unparse_strdup(&qemu_uuid); 1178398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "vm,uuid", buf)); 1179398a0bd5SDavid Gibson if (qemu_uuid_set) { 1180398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "system-id", buf)); 1181398a0bd5SDavid Gibson } 1182398a0bd5SDavid Gibson g_free(buf); 1183398a0bd5SDavid Gibson 1184398a0bd5SDavid Gibson if (qemu_get_vm_name()) { 1185398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "ibm,partition-name", 1186398a0bd5SDavid Gibson qemu_get_vm_name())); 1187398a0bd5SDavid Gibson } 1188398a0bd5SDavid Gibson 11890a794529SDavid Gibson /* Host Model & Serial Number */ 11900a794529SDavid Gibson if (spapr->host_model) { 11910a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model)); 11920a794529SDavid Gibson } else if (smc->broken_host_serial_model && kvmppc_get_host_model(&buf)) { 11930a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-model", buf)); 11940a794529SDavid Gibson g_free(buf); 11950a794529SDavid Gibson } 11960a794529SDavid Gibson 11970a794529SDavid Gibson if (spapr->host_serial) { 11980a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial)); 11990a794529SDavid Gibson } else if (smc->broken_host_serial_model && kvmppc_get_host_serial(&buf)) { 12000a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf)); 12010a794529SDavid Gibson g_free(buf); 12020a794529SDavid Gibson } 12030a794529SDavid Gibson 1204398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#address-cells", 2)); 1205398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2)); 120653018216SPaolo Bonzini 1207fc7e0765SDavid Gibson /* /interrupt controller */ 120805289273SDavid Gibson spapr_irq_dt(spapr, spapr_max_server_number(spapr), fdt, PHANDLE_INTC); 1209fc7e0765SDavid Gibson 121091335a5eSDavid Gibson ret = spapr_dt_memory(spapr, fdt); 1211e8f986fcSBharata B Rao if (ret < 0) { 1212ce9863b7SCédric Le Goater error_report("couldn't setup memory nodes in fdt"); 1213e8f986fcSBharata B Rao exit(1); 121453018216SPaolo Bonzini } 121553018216SPaolo Bonzini 1216bf5a6696SDavid Gibson /* /vdevice */ 1217bf5a6696SDavid Gibson spapr_dt_vdevice(spapr->vio_bus, fdt); 121853018216SPaolo Bonzini 12194d9392beSThomas Huth if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) { 122091335a5eSDavid Gibson ret = spapr_dt_rng(fdt); 12214d9392beSThomas Huth if (ret < 0) { 1222ce9863b7SCédric Le Goater error_report("could not set up rng device in the fdt"); 12234d9392beSThomas Huth exit(1); 12244d9392beSThomas Huth } 12254d9392beSThomas Huth } 12264d9392beSThomas Huth 122753018216SPaolo Bonzini QLIST_FOREACH(phb, &spapr->phbs, list) { 12288cbe71ecSDavid Gibson ret = spapr_dt_phb(spapr, phb, PHANDLE_INTC, fdt, NULL); 122953018216SPaolo Bonzini if (ret < 0) { 1230da34fed7SThomas Huth error_report("couldn't setup PCI devices in fdt"); 123153018216SPaolo Bonzini exit(1); 123253018216SPaolo Bonzini } 1233da34fed7SThomas Huth } 123453018216SPaolo Bonzini 123591335a5eSDavid Gibson spapr_dt_cpus(fdt, spapr); 123653018216SPaolo Bonzini 1237776e887fSGreg Kurz /* ibm,drc-indexes and friends */ 1238c20d332aSBharata B Rao if (smc->dr_lmb_enabled) { 1239776e887fSGreg Kurz root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_LMB; 1240776e887fSGreg Kurz } 1241776e887fSGreg Kurz if (smc->dr_phb_enabled) { 1242776e887fSGreg Kurz root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_PHB; 1243776e887fSGreg Kurz } 1244776e887fSGreg Kurz if (mc->nvdimm_supported) { 1245776e887fSGreg Kurz root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_PMEM; 1246776e887fSGreg Kurz } 1247776e887fSGreg Kurz if (root_drc_type_mask) { 1248776e887fSGreg Kurz _FDT(spapr_dt_drc(fdt, 0, NULL, root_drc_type_mask)); 1249c20d332aSBharata B Rao } 1250c20d332aSBharata B Rao 1251c5514d0eSIgor Mammedov if (mc->has_hotpluggable_cpus) { 1252af81cf32SBharata B Rao int offset = fdt_path_offset(fdt, "/cpus"); 12539e7d38e8SDavid Gibson ret = spapr_dt_drc(fdt, offset, NULL, SPAPR_DR_CONNECTOR_TYPE_CPU); 1254af81cf32SBharata B Rao if (ret < 0) { 1255af81cf32SBharata B Rao error_report("Couldn't set up CPU DR device tree properties"); 1256af81cf32SBharata B Rao exit(1); 1257af81cf32SBharata B Rao } 1258af81cf32SBharata B Rao } 1259af81cf32SBharata B Rao 1260ffb1e275SDavid Gibson /* /event-sources */ 1261ffbb1705SMichael Roth spapr_dt_events(spapr, fdt); 1262ffb1e275SDavid Gibson 12633f5dabceSDavid Gibson /* /rtas */ 12643f5dabceSDavid Gibson spapr_dt_rtas(spapr, fdt); 12653f5dabceSDavid Gibson 12667c866c6aSDavid Gibson /* /chosen */ 12671e0e1108SDavid Gibson spapr_dt_chosen(spapr, fdt, reset); 1268cf6e5223SDavid Gibson 1269fca5f2dcSDavid Gibson /* /hypervisor */ 1270fca5f2dcSDavid Gibson if (kvm_enabled()) { 1271fca5f2dcSDavid Gibson spapr_dt_hypervisor(spapr, fdt); 1272fca5f2dcSDavid Gibson } 1273fca5f2dcSDavid Gibson 1274cf6e5223SDavid Gibson /* Build memory reserve map */ 1275a49f62b9SAlexey Kardashevskiy if (reset) { 1276cf6e5223SDavid Gibson if (spapr->kernel_size) { 127787262806SAlexey Kardashevskiy _FDT((fdt_add_mem_rsv(fdt, spapr->kernel_addr, 127887262806SAlexey Kardashevskiy spapr->kernel_size))); 1279cf6e5223SDavid Gibson } 1280cf6e5223SDavid Gibson if (spapr->initrd_size) { 1281a49f62b9SAlexey Kardashevskiy _FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base, 1282a49f62b9SAlexey Kardashevskiy spapr->initrd_size))); 1283a49f62b9SAlexey Kardashevskiy } 1284cf6e5223SDavid Gibson } 1285cf6e5223SDavid Gibson 1286ee3a71e3SShivaprasad G Bhat /* NVDIMM devices */ 1287ee3a71e3SShivaprasad G Bhat if (mc->nvdimm_supported) { 1288f1aa45ffSDaniel Henrique Barboza spapr_dt_persistent_memory(spapr, fdt); 1289ee3a71e3SShivaprasad G Bhat } 1290ee3a71e3SShivaprasad G Bhat 1291997b6cfcSDavid Gibson return fdt; 129253018216SPaolo Bonzini } 129353018216SPaolo Bonzini 129453018216SPaolo Bonzini static uint64_t translate_kernel_address(void *opaque, uint64_t addr) 129553018216SPaolo Bonzini { 129687262806SAlexey Kardashevskiy SpaprMachineState *spapr = opaque; 129787262806SAlexey Kardashevskiy 129887262806SAlexey Kardashevskiy return (addr & 0x0fffffff) + spapr->kernel_addr; 129953018216SPaolo Bonzini } 130053018216SPaolo Bonzini 13011d1be34dSDavid Gibson static void emulate_spapr_hypercall(PPCVirtualHypervisor *vhyp, 13021d1be34dSDavid Gibson PowerPCCPU *cpu) 130353018216SPaolo Bonzini { 130453018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 130553018216SPaolo Bonzini 13068d04fb55SJan Kiszka /* The TCG path should also be holding the BQL at this point */ 13078d04fb55SJan Kiszka g_assert(qemu_mutex_iothread_locked()); 13088d04fb55SJan Kiszka 1309120f738aSNicholas Piggin g_assert(!vhyp_cpu_in_nested(cpu)); 1310120f738aSNicholas Piggin 1311d41ccf6eSVíctor Colombo if (FIELD_EX64(env->msr, MSR, PR)) { 131253018216SPaolo Bonzini hcall_dprintf("Hypercall made with MSR[PR]=1\n"); 131353018216SPaolo Bonzini env->gpr[3] = H_PRIVILEGE; 131453018216SPaolo Bonzini } else { 131553018216SPaolo Bonzini env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]); 131653018216SPaolo Bonzini } 131753018216SPaolo Bonzini } 131853018216SPaolo Bonzini 131900fd075eSBenjamin Herrenschmidt struct LPCRSyncState { 132000fd075eSBenjamin Herrenschmidt target_ulong value; 132100fd075eSBenjamin Herrenschmidt target_ulong mask; 132200fd075eSBenjamin Herrenschmidt }; 132300fd075eSBenjamin Herrenschmidt 132400fd075eSBenjamin Herrenschmidt static void do_lpcr_sync(CPUState *cs, run_on_cpu_data arg) 132500fd075eSBenjamin Herrenschmidt { 132600fd075eSBenjamin Herrenschmidt struct LPCRSyncState *s = arg.host_ptr; 132700fd075eSBenjamin Herrenschmidt PowerPCCPU *cpu = POWERPC_CPU(cs); 132800fd075eSBenjamin Herrenschmidt CPUPPCState *env = &cpu->env; 132900fd075eSBenjamin Herrenschmidt target_ulong lpcr; 133000fd075eSBenjamin Herrenschmidt 133100fd075eSBenjamin Herrenschmidt cpu_synchronize_state(cs); 133200fd075eSBenjamin Herrenschmidt lpcr = env->spr[SPR_LPCR]; 133300fd075eSBenjamin Herrenschmidt lpcr &= ~s->mask; 133400fd075eSBenjamin Herrenschmidt lpcr |= s->value; 133500fd075eSBenjamin Herrenschmidt ppc_store_lpcr(cpu, lpcr); 133600fd075eSBenjamin Herrenschmidt } 133700fd075eSBenjamin Herrenschmidt 133800fd075eSBenjamin Herrenschmidt void spapr_set_all_lpcrs(target_ulong value, target_ulong mask) 133900fd075eSBenjamin Herrenschmidt { 134000fd075eSBenjamin Herrenschmidt CPUState *cs; 134100fd075eSBenjamin Herrenschmidt struct LPCRSyncState s = { 134200fd075eSBenjamin Herrenschmidt .value = value, 134300fd075eSBenjamin Herrenschmidt .mask = mask 134400fd075eSBenjamin Herrenschmidt }; 134500fd075eSBenjamin Herrenschmidt CPU_FOREACH(cs) { 134600fd075eSBenjamin Herrenschmidt run_on_cpu(cs, do_lpcr_sync, RUN_ON_CPU_HOST_PTR(&s)); 134700fd075eSBenjamin Herrenschmidt } 134800fd075eSBenjamin Herrenschmidt } 134900fd075eSBenjamin Herrenschmidt 13509c7b7f01SNicholas Piggin /* May be used when the machine is not running */ 13519c7b7f01SNicholas Piggin void spapr_init_all_lpcrs(target_ulong value, target_ulong mask) 13529c7b7f01SNicholas Piggin { 13539c7b7f01SNicholas Piggin CPUState *cs; 13549c7b7f01SNicholas Piggin CPU_FOREACH(cs) { 13559c7b7f01SNicholas Piggin PowerPCCPU *cpu = POWERPC_CPU(cs); 13569c7b7f01SNicholas Piggin CPUPPCState *env = &cpu->env; 13579c7b7f01SNicholas Piggin target_ulong lpcr; 13589c7b7f01SNicholas Piggin 13599c7b7f01SNicholas Piggin lpcr = env->spr[SPR_LPCR]; 13609c7b7f01SNicholas Piggin lpcr &= ~(LPCR_HR | LPCR_UPRT); 13619c7b7f01SNicholas Piggin ppc_store_lpcr(cpu, lpcr); 13629c7b7f01SNicholas Piggin } 13639c7b7f01SNicholas Piggin } 13649c7b7f01SNicholas Piggin 13659c7b7f01SNicholas Piggin 1366f32d4ab4SNicholas Piggin static bool spapr_get_pate(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu, 1367f32d4ab4SNicholas Piggin target_ulong lpid, ppc_v3_pate_t *entry) 13689861bb3eSSuraj Jitindar Singh { 1369ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1370120f738aSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 13719861bb3eSSuraj Jitindar Singh 1372120f738aSNicholas Piggin if (!spapr_cpu->in_nested) { 1373f32d4ab4SNicholas Piggin assert(lpid == 0); 1374f32d4ab4SNicholas Piggin 137579825f4dSBenjamin Herrenschmidt /* Copy PATE1:GR into PATE0:HR */ 137679825f4dSBenjamin Herrenschmidt entry->dw0 = spapr->patb_entry & PATE0_HR; 137779825f4dSBenjamin Herrenschmidt entry->dw1 = spapr->patb_entry; 1378f32d4ab4SNicholas Piggin 1379120f738aSNicholas Piggin } else { 1380120f738aSNicholas Piggin uint64_t patb, pats; 1381120f738aSNicholas Piggin 1382120f738aSNicholas Piggin assert(lpid != 0); 1383120f738aSNicholas Piggin 1384120f738aSNicholas Piggin patb = spapr->nested_ptcr & PTCR_PATB; 1385120f738aSNicholas Piggin pats = spapr->nested_ptcr & PTCR_PATS; 1386120f738aSNicholas Piggin 13873c2e80adSLeandro Lupori /* Check if partition table is properly aligned */ 13883c2e80adSLeandro Lupori if (patb & MAKE_64BIT_MASK(0, pats + 12)) { 13893c2e80adSLeandro Lupori return false; 13903c2e80adSLeandro Lupori } 13913c2e80adSLeandro Lupori 1392120f738aSNicholas Piggin /* Calculate number of entries */ 1393120f738aSNicholas Piggin pats = 1ull << (pats + 12 - 4); 1394120f738aSNicholas Piggin if (pats <= lpid) { 1395120f738aSNicholas Piggin return false; 1396120f738aSNicholas Piggin } 1397120f738aSNicholas Piggin 1398120f738aSNicholas Piggin /* Grab entry */ 1399120f738aSNicholas Piggin patb += 16 * lpid; 1400120f738aSNicholas Piggin entry->dw0 = ldq_phys(CPU(cpu)->as, patb); 1401120f738aSNicholas Piggin entry->dw1 = ldq_phys(CPU(cpu)->as, patb + 8); 1402120f738aSNicholas Piggin } 1403120f738aSNicholas Piggin 1404f32d4ab4SNicholas Piggin return true; 14059861bb3eSSuraj Jitindar Singh } 14069861bb3eSSuraj Jitindar Singh 1407e6b8fd24SSamuel Mendoza-Jonas #define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2)) 1408e6b8fd24SSamuel Mendoza-Jonas #define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID) 1409e6b8fd24SSamuel Mendoza-Jonas #define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY) 1410e6b8fd24SSamuel Mendoza-Jonas #define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY)) 1411e6b8fd24SSamuel Mendoza-Jonas #define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY)) 1412e6b8fd24SSamuel Mendoza-Jonas 1413715c5407SDavid Gibson /* 1414715c5407SDavid Gibson * Get the fd to access the kernel htab, re-opening it if necessary 1415715c5407SDavid Gibson */ 1416ce2918cbSDavid Gibson static int get_htab_fd(SpaprMachineState *spapr) 1417715c5407SDavid Gibson { 141814b0d748SGreg Kurz Error *local_err = NULL; 141914b0d748SGreg Kurz 1420715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1421715c5407SDavid Gibson return spapr->htab_fd; 1422715c5407SDavid Gibson } 1423715c5407SDavid Gibson 142414b0d748SGreg Kurz spapr->htab_fd = kvmppc_get_htab_fd(false, 0, &local_err); 1425715c5407SDavid Gibson if (spapr->htab_fd < 0) { 142614b0d748SGreg Kurz error_report_err(local_err); 1427715c5407SDavid Gibson } 1428715c5407SDavid Gibson 1429715c5407SDavid Gibson return spapr->htab_fd; 1430715c5407SDavid Gibson } 1431715c5407SDavid Gibson 1432ce2918cbSDavid Gibson void close_htab_fd(SpaprMachineState *spapr) 1433715c5407SDavid Gibson { 1434715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1435715c5407SDavid Gibson close(spapr->htab_fd); 1436715c5407SDavid Gibson } 1437715c5407SDavid Gibson spapr->htab_fd = -1; 1438715c5407SDavid Gibson } 1439715c5407SDavid Gibson 1440e57ca75cSDavid Gibson static hwaddr spapr_hpt_mask(PPCVirtualHypervisor *vhyp) 1441e57ca75cSDavid Gibson { 1442ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1443e57ca75cSDavid Gibson 1444e57ca75cSDavid Gibson return HTAB_SIZE(spapr) / HASH_PTEG_SIZE_64 - 1; 1445e57ca75cSDavid Gibson } 1446e57ca75cSDavid Gibson 14471ec26c75SGreg Kurz static target_ulong spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp) 14481ec26c75SGreg Kurz { 1449ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 14501ec26c75SGreg Kurz 14511ec26c75SGreg Kurz assert(kvm_enabled()); 14521ec26c75SGreg Kurz 14531ec26c75SGreg Kurz if (!spapr->htab) { 14541ec26c75SGreg Kurz return 0; 14551ec26c75SGreg Kurz } 14561ec26c75SGreg Kurz 14571ec26c75SGreg Kurz return (target_ulong)(uintptr_t)spapr->htab | (spapr->htab_shift - 18); 14581ec26c75SGreg Kurz } 14591ec26c75SGreg Kurz 1460e57ca75cSDavid Gibson static const ppc_hash_pte64_t *spapr_map_hptes(PPCVirtualHypervisor *vhyp, 1461e57ca75cSDavid Gibson hwaddr ptex, int n) 1462e57ca75cSDavid Gibson { 1463ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1464e57ca75cSDavid Gibson hwaddr pte_offset = ptex * HASH_PTE_SIZE_64; 1465e57ca75cSDavid Gibson 1466e57ca75cSDavid Gibson if (!spapr->htab) { 1467e57ca75cSDavid Gibson /* 1468e57ca75cSDavid Gibson * HTAB is controlled by KVM. Fetch into temporary buffer 1469e57ca75cSDavid Gibson */ 1470e57ca75cSDavid Gibson ppc_hash_pte64_t *hptes = g_malloc(n * HASH_PTE_SIZE_64); 1471e57ca75cSDavid Gibson kvmppc_read_hptes(hptes, ptex, n); 1472e57ca75cSDavid Gibson return hptes; 1473e57ca75cSDavid Gibson } 1474e57ca75cSDavid Gibson 1475e57ca75cSDavid Gibson /* 1476e57ca75cSDavid Gibson * HTAB is controlled by QEMU. Just point to the internally 1477e57ca75cSDavid Gibson * accessible PTEG. 1478e57ca75cSDavid Gibson */ 1479e57ca75cSDavid Gibson return (const ppc_hash_pte64_t *)(spapr->htab + pte_offset); 1480e57ca75cSDavid Gibson } 1481e57ca75cSDavid Gibson 1482e57ca75cSDavid Gibson static void spapr_unmap_hptes(PPCVirtualHypervisor *vhyp, 1483e57ca75cSDavid Gibson const ppc_hash_pte64_t *hptes, 1484e57ca75cSDavid Gibson hwaddr ptex, int n) 1485e57ca75cSDavid Gibson { 1486ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1487e57ca75cSDavid Gibson 1488e57ca75cSDavid Gibson if (!spapr->htab) { 1489e57ca75cSDavid Gibson g_free((void *)hptes); 1490e57ca75cSDavid Gibson } 1491e57ca75cSDavid Gibson 1492e57ca75cSDavid Gibson /* Nothing to do for qemu managed HPT */ 1493e57ca75cSDavid Gibson } 1494e57ca75cSDavid Gibson 1495a2dd4e83SBenjamin Herrenschmidt void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex, 1496e57ca75cSDavid Gibson uint64_t pte0, uint64_t pte1) 1497e57ca75cSDavid Gibson { 1498a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(cpu->vhyp); 1499e57ca75cSDavid Gibson hwaddr offset = ptex * HASH_PTE_SIZE_64; 1500e57ca75cSDavid Gibson 1501e57ca75cSDavid Gibson if (!spapr->htab) { 1502e57ca75cSDavid Gibson kvmppc_write_hpte(ptex, pte0, pte1); 1503e57ca75cSDavid Gibson } else { 15043054b0caSBenjamin Herrenschmidt if (pte0 & HPTE64_V_VALID) { 15057bf00dfbSLeandro Lupori stq_p(spapr->htab + offset + HPTE64_DW1, pte1); 15063054b0caSBenjamin Herrenschmidt /* 15073054b0caSBenjamin Herrenschmidt * When setting valid, we write PTE1 first. This ensures 15083054b0caSBenjamin Herrenschmidt * proper synchronization with the reading code in 15093054b0caSBenjamin Herrenschmidt * ppc_hash64_pteg_search() 15103054b0caSBenjamin Herrenschmidt */ 15113054b0caSBenjamin Herrenschmidt smp_wmb(); 15123054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset, pte0); 15133054b0caSBenjamin Herrenschmidt } else { 15143054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset, pte0); 15153054b0caSBenjamin Herrenschmidt /* 15163054b0caSBenjamin Herrenschmidt * When clearing it we set PTE0 first. This ensures proper 15173054b0caSBenjamin Herrenschmidt * synchronization with the reading code in 15183054b0caSBenjamin Herrenschmidt * ppc_hash64_pteg_search() 15193054b0caSBenjamin Herrenschmidt */ 15203054b0caSBenjamin Herrenschmidt smp_wmb(); 15217bf00dfbSLeandro Lupori stq_p(spapr->htab + offset + HPTE64_DW1, pte1); 15223054b0caSBenjamin Herrenschmidt } 1523e57ca75cSDavid Gibson } 1524e57ca75cSDavid Gibson } 1525e57ca75cSDavid Gibson 1526a2dd4e83SBenjamin Herrenschmidt static void spapr_hpte_set_c(PPCVirtualHypervisor *vhyp, hwaddr ptex, 1527a2dd4e83SBenjamin Herrenschmidt uint64_t pte1) 1528a2dd4e83SBenjamin Herrenschmidt { 15297bf00dfbSLeandro Lupori hwaddr offset = ptex * HASH_PTE_SIZE_64 + HPTE64_DW1_C; 1530a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1531a2dd4e83SBenjamin Herrenschmidt 1532a2dd4e83SBenjamin Herrenschmidt if (!spapr->htab) { 1533a2dd4e83SBenjamin Herrenschmidt /* There should always be a hash table when this is called */ 1534a2dd4e83SBenjamin Herrenschmidt error_report("spapr_hpte_set_c called with no hash table !"); 1535a2dd4e83SBenjamin Herrenschmidt return; 1536a2dd4e83SBenjamin Herrenschmidt } 1537a2dd4e83SBenjamin Herrenschmidt 1538a2dd4e83SBenjamin Herrenschmidt /* The HW performs a non-atomic byte update */ 1539a2dd4e83SBenjamin Herrenschmidt stb_p(spapr->htab + offset, (pte1 & 0xff) | 0x80); 1540a2dd4e83SBenjamin Herrenschmidt } 1541a2dd4e83SBenjamin Herrenschmidt 1542a2dd4e83SBenjamin Herrenschmidt static void spapr_hpte_set_r(PPCVirtualHypervisor *vhyp, hwaddr ptex, 1543a2dd4e83SBenjamin Herrenschmidt uint64_t pte1) 1544a2dd4e83SBenjamin Herrenschmidt { 15457bf00dfbSLeandro Lupori hwaddr offset = ptex * HASH_PTE_SIZE_64 + HPTE64_DW1_R; 1546a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); 1547a2dd4e83SBenjamin Herrenschmidt 1548a2dd4e83SBenjamin Herrenschmidt if (!spapr->htab) { 1549a2dd4e83SBenjamin Herrenschmidt /* There should always be a hash table when this is called */ 1550a2dd4e83SBenjamin Herrenschmidt error_report("spapr_hpte_set_r called with no hash table !"); 1551a2dd4e83SBenjamin Herrenschmidt return; 1552a2dd4e83SBenjamin Herrenschmidt } 1553a2dd4e83SBenjamin Herrenschmidt 1554a2dd4e83SBenjamin Herrenschmidt /* The HW performs a non-atomic byte update */ 1555a2dd4e83SBenjamin Herrenschmidt stb_p(spapr->htab + offset, ((pte1 >> 8) & 0xff) | 0x01); 1556a2dd4e83SBenjamin Herrenschmidt } 1557a2dd4e83SBenjamin Herrenschmidt 15580b0b8310SDavid Gibson int spapr_hpt_shift_for_ramsize(uint64_t ramsize) 15598dfe8e7fSDavid Gibson { 15608dfe8e7fSDavid Gibson int shift; 15618dfe8e7fSDavid Gibson 15628dfe8e7fSDavid Gibson /* We aim for a hash table of size 1/128 the size of RAM (rounded 15638dfe8e7fSDavid Gibson * up). The PAPR recommendation is actually 1/64 of RAM size, but 15648dfe8e7fSDavid Gibson * that's much more than is needed for Linux guests */ 15658dfe8e7fSDavid Gibson shift = ctz64(pow2ceil(ramsize)) - 7; 15668dfe8e7fSDavid Gibson shift = MAX(shift, 18); /* Minimum architected size */ 15678dfe8e7fSDavid Gibson shift = MIN(shift, 46); /* Maximum architected size */ 15688dfe8e7fSDavid Gibson return shift; 15698dfe8e7fSDavid Gibson } 15708dfe8e7fSDavid Gibson 1571ce2918cbSDavid Gibson void spapr_free_hpt(SpaprMachineState *spapr) 157206ec79e8SBharata B Rao { 1573cb5b5ab9SXuzhou Cheng qemu_vfree(spapr->htab); 157406ec79e8SBharata B Rao spapr->htab = NULL; 157506ec79e8SBharata B Rao spapr->htab_shift = 0; 157606ec79e8SBharata B Rao close_htab_fd(spapr); 157706ec79e8SBharata B Rao } 157806ec79e8SBharata B Rao 1579a4e3a7c0SGreg Kurz int spapr_reallocate_hpt(SpaprMachineState *spapr, int shift, Error **errp) 158053018216SPaolo Bonzini { 1581c3e051edSGreg Kurz ERRP_GUARD(); 1582c5f54f3eSDavid Gibson long rc; 158353018216SPaolo Bonzini 1584c5f54f3eSDavid Gibson /* Clean up any HPT info from a previous boot */ 158506ec79e8SBharata B Rao spapr_free_hpt(spapr); 158653018216SPaolo Bonzini 1587c5f54f3eSDavid Gibson rc = kvmppc_reset_htab(shift); 1588f0638a0bSFabiano Rosas 1589f0638a0bSFabiano Rosas if (rc == -EOPNOTSUPP) { 1590f0638a0bSFabiano Rosas error_setg(errp, "HPT not supported in nested guests"); 1591a4e3a7c0SGreg Kurz return -EOPNOTSUPP; 1592f0638a0bSFabiano Rosas } 1593f0638a0bSFabiano Rosas 1594c5f54f3eSDavid Gibson if (rc < 0) { 1595c5f54f3eSDavid Gibson /* kernel-side HPT needed, but couldn't allocate one */ 1596c3e051edSGreg Kurz error_setg_errno(errp, errno, "Failed to allocate KVM HPT of order %d", 1597c5f54f3eSDavid Gibson shift); 1598c3e051edSGreg Kurz error_append_hint(errp, "Try smaller maxmem?\n"); 1599a4e3a7c0SGreg Kurz return -errno; 1600c5f54f3eSDavid Gibson } else if (rc > 0) { 1601c5f54f3eSDavid Gibson /* kernel-side HPT allocated */ 1602c5f54f3eSDavid Gibson if (rc != shift) { 1603c5f54f3eSDavid Gibson error_setg(errp, 1604c3e051edSGreg Kurz "Requested order %d HPT, but kernel allocated order %ld", 1605c5f54f3eSDavid Gibson shift, rc); 1606c3e051edSGreg Kurz error_append_hint(errp, "Try smaller maxmem?\n"); 1607a4e3a7c0SGreg Kurz return -ENOSPC; 16087735fedaSBharata B Rao } 16097735fedaSBharata B Rao 161053018216SPaolo Bonzini spapr->htab_shift = shift; 1611c18ad9a5SDavid Gibson spapr->htab = NULL; 1612b817772aSBharata B Rao } else { 1613c5f54f3eSDavid Gibson /* kernel-side HPT not needed, allocate in userspace instead */ 1614c5f54f3eSDavid Gibson size_t size = 1ULL << shift; 1615c5f54f3eSDavid Gibson int i; 161601a57972SSamuel Mendoza-Jonas 1617c5f54f3eSDavid Gibson spapr->htab = qemu_memalign(size, size); 1618c5f54f3eSDavid Gibson memset(spapr->htab, 0, size); 1619c5f54f3eSDavid Gibson spapr->htab_shift = shift; 1620b817772aSBharata B Rao 1621c5f54f3eSDavid Gibson for (i = 0; i < size / HASH_PTE_SIZE_64; i++) { 1622c5f54f3eSDavid Gibson DIRTY_HPTE(HPTE(spapr->htab, i)); 16237735fedaSBharata B Rao } 162453018216SPaolo Bonzini } 1625ee4d9eccSSuraj Jitindar Singh /* We're setting up a hash table, so that means we're not radix */ 1626176dcceeSSuraj Jitindar Singh spapr->patb_entry = 0; 16279c7b7f01SNicholas Piggin spapr_init_all_lpcrs(0, LPCR_HR | LPCR_UPRT); 1628a4e3a7c0SGreg Kurz return 0; 162953018216SPaolo Bonzini } 163053018216SPaolo Bonzini 16318897ea5aSDavid Gibson void spapr_setup_hpt(SpaprMachineState *spapr) 1632b4db5413SSuraj Jitindar Singh { 16332772cf6bSDavid Gibson int hpt_shift; 16342772cf6bSDavid Gibson 1635087820e3SGreg Kurz if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DISABLED) { 16362772cf6bSDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(MACHINE(spapr)->maxram_size); 16372772cf6bSDavid Gibson } else { 1638768a20f3SDavid Gibson uint64_t current_ram_size; 1639768a20f3SDavid Gibson 1640768a20f3SDavid Gibson current_ram_size = MACHINE(spapr)->ram_size + get_plugged_memory_size(); 1641768a20f3SDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(current_ram_size); 16422772cf6bSDavid Gibson } 16432772cf6bSDavid Gibson spapr_reallocate_hpt(spapr, hpt_shift, &error_fatal); 16442772cf6bSDavid Gibson 16458897ea5aSDavid Gibson if (kvm_enabled()) { 16466a84737cSDavid Gibson hwaddr vrma_limit = kvmppc_vrma_limit(spapr->htab_shift); 16476a84737cSDavid Gibson 16488897ea5aSDavid Gibson /* Check our RMA fits in the possible VRMA */ 16498897ea5aSDavid Gibson if (vrma_limit < spapr->rma_size) { 16508897ea5aSDavid Gibson error_report("Unable to create %" HWADDR_PRIu 16518897ea5aSDavid Gibson "MiB RMA (VRMA only allows %" HWADDR_PRIu "MiB", 16528897ea5aSDavid Gibson spapr->rma_size / MiB, vrma_limit / MiB); 16538897ea5aSDavid Gibson exit(EXIT_FAILURE); 16548897ea5aSDavid Gibson } 1655b4db5413SSuraj Jitindar Singh } 1656b4db5413SSuraj Jitindar Singh } 1657b4db5413SSuraj Jitindar Singh 1658068479e1SFabiano Rosas void spapr_check_mmu_mode(bool guest_radix) 1659068479e1SFabiano Rosas { 1660068479e1SFabiano Rosas if (guest_radix) { 1661068479e1SFabiano Rosas if (kvm_enabled() && !kvmppc_has_cap_mmu_radix()) { 1662068479e1SFabiano Rosas error_report("Guest requested unavailable MMU mode (radix)."); 1663068479e1SFabiano Rosas exit(EXIT_FAILURE); 1664068479e1SFabiano Rosas } 1665068479e1SFabiano Rosas } else { 1666068479e1SFabiano Rosas if (kvm_enabled() && kvmppc_has_cap_mmu_radix() 1667068479e1SFabiano Rosas && !kvmppc_has_cap_mmu_hash_v3()) { 1668068479e1SFabiano Rosas error_report("Guest requested unavailable MMU mode (hash)."); 1669068479e1SFabiano Rosas exit(EXIT_FAILURE); 1670068479e1SFabiano Rosas } 1671068479e1SFabiano Rosas } 1672068479e1SFabiano Rosas } 1673068479e1SFabiano Rosas 16747966d70fSJason A. Donenfeld static void spapr_machine_reset(MachineState *machine, ShutdownCause reason) 167553018216SPaolo Bonzini { 1676ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(machine); 1677182735efSAndreas Färber PowerPCCPU *first_ppc_cpu; 1678744a928cSAlexey Kardashevskiy hwaddr fdt_addr; 1679997b6cfcSDavid Gibson void *fdt; 1680997b6cfcSDavid Gibson int rc; 1681259186a7SAndreas Färber 1682b27fcb28SNicholas Piggin if (reason != SHUTDOWN_CAUSE_SNAPSHOT_LOAD) { 1683b27fcb28SNicholas Piggin /* 1684b27fcb28SNicholas Piggin * Record-replay snapshot load must not consume random, this was 1685b27fcb28SNicholas Piggin * already replayed from initial machine reset. 1686b27fcb28SNicholas Piggin */ 1687b27fcb28SNicholas Piggin qemu_guest_getrandom_nofail(spapr->fdt_rng_seed, 32); 1688b27fcb28SNicholas Piggin } 1689b27fcb28SNicholas Piggin 16906c8ebe30SDavid Gibson pef_kvm_reset(machine->cgs, &error_fatal); 16919f6edd06SDavid Gibson spapr_caps_apply(spapr); 169233face6bSDavid Gibson 16931481fe5fSLaurent Vivier first_ppc_cpu = POWERPC_CPU(first_cpu); 16941481fe5fSLaurent Vivier if (kvm_enabled() && kvmppc_has_cap_mmu_radix() && 1695ad99d04cSDavid Gibson ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, 16961481fe5fSLaurent Vivier spapr->max_compat_pvr)) { 169779825f4dSBenjamin Herrenschmidt /* 169879825f4dSBenjamin Herrenschmidt * If using KVM with radix mode available, VCPUs can be started 1699b4db5413SSuraj Jitindar Singh * without a HPT because KVM will start them in radix mode. 170079825f4dSBenjamin Herrenschmidt * Set the GR bit in PATE so that we know there is no HPT. 170179825f4dSBenjamin Herrenschmidt */ 170279825f4dSBenjamin Herrenschmidt spapr->patb_entry = PATE1_GR; 170300fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(LPCR_HR | LPCR_UPRT, LPCR_HR | LPCR_UPRT); 1704b4db5413SSuraj Jitindar Singh } else { 17058897ea5aSDavid Gibson spapr_setup_hpt(spapr); 1706c5f54f3eSDavid Gibson } 170753018216SPaolo Bonzini 17087966d70fSJason A. Donenfeld qemu_devices_reset(reason); 170925c9780dSDavid Gibson 17109012a53fSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas); 17119012a53fSGreg Kurz spapr->ov5_cas = spapr_ovec_new(); 17129012a53fSGreg Kurz 17139c7b7f01SNicholas Piggin ppc_init_compat_all(spapr->max_compat_pvr, &error_fatal); 17149012a53fSGreg Kurz 1715ec132efaSAlexey Kardashevskiy /* 1716b2e22477SCédric Le Goater * This is fixing some of the default configuration of the XIVE 1717b2e22477SCédric Le Goater * devices. To be called after the reset of the machine devices. 1718b2e22477SCédric Le Goater */ 1719b2e22477SCédric Le Goater spapr_irq_reset(spapr, &error_fatal); 1720b2e22477SCédric Le Goater 172123ff81bdSGreg Kurz /* 172223ff81bdSGreg Kurz * There is no CAS under qtest. Simulate one to please the code that 172323ff81bdSGreg Kurz * depends on spapr->ov5_cas. This is especially needed to test device 172423ff81bdSGreg Kurz * unplug, so we do that before resetting the DRCs. 172523ff81bdSGreg Kurz */ 172623ff81bdSGreg Kurz if (qtest_enabled()) { 172723ff81bdSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas); 172823ff81bdSGreg Kurz spapr->ov5_cas = spapr_ovec_clone(spapr->ov5); 172923ff81bdSGreg Kurz } 173023ff81bdSGreg Kurz 1731b5513584SShivaprasad G Bhat spapr_nvdimm_finish_flushes(); 1732b5513584SShivaprasad G Bhat 173382512483SGreg Kurz /* DRC reset may cause a device to be unplugged. This will cause troubles 173482512483SGreg Kurz * if this device is used by another device (eg, a running vhost backend 173582512483SGreg Kurz * will crash QEMU if the DIMM holding the vring goes away). To avoid such 173682512483SGreg Kurz * situations, we reset DRCs after all devices have been reset. 173782512483SGreg Kurz */ 173811055041SGreg Kurz spapr_drc_reset_all(spapr); 173982512483SGreg Kurz 174056258174SDaniel Henrique Barboza spapr_clear_pending_events(spapr); 174153018216SPaolo Bonzini 1742b7d1f77aSBenjamin Herrenschmidt /* 17434b98e72dSAlexey Kardashevskiy * We place the device tree just below either the top of the RMA, 1744df269271SAlexey Kardashevskiy * or just below 2GB, whichever is lower, so that it can be 1745b7d1f77aSBenjamin Herrenschmidt * processed with 32-bit real mode code if necessary 1746b7d1f77aSBenjamin Herrenschmidt */ 17474b98e72dSAlexey Kardashevskiy fdt_addr = MIN(spapr->rma_size, FDT_MAX_ADDR) - FDT_MAX_SIZE; 1748b7d1f77aSBenjamin Herrenschmidt 174997b32a6aSDavid Gibson fdt = spapr_build_fdt(spapr, true, FDT_MAX_SIZE); 1750fc8c745dSAlexey Kardashevskiy if (spapr->vof) { 175121bde1ecSAlexey Kardashevskiy spapr_vof_reset(spapr, fdt, &error_fatal); 1752fc8c745dSAlexey Kardashevskiy /* 1753fc8c745dSAlexey Kardashevskiy * Do not pack the FDT as the client may change properties. 1754fc8c745dSAlexey Kardashevskiy * VOF client does not expect the FDT so we do not load it to the VM. 1755fc8c745dSAlexey Kardashevskiy */ 1756fc8c745dSAlexey Kardashevskiy } else { 1757997b6cfcSDavid Gibson rc = fdt_pack(fdt); 1758997b6cfcSDavid Gibson /* Should only fail if we've built a corrupted tree */ 1759997b6cfcSDavid Gibson assert(rc == 0); 1760997b6cfcSDavid Gibson 1761fc8c745dSAlexey Kardashevskiy spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT, 1762fc8c745dSAlexey Kardashevskiy 0, fdt_addr, 0); 1763cae172abSDavid Gibson cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); 1764fc8c745dSAlexey Kardashevskiy } 1765fc8c745dSAlexey Kardashevskiy qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 1766fc8c745dSAlexey Kardashevskiy 1767fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob); 1768fea35ca4SAlexey Kardashevskiy spapr->fdt_size = fdt_totalsize(fdt); 1769fea35ca4SAlexey Kardashevskiy spapr->fdt_initial_size = spapr->fdt_size; 1770fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = fdt; 1771997b6cfcSDavid Gibson 1772d890f2faSDaniel Henrique Barboza /* Set machine->fdt for 'dumpdtb' QMP/HMP command */ 1773d890f2faSDaniel Henrique Barboza machine->fdt = fdt; 1774d890f2faSDaniel Henrique Barboza 177553018216SPaolo Bonzini /* Set up the entry state */ 1776182735efSAndreas Färber first_ppc_cpu->env.gpr[5] = 0; 177753018216SPaolo Bonzini 1778edfdbf9cSNicholas Piggin spapr->fwnmi_system_reset_addr = -1; 17798af7e1feSNicholas Piggin spapr->fwnmi_machine_check_addr = -1; 17808af7e1feSNicholas Piggin spapr->fwnmi_machine_check_interlock = -1; 17819ac703acSAravinda Prasad 17829ac703acSAravinda Prasad /* Signal all vCPUs waiting on this condition */ 17838af7e1feSNicholas Piggin qemu_cond_broadcast(&spapr->fwnmi_machine_check_interlock_cond); 17842500fb42SAravinda Prasad 1785c8a7fc51SSteve Sistare migrate_del_blocker(&spapr->fwnmi_migration_blocker); 178653018216SPaolo Bonzini } 178753018216SPaolo Bonzini 1788ce2918cbSDavid Gibson static void spapr_create_nvram(SpaprMachineState *spapr) 178953018216SPaolo Bonzini { 17903e80f690SMarkus Armbruster DeviceState *dev = qdev_new("spapr-nvram"); 17913978b863SPaolo Bonzini DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); 179253018216SPaolo Bonzini 17933978b863SPaolo Bonzini if (dinfo) { 1794934df912SMarkus Armbruster qdev_prop_set_drive_err(dev, "drive", blk_by_legacy_dinfo(dinfo), 17956231a6daSMarkus Armbruster &error_fatal); 179653018216SPaolo Bonzini } 179753018216SPaolo Bonzini 17983e80f690SMarkus Armbruster qdev_realize_and_unref(dev, &spapr->vio_bus->bus, &error_fatal); 179953018216SPaolo Bonzini 1800ce2918cbSDavid Gibson spapr->nvram = (struct SpaprNvram *)dev; 180153018216SPaolo Bonzini } 180253018216SPaolo Bonzini 1803ce2918cbSDavid Gibson static void spapr_rtc_create(SpaprMachineState *spapr) 180428df36a1SDavid Gibson { 18059fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(spapr), "rtc", &spapr->rtc, 18069fc7fc4dSMarkus Armbruster sizeof(spapr->rtc), TYPE_SPAPR_RTC, 1807f6d4dca8SThomas Huth &error_fatal, NULL); 1808ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&spapr->rtc), NULL, &error_fatal); 1809147ff807SCédric Le Goater object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc), 1810d2623129SMarkus Armbruster "date"); 181128df36a1SDavid Gibson } 181228df36a1SDavid Gibson 181353018216SPaolo Bonzini /* Returns whether we want to use VGA or not */ 181414c6a894SDavid Gibson static bool spapr_vga_init(PCIBus *pci_bus, Error **errp) 181553018216SPaolo Bonzini { 1816f9bcb2d6SGautam Agrawal vga_interface_created = true; 181753018216SPaolo Bonzini switch (vga_interface_type) { 181853018216SPaolo Bonzini case VGA_NONE: 18197effdaa3SMark Wu return false; 18207effdaa3SMark Wu case VGA_DEVICE: 18217effdaa3SMark Wu return true; 182253018216SPaolo Bonzini case VGA_STD: 1823b798c190SBenjamin Herrenschmidt case VGA_VIRTIO: 18246e66d0c6SThomas Huth case VGA_CIRRUS: 182553018216SPaolo Bonzini return pci_vga_init(pci_bus) != NULL; 182653018216SPaolo Bonzini default: 182714c6a894SDavid Gibson error_setg(errp, 182814c6a894SDavid Gibson "Unsupported VGA mode, only -vga std or -vga virtio is supported"); 182914c6a894SDavid Gibson return false; 183053018216SPaolo Bonzini } 183153018216SPaolo Bonzini } 183253018216SPaolo Bonzini 18334e5fe368SSuraj Jitindar Singh static int spapr_pre_load(void *opaque) 18344e5fe368SSuraj Jitindar Singh { 18354e5fe368SSuraj Jitindar Singh int rc; 18364e5fe368SSuraj Jitindar Singh 18374e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_load(opaque); 18384e5fe368SSuraj Jitindar Singh if (rc) { 18394e5fe368SSuraj Jitindar Singh return rc; 18404e5fe368SSuraj Jitindar Singh } 18414e5fe368SSuraj Jitindar Singh 18424e5fe368SSuraj Jitindar Singh return 0; 18434e5fe368SSuraj Jitindar Singh } 18444e5fe368SSuraj Jitindar Singh 1845880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id) 1846880ae7deSDavid Gibson { 1847ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 1848880ae7deSDavid Gibson int err = 0; 1849880ae7deSDavid Gibson 1850be85537dSDavid Gibson err = spapr_caps_post_migration(spapr); 1851be85537dSDavid Gibson if (err) { 1852be85537dSDavid Gibson return err; 1853be85537dSDavid Gibson } 1854be85537dSDavid Gibson 1855e502202cSCédric Le Goater /* 1856e502202cSCédric Le Goater * In earlier versions, there was no separate qdev for the PAPR 1857880ae7deSDavid Gibson * RTC, so the RTC offset was stored directly in sPAPREnvironment. 1858880ae7deSDavid Gibson * So when migrating from those versions, poke the incoming offset 1859e502202cSCédric Le Goater * value into the RTC device 1860e502202cSCédric Le Goater */ 1861880ae7deSDavid Gibson if (version_id < 3) { 1862147ff807SCédric Le Goater err = spapr_rtc_import_offset(&spapr->rtc, spapr->rtc_offset); 1863e502202cSCédric Le Goater if (err) { 1864e502202cSCédric Le Goater return err; 1865e502202cSCédric Le Goater } 1866880ae7deSDavid Gibson } 1867880ae7deSDavid Gibson 18680c86b2dfSLaurent Vivier if (kvm_enabled() && spapr->patb_entry) { 1869d39c90f5SBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(first_cpu); 187079825f4dSBenjamin Herrenschmidt bool radix = !!(spapr->patb_entry & PATE1_GR); 1871d39c90f5SBharata B Rao bool gtse = !!(cpu->env.spr[SPR_LPCR] & LPCR_GTSE); 1872d39c90f5SBharata B Rao 187300fd075eSBenjamin Herrenschmidt /* 187400fd075eSBenjamin Herrenschmidt * Update LPCR:HR and UPRT as they may not be set properly in 187500fd075eSBenjamin Herrenschmidt * the stream 187600fd075eSBenjamin Herrenschmidt */ 187700fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(radix ? (LPCR_HR | LPCR_UPRT) : 0, 187800fd075eSBenjamin Herrenschmidt LPCR_HR | LPCR_UPRT); 187900fd075eSBenjamin Herrenschmidt 1880d39c90f5SBharata B Rao err = kvmppc_configure_v3_mmu(cpu, radix, gtse, spapr->patb_entry); 1881d39c90f5SBharata B Rao if (err) { 1882d39c90f5SBharata B Rao error_report("Process table config unsupported by the host"); 1883d39c90f5SBharata B Rao return -EINVAL; 1884d39c90f5SBharata B Rao } 1885d39c90f5SBharata B Rao } 1886d39c90f5SBharata B Rao 18871c53b06cSCédric Le Goater err = spapr_irq_post_load(spapr, version_id); 18881c53b06cSCédric Le Goater if (err) { 18891c53b06cSCédric Le Goater return err; 18901c53b06cSCédric Le Goater } 18911c53b06cSCédric Le Goater 1892880ae7deSDavid Gibson return err; 1893880ae7deSDavid Gibson } 1894880ae7deSDavid Gibson 18954e5fe368SSuraj Jitindar Singh static int spapr_pre_save(void *opaque) 18964e5fe368SSuraj Jitindar Singh { 18974e5fe368SSuraj Jitindar Singh int rc; 18984e5fe368SSuraj Jitindar Singh 18994e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_save(opaque); 19004e5fe368SSuraj Jitindar Singh if (rc) { 19014e5fe368SSuraj Jitindar Singh return rc; 19024e5fe368SSuraj Jitindar Singh } 19034e5fe368SSuraj Jitindar Singh 19044e5fe368SSuraj Jitindar Singh return 0; 19054e5fe368SSuraj Jitindar Singh } 19064e5fe368SSuraj Jitindar Singh 1907880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id) 1908880ae7deSDavid Gibson { 1909880ae7deSDavid Gibson return version_id < 3; 1910880ae7deSDavid Gibson } 1911880ae7deSDavid Gibson 1912fd38804bSDaniel Henrique Barboza static bool spapr_pending_events_needed(void *opaque) 1913fd38804bSDaniel Henrique Barboza { 1914ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 1915fd38804bSDaniel Henrique Barboza return !QTAILQ_EMPTY(&spapr->pending_events); 1916fd38804bSDaniel Henrique Barboza } 1917fd38804bSDaniel Henrique Barboza 1918fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_event_entry = { 1919fd38804bSDaniel Henrique Barboza .name = "spapr_event_log_entry", 1920fd38804bSDaniel Henrique Barboza .version_id = 1, 1921fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1922fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 1923ce2918cbSDavid Gibson VMSTATE_UINT32(summary, SpaprEventLogEntry), 1924ce2918cbSDavid Gibson VMSTATE_UINT32(extended_length, SpaprEventLogEntry), 1925ce2918cbSDavid Gibson VMSTATE_VBUFFER_ALLOC_UINT32(extended_log, SpaprEventLogEntry, 0, 19265341258eSDavid Gibson NULL, extended_length), 1927fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1928fd38804bSDaniel Henrique Barboza }, 1929fd38804bSDaniel Henrique Barboza }; 1930fd38804bSDaniel Henrique Barboza 1931fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_pending_events = { 1932fd38804bSDaniel Henrique Barboza .name = "spapr_pending_events", 1933fd38804bSDaniel Henrique Barboza .version_id = 1, 1934fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1935fd38804bSDaniel Henrique Barboza .needed = spapr_pending_events_needed, 1936fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 1937ce2918cbSDavid Gibson VMSTATE_QTAILQ_V(pending_events, SpaprMachineState, 1, 1938ce2918cbSDavid Gibson vmstate_spapr_event_entry, SpaprEventLogEntry, next), 1939fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1940fd38804bSDaniel Henrique Barboza }, 1941fd38804bSDaniel Henrique Barboza }; 1942fd38804bSDaniel Henrique Barboza 194362ef3760SMichael Roth static bool spapr_ov5_cas_needed(void *opaque) 194462ef3760SMichael Roth { 1945ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 1946ce2918cbSDavid Gibson SpaprOptionVector *ov5_mask = spapr_ovec_new(); 194762ef3760SMichael Roth bool cas_needed; 194862ef3760SMichael Roth 1949ce2918cbSDavid Gibson /* Prior to the introduction of SpaprOptionVector, we had two option 195062ef3760SMichael Roth * vectors we dealt with: OV5_FORM1_AFFINITY, and OV5_DRCONF_MEMORY. 195162ef3760SMichael Roth * Both of these options encode machine topology into the device-tree 195262ef3760SMichael Roth * in such a way that the now-booted OS should still be able to interact 195362ef3760SMichael Roth * appropriately with QEMU regardless of what options were actually 195462ef3760SMichael Roth * negotiatied on the source side. 195562ef3760SMichael Roth * 195662ef3760SMichael Roth * As such, we can avoid migrating the CAS-negotiated options if these 195762ef3760SMichael Roth * are the only options available on the current machine/platform. 195862ef3760SMichael Roth * Since these are the only options available for pseries-2.7 and 195962ef3760SMichael Roth * earlier, this allows us to maintain old->new/new->old migration 196062ef3760SMichael Roth * compatibility. 196162ef3760SMichael Roth * 196262ef3760SMichael Roth * For QEMU 2.8+, there are additional CAS-negotiatable options available 196362ef3760SMichael Roth * via default pseries-2.8 machines and explicit command-line parameters. 196462ef3760SMichael Roth * Some of these options, like OV5_HP_EVT, *do* require QEMU to be aware 196562ef3760SMichael Roth * of the actual CAS-negotiated values to continue working properly. For 196662ef3760SMichael Roth * example, availability of memory unplug depends on knowing whether 196762ef3760SMichael Roth * OV5_HP_EVT was negotiated via CAS. 196862ef3760SMichael Roth * 196962ef3760SMichael Roth * Thus, for any cases where the set of available CAS-negotiatable 197062ef3760SMichael Roth * options extends beyond OV5_FORM1_AFFINITY and OV5_DRCONF_MEMORY, we 1971aef19c04SGreg Kurz * include the CAS-negotiated options in the migration stream, unless 1972aef19c04SGreg Kurz * if they affect boot time behaviour only. 197362ef3760SMichael Roth */ 197462ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_FORM1_AFFINITY); 197562ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_DRCONF_MEMORY); 1976aef19c04SGreg Kurz spapr_ovec_set(ov5_mask, OV5_DRMEM_V2); 197762ef3760SMichael Roth 1978d1d32d62SDavid Gibson /* We need extra information if we have any bits outside the mask 1979d1d32d62SDavid Gibson * defined above */ 1980d1d32d62SDavid Gibson cas_needed = !spapr_ovec_subset(spapr->ov5, ov5_mask); 198162ef3760SMichael Roth 198262ef3760SMichael Roth spapr_ovec_cleanup(ov5_mask); 198362ef3760SMichael Roth 198462ef3760SMichael Roth return cas_needed; 198562ef3760SMichael Roth } 198662ef3760SMichael Roth 198762ef3760SMichael Roth static const VMStateDescription vmstate_spapr_ov5_cas = { 198862ef3760SMichael Roth .name = "spapr_option_vector_ov5_cas", 198962ef3760SMichael Roth .version_id = 1, 199062ef3760SMichael Roth .minimum_version_id = 1, 199162ef3760SMichael Roth .needed = spapr_ov5_cas_needed, 199262ef3760SMichael Roth .fields = (VMStateField[]) { 1993ce2918cbSDavid Gibson VMSTATE_STRUCT_POINTER_V(ov5_cas, SpaprMachineState, 1, 1994ce2918cbSDavid Gibson vmstate_spapr_ovec, SpaprOptionVector), 199562ef3760SMichael Roth VMSTATE_END_OF_LIST() 199662ef3760SMichael Roth }, 199762ef3760SMichael Roth }; 199862ef3760SMichael Roth 19999861bb3eSSuraj Jitindar Singh static bool spapr_patb_entry_needed(void *opaque) 20009861bb3eSSuraj Jitindar Singh { 2001ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 20029861bb3eSSuraj Jitindar Singh 20039861bb3eSSuraj Jitindar Singh return !!spapr->patb_entry; 20049861bb3eSSuraj Jitindar Singh } 20059861bb3eSSuraj Jitindar Singh 20069861bb3eSSuraj Jitindar Singh static const VMStateDescription vmstate_spapr_patb_entry = { 20079861bb3eSSuraj Jitindar Singh .name = "spapr_patb_entry", 20089861bb3eSSuraj Jitindar Singh .version_id = 1, 20099861bb3eSSuraj Jitindar Singh .minimum_version_id = 1, 20109861bb3eSSuraj Jitindar Singh .needed = spapr_patb_entry_needed, 20119861bb3eSSuraj Jitindar Singh .fields = (VMStateField[]) { 2012ce2918cbSDavid Gibson VMSTATE_UINT64(patb_entry, SpaprMachineState), 20139861bb3eSSuraj Jitindar Singh VMSTATE_END_OF_LIST() 20149861bb3eSSuraj Jitindar Singh }, 20159861bb3eSSuraj Jitindar Singh }; 20169861bb3eSSuraj Jitindar Singh 201782cffa2eSCédric Le Goater static bool spapr_irq_map_needed(void *opaque) 201882cffa2eSCédric Le Goater { 2019ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 202082cffa2eSCédric Le Goater 202182cffa2eSCédric Le Goater return spapr->irq_map && !bitmap_empty(spapr->irq_map, spapr->irq_map_nr); 202282cffa2eSCédric Le Goater } 202382cffa2eSCédric Le Goater 202482cffa2eSCédric Le Goater static const VMStateDescription vmstate_spapr_irq_map = { 202582cffa2eSCédric Le Goater .name = "spapr_irq_map", 202682cffa2eSCédric Le Goater .version_id = 1, 202782cffa2eSCédric Le Goater .minimum_version_id = 1, 202882cffa2eSCédric Le Goater .needed = spapr_irq_map_needed, 202982cffa2eSCédric Le Goater .fields = (VMStateField[]) { 2030ce2918cbSDavid Gibson VMSTATE_BITMAP(irq_map, SpaprMachineState, 0, irq_map_nr), 203182cffa2eSCédric Le Goater VMSTATE_END_OF_LIST() 203282cffa2eSCédric Le Goater }, 203382cffa2eSCédric Le Goater }; 203482cffa2eSCédric Le Goater 2035fea35ca4SAlexey Kardashevskiy static bool spapr_dtb_needed(void *opaque) 2036fea35ca4SAlexey Kardashevskiy { 2037ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(opaque); 2038fea35ca4SAlexey Kardashevskiy 2039fea35ca4SAlexey Kardashevskiy return smc->update_dt_enabled; 2040fea35ca4SAlexey Kardashevskiy } 2041fea35ca4SAlexey Kardashevskiy 2042fea35ca4SAlexey Kardashevskiy static int spapr_dtb_pre_load(void *opaque) 2043fea35ca4SAlexey Kardashevskiy { 2044ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque; 2045fea35ca4SAlexey Kardashevskiy 2046fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob); 2047fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = NULL; 2048fea35ca4SAlexey Kardashevskiy spapr->fdt_size = 0; 2049fea35ca4SAlexey Kardashevskiy 2050fea35ca4SAlexey Kardashevskiy return 0; 2051fea35ca4SAlexey Kardashevskiy } 2052fea35ca4SAlexey Kardashevskiy 2053fea35ca4SAlexey Kardashevskiy static const VMStateDescription vmstate_spapr_dtb = { 2054fea35ca4SAlexey Kardashevskiy .name = "spapr_dtb", 2055fea35ca4SAlexey Kardashevskiy .version_id = 1, 2056fea35ca4SAlexey Kardashevskiy .minimum_version_id = 1, 2057fea35ca4SAlexey Kardashevskiy .needed = spapr_dtb_needed, 2058fea35ca4SAlexey Kardashevskiy .pre_load = spapr_dtb_pre_load, 2059fea35ca4SAlexey Kardashevskiy .fields = (VMStateField[]) { 2060ce2918cbSDavid Gibson VMSTATE_UINT32(fdt_initial_size, SpaprMachineState), 2061ce2918cbSDavid Gibson VMSTATE_UINT32(fdt_size, SpaprMachineState), 2062ce2918cbSDavid Gibson VMSTATE_VBUFFER_ALLOC_UINT32(fdt_blob, SpaprMachineState, 0, NULL, 2063fea35ca4SAlexey Kardashevskiy fdt_size), 2064fea35ca4SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 2065fea35ca4SAlexey Kardashevskiy }, 2066fea35ca4SAlexey Kardashevskiy }; 2067fea35ca4SAlexey Kardashevskiy 20682500fb42SAravinda Prasad static bool spapr_fwnmi_needed(void *opaque) 20692500fb42SAravinda Prasad { 20702500fb42SAravinda Prasad SpaprMachineState *spapr = (SpaprMachineState *)opaque; 20712500fb42SAravinda Prasad 20728af7e1feSNicholas Piggin return spapr->fwnmi_machine_check_addr != -1; 20732500fb42SAravinda Prasad } 20742500fb42SAravinda Prasad 20752500fb42SAravinda Prasad static int spapr_fwnmi_pre_save(void *opaque) 20762500fb42SAravinda Prasad { 20772500fb42SAravinda Prasad SpaprMachineState *spapr = (SpaprMachineState *)opaque; 20782500fb42SAravinda Prasad 20792500fb42SAravinda Prasad /* 20802500fb42SAravinda Prasad * Check if machine check handling is in progress and print a 20812500fb42SAravinda Prasad * warning message. 20822500fb42SAravinda Prasad */ 20838af7e1feSNicholas Piggin if (spapr->fwnmi_machine_check_interlock != -1) { 20842500fb42SAravinda Prasad warn_report("A machine check is being handled during migration. The" 20852500fb42SAravinda Prasad "handler may run and log hardware error on the destination"); 20862500fb42SAravinda Prasad } 20872500fb42SAravinda Prasad 20882500fb42SAravinda Prasad return 0; 20892500fb42SAravinda Prasad } 20902500fb42SAravinda Prasad 20918af7e1feSNicholas Piggin static const VMStateDescription vmstate_spapr_fwnmi = { 20928af7e1feSNicholas Piggin .name = "spapr_fwnmi", 20932500fb42SAravinda Prasad .version_id = 1, 20942500fb42SAravinda Prasad .minimum_version_id = 1, 20952500fb42SAravinda Prasad .needed = spapr_fwnmi_needed, 20962500fb42SAravinda Prasad .pre_save = spapr_fwnmi_pre_save, 20972500fb42SAravinda Prasad .fields = (VMStateField[]) { 2098edfdbf9cSNicholas Piggin VMSTATE_UINT64(fwnmi_system_reset_addr, SpaprMachineState), 20998af7e1feSNicholas Piggin VMSTATE_UINT64(fwnmi_machine_check_addr, SpaprMachineState), 21008af7e1feSNicholas Piggin VMSTATE_INT32(fwnmi_machine_check_interlock, SpaprMachineState), 21012500fb42SAravinda Prasad VMSTATE_END_OF_LIST() 21022500fb42SAravinda Prasad }, 21032500fb42SAravinda Prasad }; 21042500fb42SAravinda Prasad 21054be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = { 21064be21d56SDavid Gibson .name = "spapr", 2107880ae7deSDavid Gibson .version_id = 3, 21084be21d56SDavid Gibson .minimum_version_id = 1, 21094e5fe368SSuraj Jitindar Singh .pre_load = spapr_pre_load, 2110880ae7deSDavid Gibson .post_load = spapr_post_load, 21114e5fe368SSuraj Jitindar Singh .pre_save = spapr_pre_save, 21124be21d56SDavid Gibson .fields = (VMStateField[]) { 2113880ae7deSDavid Gibson /* used to be @next_irq */ 2114880ae7deSDavid Gibson VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4), 21154be21d56SDavid Gibson 21164be21d56SDavid Gibson /* RTC offset */ 2117ce2918cbSDavid Gibson VMSTATE_UINT64_TEST(rtc_offset, SpaprMachineState, version_before_3), 2118880ae7deSDavid Gibson 2119ce2918cbSDavid Gibson VMSTATE_PPC_TIMEBASE_V(tb, SpaprMachineState, 2), 21204be21d56SDavid Gibson VMSTATE_END_OF_LIST() 21214be21d56SDavid Gibson }, 212262ef3760SMichael Roth .subsections = (const VMStateDescription*[]) { 212362ef3760SMichael Roth &vmstate_spapr_ov5_cas, 21249861bb3eSSuraj Jitindar Singh &vmstate_spapr_patb_entry, 2125fd38804bSDaniel Henrique Barboza &vmstate_spapr_pending_events, 21264e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_htm, 21274e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_vsx, 21284e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_dfp, 21298f38eaf8SSuraj Jitindar Singh &vmstate_spapr_cap_cfpc, 213009114fd8SSuraj Jitindar Singh &vmstate_spapr_cap_sbbc, 21314be8d4e7SSuraj Jitindar Singh &vmstate_spapr_cap_ibs, 213264d4a534SDavid Gibson &vmstate_spapr_cap_hpt_maxpagesize, 213382cffa2eSCédric Le Goater &vmstate_spapr_irq_map, 2134b9a477b7SSuraj Jitindar Singh &vmstate_spapr_cap_nested_kvm_hv, 2135fea35ca4SAlexey Kardashevskiy &vmstate_spapr_dtb, 2136c982f5cfSSuraj Jitindar Singh &vmstate_spapr_cap_large_decr, 21378ff43ee4SSuraj Jitindar Singh &vmstate_spapr_cap_ccf_assist, 21389d953ce4SAravinda Prasad &vmstate_spapr_cap_fwnmi, 21398af7e1feSNicholas Piggin &vmstate_spapr_fwnmi, 214082123b75SBharata B Rao &vmstate_spapr_cap_rpt_invalidate, 214162ef3760SMichael Roth NULL 214262ef3760SMichael Roth } 21434be21d56SDavid Gibson }; 21444be21d56SDavid Gibson 21454be21d56SDavid Gibson static int htab_save_setup(QEMUFile *f, void *opaque) 21464be21d56SDavid Gibson { 2147ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 21484be21d56SDavid Gibson 21494be21d56SDavid Gibson /* "Iteration" header */ 21503a384297SBharata B Rao if (!spapr->htab_shift) { 21513a384297SBharata B Rao qemu_put_be32(f, -1); 21523a384297SBharata B Rao } else { 21534be21d56SDavid Gibson qemu_put_be32(f, spapr->htab_shift); 21543a384297SBharata B Rao } 21554be21d56SDavid Gibson 2156e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 2157e68cb8b4SAlexey Kardashevskiy spapr->htab_save_index = 0; 2158e68cb8b4SAlexey Kardashevskiy spapr->htab_first_pass = true; 2159e68cb8b4SAlexey Kardashevskiy } else { 21603a384297SBharata B Rao if (spapr->htab_shift) { 2161e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 21624be21d56SDavid Gibson } 21633a384297SBharata B Rao } 21644be21d56SDavid Gibson 2165e68cb8b4SAlexey Kardashevskiy 2166e68cb8b4SAlexey Kardashevskiy return 0; 2167e68cb8b4SAlexey Kardashevskiy } 21684be21d56SDavid Gibson 2169ce2918cbSDavid Gibson static void htab_save_chunk(QEMUFile *f, SpaprMachineState *spapr, 2170332f7721SGreg Kurz int chunkstart, int n_valid, int n_invalid) 2171332f7721SGreg Kurz { 2172332f7721SGreg Kurz qemu_put_be32(f, chunkstart); 2173332f7721SGreg Kurz qemu_put_be16(f, n_valid); 2174332f7721SGreg Kurz qemu_put_be16(f, n_invalid); 2175332f7721SGreg Kurz qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 2176332f7721SGreg Kurz HASH_PTE_SIZE_64 * n_valid); 2177332f7721SGreg Kurz } 2178332f7721SGreg Kurz 2179332f7721SGreg Kurz static void htab_save_end_marker(QEMUFile *f) 2180332f7721SGreg Kurz { 2181332f7721SGreg Kurz qemu_put_be32(f, 0); 2182332f7721SGreg Kurz qemu_put_be16(f, 0); 2183332f7721SGreg Kurz qemu_put_be16(f, 0); 2184332f7721SGreg Kurz } 2185332f7721SGreg Kurz 2186ce2918cbSDavid Gibson static void htab_save_first_pass(QEMUFile *f, SpaprMachineState *spapr, 21874be21d56SDavid Gibson int64_t max_ns) 21884be21d56SDavid Gibson { 2189378bc217SDavid Gibson bool has_timeout = max_ns != -1; 21904be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 21914be21d56SDavid Gibson int index = spapr->htab_save_index; 2192bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 21934be21d56SDavid Gibson 21944be21d56SDavid Gibson assert(spapr->htab_first_pass); 21954be21d56SDavid Gibson 21964be21d56SDavid Gibson do { 21974be21d56SDavid Gibson int chunkstart; 21984be21d56SDavid Gibson 21994be21d56SDavid Gibson /* Consume invalid HPTEs */ 22004be21d56SDavid Gibson while ((index < htabslots) 22014be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 22024be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 220324ec2863SMarc-André Lureau index++; 22044be21d56SDavid Gibson } 22054be21d56SDavid Gibson 22064be21d56SDavid Gibson /* Consume valid HPTEs */ 22074be21d56SDavid Gibson chunkstart = index; 2208338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 22094be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 22104be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 221124ec2863SMarc-André Lureau index++; 22124be21d56SDavid Gibson } 22134be21d56SDavid Gibson 22144be21d56SDavid Gibson if (index > chunkstart) { 22154be21d56SDavid Gibson int n_valid = index - chunkstart; 22164be21d56SDavid Gibson 2217332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, 0); 22184be21d56SDavid Gibson 2219378bc217SDavid Gibson if (has_timeout && 2220378bc217SDavid Gibson (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 22214be21d56SDavid Gibson break; 22224be21d56SDavid Gibson } 22234be21d56SDavid Gibson } 2224e1fde0e0SJuan Quintela } while ((index < htabslots) && !migration_rate_exceeded(f)); 22254be21d56SDavid Gibson 22264be21d56SDavid Gibson if (index >= htabslots) { 22274be21d56SDavid Gibson assert(index == htabslots); 22284be21d56SDavid Gibson index = 0; 22294be21d56SDavid Gibson spapr->htab_first_pass = false; 22304be21d56SDavid Gibson } 22314be21d56SDavid Gibson spapr->htab_save_index = index; 22324be21d56SDavid Gibson } 22334be21d56SDavid Gibson 2234ce2918cbSDavid Gibson static int htab_save_later_pass(QEMUFile *f, SpaprMachineState *spapr, 22354be21d56SDavid Gibson int64_t max_ns) 22364be21d56SDavid Gibson { 22374be21d56SDavid Gibson bool final = max_ns < 0; 22384be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 22394be21d56SDavid Gibson int examined = 0, sent = 0; 22404be21d56SDavid Gibson int index = spapr->htab_save_index; 2241bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 22424be21d56SDavid Gibson 22434be21d56SDavid Gibson assert(!spapr->htab_first_pass); 22444be21d56SDavid Gibson 22454be21d56SDavid Gibson do { 22464be21d56SDavid Gibson int chunkstart, invalidstart; 22474be21d56SDavid Gibson 22484be21d56SDavid Gibson /* Consume non-dirty HPTEs */ 22494be21d56SDavid Gibson while ((index < htabslots) 22504be21d56SDavid Gibson && !HPTE_DIRTY(HPTE(spapr->htab, index))) { 22514be21d56SDavid Gibson index++; 22524be21d56SDavid Gibson examined++; 22534be21d56SDavid Gibson } 22544be21d56SDavid Gibson 22554be21d56SDavid Gibson chunkstart = index; 22564be21d56SDavid Gibson /* Consume valid dirty HPTEs */ 2257338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 22584be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 22594be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 22604be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 22614be21d56SDavid Gibson index++; 22624be21d56SDavid Gibson examined++; 22634be21d56SDavid Gibson } 22644be21d56SDavid Gibson 22654be21d56SDavid Gibson invalidstart = index; 22664be21d56SDavid Gibson /* Consume invalid dirty HPTEs */ 2267338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - invalidstart < USHRT_MAX) 22684be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 22694be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 22704be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 22714be21d56SDavid Gibson index++; 22724be21d56SDavid Gibson examined++; 22734be21d56SDavid Gibson } 22744be21d56SDavid Gibson 22754be21d56SDavid Gibson if (index > chunkstart) { 22764be21d56SDavid Gibson int n_valid = invalidstart - chunkstart; 22774be21d56SDavid Gibson int n_invalid = index - invalidstart; 22784be21d56SDavid Gibson 2279332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, n_invalid); 22804be21d56SDavid Gibson sent += index - chunkstart; 22814be21d56SDavid Gibson 2282bc72ad67SAlex Bligh if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 22834be21d56SDavid Gibson break; 22844be21d56SDavid Gibson } 22854be21d56SDavid Gibson } 22864be21d56SDavid Gibson 22874be21d56SDavid Gibson if (examined >= htabslots) { 22884be21d56SDavid Gibson break; 22894be21d56SDavid Gibson } 22904be21d56SDavid Gibson 22914be21d56SDavid Gibson if (index >= htabslots) { 22924be21d56SDavid Gibson assert(index == htabslots); 22934be21d56SDavid Gibson index = 0; 22944be21d56SDavid Gibson } 2295e1fde0e0SJuan Quintela } while ((examined < htabslots) && (!migration_rate_exceeded(f) || final)); 22964be21d56SDavid Gibson 22974be21d56SDavid Gibson if (index >= htabslots) { 22984be21d56SDavid Gibson assert(index == htabslots); 22994be21d56SDavid Gibson index = 0; 23004be21d56SDavid Gibson } 23014be21d56SDavid Gibson 23024be21d56SDavid Gibson spapr->htab_save_index = index; 23034be21d56SDavid Gibson 2304e68cb8b4SAlexey Kardashevskiy return (examined >= htabslots) && (sent == 0) ? 1 : 0; 23054be21d56SDavid Gibson } 23064be21d56SDavid Gibson 2307e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS 5000000 /* 5 ms */ 2308e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE 2048 2309e68cb8b4SAlexey Kardashevskiy 23104be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque) 23114be21d56SDavid Gibson { 2312ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2313715c5407SDavid Gibson int fd; 2314e68cb8b4SAlexey Kardashevskiy int rc = 0; 23154be21d56SDavid Gibson 23164be21d56SDavid Gibson /* Iteration header */ 23173a384297SBharata B Rao if (!spapr->htab_shift) { 23183a384297SBharata B Rao qemu_put_be32(f, -1); 2319e8cd4247SLaurent Vivier return 1; 23203a384297SBharata B Rao } else { 23214be21d56SDavid Gibson qemu_put_be32(f, 0); 23223a384297SBharata B Rao } 23234be21d56SDavid Gibson 2324e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2325e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2326e68cb8b4SAlexey Kardashevskiy 2327715c5407SDavid Gibson fd = get_htab_fd(spapr); 2328715c5407SDavid Gibson if (fd < 0) { 2329715c5407SDavid Gibson return fd; 233001a57972SSamuel Mendoza-Jonas } 233101a57972SSamuel Mendoza-Jonas 2332715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); 2333e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2334e68cb8b4SAlexey Kardashevskiy return rc; 2335e68cb8b4SAlexey Kardashevskiy } 2336e68cb8b4SAlexey Kardashevskiy } else if (spapr->htab_first_pass) { 23374be21d56SDavid Gibson htab_save_first_pass(f, spapr, MAX_ITERATION_NS); 23384be21d56SDavid Gibson } else { 2339e68cb8b4SAlexey Kardashevskiy rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS); 23404be21d56SDavid Gibson } 23414be21d56SDavid Gibson 2342332f7721SGreg Kurz htab_save_end_marker(f); 23434be21d56SDavid Gibson 2344e68cb8b4SAlexey Kardashevskiy return rc; 23454be21d56SDavid Gibson } 23464be21d56SDavid Gibson 23474be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque) 23484be21d56SDavid Gibson { 2349ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2350715c5407SDavid Gibson int fd; 23514be21d56SDavid Gibson 23524be21d56SDavid Gibson /* Iteration header */ 23533a384297SBharata B Rao if (!spapr->htab_shift) { 23543a384297SBharata B Rao qemu_put_be32(f, -1); 23553a384297SBharata B Rao return 0; 23563a384297SBharata B Rao } else { 23574be21d56SDavid Gibson qemu_put_be32(f, 0); 23583a384297SBharata B Rao } 23594be21d56SDavid Gibson 2360e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2361e68cb8b4SAlexey Kardashevskiy int rc; 2362e68cb8b4SAlexey Kardashevskiy 2363e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2364e68cb8b4SAlexey Kardashevskiy 2365715c5407SDavid Gibson fd = get_htab_fd(spapr); 2366715c5407SDavid Gibson if (fd < 0) { 2367715c5407SDavid Gibson return fd; 236801a57972SSamuel Mendoza-Jonas } 236901a57972SSamuel Mendoza-Jonas 2370715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1); 2371e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2372e68cb8b4SAlexey Kardashevskiy return rc; 2373e68cb8b4SAlexey Kardashevskiy } 2374e68cb8b4SAlexey Kardashevskiy } else { 2375378bc217SDavid Gibson if (spapr->htab_first_pass) { 2376378bc217SDavid Gibson htab_save_first_pass(f, spapr, -1); 2377378bc217SDavid Gibson } 23784be21d56SDavid Gibson htab_save_later_pass(f, spapr, -1); 2379e68cb8b4SAlexey Kardashevskiy } 23804be21d56SDavid Gibson 23814be21d56SDavid Gibson /* End marker */ 2382332f7721SGreg Kurz htab_save_end_marker(f); 23834be21d56SDavid Gibson 23844be21d56SDavid Gibson return 0; 23854be21d56SDavid Gibson } 23864be21d56SDavid Gibson 23874be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id) 23884be21d56SDavid Gibson { 2389ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 23904be21d56SDavid Gibson uint32_t section_hdr; 2391e68cb8b4SAlexey Kardashevskiy int fd = -1; 239214b0d748SGreg Kurz Error *local_err = NULL; 23934be21d56SDavid Gibson 23944be21d56SDavid Gibson if (version_id < 1 || version_id > 1) { 239598a5d100SDavid Gibson error_report("htab_load() bad version"); 23964be21d56SDavid Gibson return -EINVAL; 23974be21d56SDavid Gibson } 23984be21d56SDavid Gibson 23994be21d56SDavid Gibson section_hdr = qemu_get_be32(f); 24004be21d56SDavid Gibson 24013a384297SBharata B Rao if (section_hdr == -1) { 24023a384297SBharata B Rao spapr_free_hpt(spapr); 24033a384297SBharata B Rao return 0; 24043a384297SBharata B Rao } 24053a384297SBharata B Rao 24064be21d56SDavid Gibson if (section_hdr) { 2407a4e3a7c0SGreg Kurz int ret; 2408a4e3a7c0SGreg Kurz 2409c5f54f3eSDavid Gibson /* First section gives the htab size */ 2410a4e3a7c0SGreg Kurz ret = spapr_reallocate_hpt(spapr, section_hdr, &local_err); 2411a4e3a7c0SGreg Kurz if (ret < 0) { 2412c5f54f3eSDavid Gibson error_report_err(local_err); 2413a4e3a7c0SGreg Kurz return ret; 24144be21d56SDavid Gibson } 24154be21d56SDavid Gibson return 0; 24164be21d56SDavid Gibson } 24174be21d56SDavid Gibson 2418e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2419e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2420e68cb8b4SAlexey Kardashevskiy 242114b0d748SGreg Kurz fd = kvmppc_get_htab_fd(true, 0, &local_err); 2422e68cb8b4SAlexey Kardashevskiy if (fd < 0) { 242314b0d748SGreg Kurz error_report_err(local_err); 242482be8e73SGreg Kurz return fd; 2425e68cb8b4SAlexey Kardashevskiy } 2426e68cb8b4SAlexey Kardashevskiy } 2427e68cb8b4SAlexey Kardashevskiy 24284be21d56SDavid Gibson while (true) { 24294be21d56SDavid Gibson uint32_t index; 24304be21d56SDavid Gibson uint16_t n_valid, n_invalid; 24314be21d56SDavid Gibson 24324be21d56SDavid Gibson index = qemu_get_be32(f); 24334be21d56SDavid Gibson n_valid = qemu_get_be16(f); 24344be21d56SDavid Gibson n_invalid = qemu_get_be16(f); 24354be21d56SDavid Gibson 24364be21d56SDavid Gibson if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) { 24374be21d56SDavid Gibson /* End of Stream */ 24384be21d56SDavid Gibson break; 24394be21d56SDavid Gibson } 24404be21d56SDavid Gibson 2441e68cb8b4SAlexey Kardashevskiy if ((index + n_valid + n_invalid) > 24424be21d56SDavid Gibson (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) { 24434be21d56SDavid Gibson /* Bad index in stream */ 244498a5d100SDavid Gibson error_report( 244598a5d100SDavid Gibson "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)", 244698a5d100SDavid Gibson index, n_valid, n_invalid, spapr->htab_shift); 24474be21d56SDavid Gibson return -EINVAL; 24484be21d56SDavid Gibson } 24494be21d56SDavid Gibson 2450e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 24514be21d56SDavid Gibson if (n_valid) { 24524be21d56SDavid Gibson qemu_get_buffer(f, HPTE(spapr->htab, index), 24534be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 24544be21d56SDavid Gibson } 24554be21d56SDavid Gibson if (n_invalid) { 24564be21d56SDavid Gibson memset(HPTE(spapr->htab, index + n_valid), 0, 24574be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_invalid); 24584be21d56SDavid Gibson } 2459e68cb8b4SAlexey Kardashevskiy } else { 2460e68cb8b4SAlexey Kardashevskiy int rc; 2461e68cb8b4SAlexey Kardashevskiy 2462e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2463e68cb8b4SAlexey Kardashevskiy 24640a06e4d6SGreg Kurz rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid, 24650a06e4d6SGreg Kurz &local_err); 2466e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 24670a06e4d6SGreg Kurz error_report_err(local_err); 2468e68cb8b4SAlexey Kardashevskiy return rc; 2469e68cb8b4SAlexey Kardashevskiy } 2470e68cb8b4SAlexey Kardashevskiy } 2471e68cb8b4SAlexey Kardashevskiy } 2472e68cb8b4SAlexey Kardashevskiy 2473e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2474e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2475e68cb8b4SAlexey Kardashevskiy close(fd); 24764be21d56SDavid Gibson } 24774be21d56SDavid Gibson 24784be21d56SDavid Gibson return 0; 24794be21d56SDavid Gibson } 24804be21d56SDavid Gibson 248170f794fcSJuan Quintela static void htab_save_cleanup(void *opaque) 2482c573fc03SThomas Huth { 2483ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 2484c573fc03SThomas Huth 2485c573fc03SThomas Huth close_htab_fd(spapr); 2486c573fc03SThomas Huth } 2487c573fc03SThomas Huth 24884be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = { 24899907e842SJuan Quintela .save_setup = htab_save_setup, 24904be21d56SDavid Gibson .save_live_iterate = htab_save_iterate, 2491a3e06c3dSDr. David Alan Gilbert .save_live_complete_precopy = htab_save_complete, 249270f794fcSJuan Quintela .save_cleanup = htab_save_cleanup, 24934be21d56SDavid Gibson .load_state = htab_load, 24944be21d56SDavid Gibson }; 24954be21d56SDavid Gibson 24965b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device, 24975b2128d2SAlexander Graf Error **errp) 24985b2128d2SAlexander Graf { 24993bf0844fSGreg Kurz SpaprMachineState *spapr = SPAPR_MACHINE(opaque); 25003bf0844fSGreg Kurz 25013bf0844fSGreg Kurz g_free(spapr->boot_device); 25023bf0844fSGreg Kurz spapr->boot_device = g_strdup(boot_device); 25035b2128d2SAlexander Graf } 25045b2128d2SAlexander Graf 2505ce2918cbSDavid Gibson static void spapr_create_lmb_dr_connectors(SpaprMachineState *spapr) 2506224245bfSDavid Gibson { 2507224245bfSDavid Gibson MachineState *machine = MACHINE(spapr); 2508224245bfSDavid Gibson uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 2509e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 2510224245bfSDavid Gibson int i; 2511224245bfSDavid Gibson 2512c0ce7b4aSDavid Hildenbrand g_assert(!nr_lmbs || machine->device_memory); 2513224245bfSDavid Gibson for (i = 0; i < nr_lmbs; i++) { 2514224245bfSDavid Gibson uint64_t addr; 2515224245bfSDavid Gibson 2516b0c14ec4SDavid Hildenbrand addr = i * lmb_size + machine->device_memory->base; 25176caf3ac6SDavid Gibson spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_LMB, 2518224245bfSDavid Gibson addr / lmb_size); 2519224245bfSDavid Gibson } 2520224245bfSDavid Gibson } 2521224245bfSDavid Gibson 2522224245bfSDavid Gibson /* 2523224245bfSDavid Gibson * If RAM size, maxmem size and individual node mem sizes aren't aligned 2524224245bfSDavid Gibson * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest 2525224245bfSDavid Gibson * since we can't support such unaligned sizes with DRCONF_MEMORY. 2526224245bfSDavid Gibson */ 25277c150d6fSDavid Gibson static void spapr_validate_node_memory(MachineState *machine, Error **errp) 2528224245bfSDavid Gibson { 2529224245bfSDavid Gibson int i; 2530224245bfSDavid Gibson 25317c150d6fSDavid Gibson if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) { 25327c150d6fSDavid Gibson error_setg(errp, "Memory size 0x" RAM_ADDR_FMT 2533ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 25347c150d6fSDavid Gibson machine->ram_size, 2535d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 25367c150d6fSDavid Gibson return; 25377c150d6fSDavid Gibson } 25387c150d6fSDavid Gibson 25397c150d6fSDavid Gibson if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) { 25407c150d6fSDavid Gibson error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT 2541ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 25427c150d6fSDavid Gibson machine->ram_size, 2543d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 25447c150d6fSDavid Gibson return; 2545224245bfSDavid Gibson } 2546224245bfSDavid Gibson 2547aa570207STao Xu for (i = 0; i < machine->numa_state->num_nodes; i++) { 25487e721e7bSTao Xu if (machine->numa_state->nodes[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) { 25497c150d6fSDavid Gibson error_setg(errp, 25507c150d6fSDavid Gibson "Node %d memory size 0x%" PRIx64 2551ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB", 25527e721e7bSTao Xu i, machine->numa_state->nodes[i].node_mem, 2553d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB); 25547c150d6fSDavid Gibson return; 2555224245bfSDavid Gibson } 2556224245bfSDavid Gibson } 2557224245bfSDavid Gibson } 2558224245bfSDavid Gibson 2559535455fdSIgor Mammedov /* find cpu slot in machine->possible_cpus by core_id */ 2560535455fdSIgor Mammedov static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx) 2561535455fdSIgor Mammedov { 2562fe6b6346SLike Xu int index = id / ms->smp.threads; 2563535455fdSIgor Mammedov 2564535455fdSIgor Mammedov if (index >= ms->possible_cpus->len) { 2565535455fdSIgor Mammedov return NULL; 2566535455fdSIgor Mammedov } 2567535455fdSIgor Mammedov if (idx) { 2568535455fdSIgor Mammedov *idx = index; 2569535455fdSIgor Mammedov } 2570535455fdSIgor Mammedov return &ms->possible_cpus->cpus[index]; 2571535455fdSIgor Mammedov } 2572535455fdSIgor Mammedov 2573ce2918cbSDavid Gibson static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp) 2574fa98fbfcSSam Bobroff { 2575fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 257629cb4187SGreg Kurz SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 2577fa98fbfcSSam Bobroff Error *local_err = NULL; 2578fa98fbfcSSam Bobroff bool vsmt_user = !!spapr->vsmt; 2579fa98fbfcSSam Bobroff int kvm_smt = kvmppc_smt_threads(); 2580fa98fbfcSSam Bobroff int ret; 2581fe6b6346SLike Xu unsigned int smp_threads = ms->smp.threads; 2582fa98fbfcSSam Bobroff 2583dc5e0721SNicholas Piggin if (tcg_enabled()) { 2584dc5e0721SNicholas Piggin if (smp_threads > 1 && 2585dc5e0721SNicholas Piggin !ppc_type_check_compat(ms->cpu_type, CPU_POWERPC_LOGICAL_2_07, 0, 2586dc5e0721SNicholas Piggin spapr->max_compat_pvr)) { 2587dc5e0721SNicholas Piggin error_setg(errp, "TCG only supports SMT on POWER8 or newer CPUs"); 2588dc5e0721SNicholas Piggin return; 2589dc5e0721SNicholas Piggin } 2590dc5e0721SNicholas Piggin 2591dc5e0721SNicholas Piggin if (smp_threads > 8) { 2592dc5e0721SNicholas Piggin error_setg(errp, "TCG cannot support more than 8 threads/core " 2593fa98fbfcSSam Bobroff "on a pseries machine"); 2594dcfe4805SMarkus Armbruster return; 2595fa98fbfcSSam Bobroff } 2596dc5e0721SNicholas Piggin } 2597fa98fbfcSSam Bobroff if (!is_power_of_2(smp_threads)) { 2598dcfe4805SMarkus Armbruster error_setg(errp, "Cannot support %d threads/core on a pseries " 2599fa98fbfcSSam Bobroff "machine because it must be a power of 2", smp_threads); 2600dcfe4805SMarkus Armbruster return; 2601fa98fbfcSSam Bobroff } 2602fa98fbfcSSam Bobroff 2603e6a19a64SMichael Tokarev /* Determine the VSMT mode to use: */ 2604fa98fbfcSSam Bobroff if (vsmt_user) { 2605fa98fbfcSSam Bobroff if (spapr->vsmt < smp_threads) { 2606dcfe4805SMarkus Armbruster error_setg(errp, "Cannot support VSMT mode %d" 2607fa98fbfcSSam Bobroff " because it must be >= threads/core (%d)", 2608fa98fbfcSSam Bobroff spapr->vsmt, smp_threads); 2609dcfe4805SMarkus Armbruster return; 2610fa98fbfcSSam Bobroff } 2611fa98fbfcSSam Bobroff /* In this case, spapr->vsmt has been set by the command line */ 261229cb4187SGreg Kurz } else if (!smc->smp_threads_vsmt) { 26138904e5a7SDavid Gibson /* 26148904e5a7SDavid Gibson * Default VSMT value is tricky, because we need it to be as 26158904e5a7SDavid Gibson * consistent as possible (for migration), but this requires 26168904e5a7SDavid Gibson * changing it for at least some existing cases. We pick 8 as 26178904e5a7SDavid Gibson * the value that we'd get with KVM on POWER8, the 26188904e5a7SDavid Gibson * overwhelmingly common case in production systems. 26198904e5a7SDavid Gibson */ 26204ad64cbdSLaurent Vivier spapr->vsmt = MAX(8, smp_threads); 262129cb4187SGreg Kurz } else { 262229cb4187SGreg Kurz spapr->vsmt = smp_threads; 2623fa98fbfcSSam Bobroff } 2624fa98fbfcSSam Bobroff 2625fa98fbfcSSam Bobroff /* KVM: If necessary, set the SMT mode: */ 2626fa98fbfcSSam Bobroff if (kvm_enabled() && (spapr->vsmt != kvm_smt)) { 2627fa98fbfcSSam Bobroff ret = kvmppc_set_smt_threads(spapr->vsmt); 2628fa98fbfcSSam Bobroff if (ret) { 26291f20f2e0SDavid Gibson /* Looks like KVM isn't able to change VSMT mode */ 2630fa98fbfcSSam Bobroff error_setg(&local_err, 2631fa98fbfcSSam Bobroff "Failed to set KVM's VSMT mode to %d (errno %d)", 2632fa98fbfcSSam Bobroff spapr->vsmt, ret); 26331f20f2e0SDavid Gibson /* We can live with that if the default one is big enough 26341f20f2e0SDavid Gibson * for the number of threads, and a submultiple of the one 26351f20f2e0SDavid Gibson * we want. In this case we'll waste some vcpu ids, but 26361f20f2e0SDavid Gibson * behaviour will be correct */ 26371f20f2e0SDavid Gibson if ((kvm_smt >= smp_threads) && ((spapr->vsmt % kvm_smt) == 0)) { 26381f20f2e0SDavid Gibson warn_report_err(local_err); 26391f20f2e0SDavid Gibson } else { 2640fa98fbfcSSam Bobroff if (!vsmt_user) { 26411f20f2e0SDavid Gibson error_append_hint(&local_err, 26421f20f2e0SDavid Gibson "On PPC, a VM with %d threads/core" 26431f20f2e0SDavid Gibson " on a host with %d threads/core" 26441f20f2e0SDavid Gibson " requires the use of VSMT mode %d.\n", 2645fa98fbfcSSam Bobroff smp_threads, kvm_smt, spapr->vsmt); 2646fa98fbfcSSam Bobroff } 2647cdcca22aSVladimir Sementsov-Ogievskiy kvmppc_error_append_smt_possible_hint(&local_err); 2648dcfe4805SMarkus Armbruster error_propagate(errp, local_err); 2649fa98fbfcSSam Bobroff } 2650fa98fbfcSSam Bobroff } 26511f20f2e0SDavid Gibson } 2652fa98fbfcSSam Bobroff /* else TCG: nothing to do currently */ 2653fa98fbfcSSam Bobroff } 2654fa98fbfcSSam Bobroff 2655ce2918cbSDavid Gibson static void spapr_init_cpus(SpaprMachineState *spapr) 26561a5008fcSGreg Kurz { 26571a5008fcSGreg Kurz MachineState *machine = MACHINE(spapr); 26581a5008fcSGreg Kurz MachineClass *mc = MACHINE_GET_CLASS(machine); 2659ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 26601a5008fcSGreg Kurz const char *type = spapr_get_cpu_core_type(machine->cpu_type); 26611a5008fcSGreg Kurz const CPUArchIdList *possible_cpus; 2662fe6b6346SLike Xu unsigned int smp_cpus = machine->smp.cpus; 2663fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 2664fe6b6346SLike Xu unsigned int max_cpus = machine->smp.max_cpus; 26651a5008fcSGreg Kurz int boot_cores_nr = smp_cpus / smp_threads; 26661a5008fcSGreg Kurz int i; 26671a5008fcSGreg Kurz 26681a5008fcSGreg Kurz possible_cpus = mc->possible_cpu_arch_ids(machine); 26691a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 26701a5008fcSGreg Kurz if (smp_cpus % smp_threads) { 26711a5008fcSGreg Kurz error_report("smp_cpus (%u) must be multiple of threads (%u)", 26721a5008fcSGreg Kurz smp_cpus, smp_threads); 26731a5008fcSGreg Kurz exit(1); 26741a5008fcSGreg Kurz } 26751a5008fcSGreg Kurz if (max_cpus % smp_threads) { 26761a5008fcSGreg Kurz error_report("max_cpus (%u) must be multiple of threads (%u)", 26771a5008fcSGreg Kurz max_cpus, smp_threads); 26781a5008fcSGreg Kurz exit(1); 26791a5008fcSGreg Kurz } 26801a5008fcSGreg Kurz } else { 26811a5008fcSGreg Kurz if (max_cpus != smp_cpus) { 26821a5008fcSGreg Kurz error_report("This machine version does not support CPU hotplug"); 26831a5008fcSGreg Kurz exit(1); 26841a5008fcSGreg Kurz } 26851a5008fcSGreg Kurz boot_cores_nr = possible_cpus->len; 26861a5008fcSGreg Kurz } 26871a5008fcSGreg Kurz 26881a5008fcSGreg Kurz if (smc->pre_2_10_has_unused_icps) { 26891a518e76SCédric Le Goater for (i = 0; i < spapr_max_server_number(spapr); i++) { 26901a5008fcSGreg Kurz /* Dummy entries get deregistered when real ICPState objects 26911a5008fcSGreg Kurz * are registered during CPU core hotplug. 26921a5008fcSGreg Kurz */ 26931a5008fcSGreg Kurz pre_2_10_vmstate_register_dummy_icp(i); 26941a5008fcSGreg Kurz } 26951a5008fcSGreg Kurz } 26961a5008fcSGreg Kurz 26971a5008fcSGreg Kurz for (i = 0; i < possible_cpus->len; i++) { 26981a5008fcSGreg Kurz int core_id = i * smp_threads; 26991a5008fcSGreg Kurz 27001a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 27011a5008fcSGreg Kurz spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU, 27021a5008fcSGreg Kurz spapr_vcpu_id(spapr, core_id)); 27031a5008fcSGreg Kurz } 27041a5008fcSGreg Kurz 27051a5008fcSGreg Kurz if (i < boot_cores_nr) { 27061a5008fcSGreg Kurz Object *core = object_new(type); 27071a5008fcSGreg Kurz int nr_threads = smp_threads; 27081a5008fcSGreg Kurz 27091a5008fcSGreg Kurz /* Handle the partially filled core for older machine types */ 27101a5008fcSGreg Kurz if ((i + 1) * smp_threads >= smp_cpus) { 27111a5008fcSGreg Kurz nr_threads = smp_cpus - i * smp_threads; 27121a5008fcSGreg Kurz } 27131a5008fcSGreg Kurz 27145325cc34SMarkus Armbruster object_property_set_int(core, "nr-threads", nr_threads, 27151a5008fcSGreg Kurz &error_fatal); 27165325cc34SMarkus Armbruster object_property_set_int(core, CPU_CORE_PROP_CORE_ID, core_id, 27171a5008fcSGreg Kurz &error_fatal); 2718ce189ab2SMarkus Armbruster qdev_realize(DEVICE(core), NULL, &error_fatal); 2719ecda255eSSam Bobroff 2720ecda255eSSam Bobroff object_unref(core); 27211a5008fcSGreg Kurz } 27221a5008fcSGreg Kurz } 27231a5008fcSGreg Kurz } 27241a5008fcSGreg Kurz 2725999c9cafSGreg Kurz static PCIHostState *spapr_create_default_phb(void) 2726999c9cafSGreg Kurz { 2727999c9cafSGreg Kurz DeviceState *dev; 2728999c9cafSGreg Kurz 27293e80f690SMarkus Armbruster dev = qdev_new(TYPE_SPAPR_PCI_HOST_BRIDGE); 2730999c9cafSGreg Kurz qdev_prop_set_uint32(dev, "index", 0); 27313c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); 2732999c9cafSGreg Kurz 2733999c9cafSGreg Kurz return PCI_HOST_BRIDGE(dev); 2734999c9cafSGreg Kurz } 2735999c9cafSGreg Kurz 2736425f0b7aSDavid Gibson static hwaddr spapr_rma_size(SpaprMachineState *spapr, Error **errp) 2737425f0b7aSDavid Gibson { 2738425f0b7aSDavid Gibson MachineState *machine = MACHINE(spapr); 2739425f0b7aSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 2740425f0b7aSDavid Gibson hwaddr rma_size = machine->ram_size; 2741425f0b7aSDavid Gibson hwaddr node0_size = spapr_node0_size(machine); 2742425f0b7aSDavid Gibson 2743425f0b7aSDavid Gibson /* RMA has to fit in the first NUMA node */ 2744425f0b7aSDavid Gibson rma_size = MIN(rma_size, node0_size); 2745425f0b7aSDavid Gibson 2746425f0b7aSDavid Gibson /* 2747425f0b7aSDavid Gibson * VRMA access is via a special 1TiB SLB mapping, so the RMA can 2748425f0b7aSDavid Gibson * never exceed that 2749425f0b7aSDavid Gibson */ 2750425f0b7aSDavid Gibson rma_size = MIN(rma_size, 1 * TiB); 2751425f0b7aSDavid Gibson 2752425f0b7aSDavid Gibson /* 2753425f0b7aSDavid Gibson * Clamp the RMA size based on machine type. This is for 2754425f0b7aSDavid Gibson * migration compatibility with older qemu versions, which limited 2755425f0b7aSDavid Gibson * the RMA size for complicated and mostly bad reasons. 2756425f0b7aSDavid Gibson */ 2757425f0b7aSDavid Gibson if (smc->rma_limit) { 2758425f0b7aSDavid Gibson rma_size = MIN(rma_size, smc->rma_limit); 2759425f0b7aSDavid Gibson } 2760425f0b7aSDavid Gibson 2761425f0b7aSDavid Gibson if (rma_size < MIN_RMA_SLOF) { 2762425f0b7aSDavid Gibson error_setg(errp, 2763425f0b7aSDavid Gibson "pSeries SLOF firmware requires >= %" HWADDR_PRIx 2764425f0b7aSDavid Gibson "ldMiB guest RMA (Real Mode Area memory)", 2765425f0b7aSDavid Gibson MIN_RMA_SLOF / MiB); 2766425f0b7aSDavid Gibson return 0; 2767425f0b7aSDavid Gibson } 2768425f0b7aSDavid Gibson 2769425f0b7aSDavid Gibson return rma_size; 2770425f0b7aSDavid Gibson } 2771425f0b7aSDavid Gibson 2772ce316b51SGreg Kurz static void spapr_create_nvdimm_dr_connectors(SpaprMachineState *spapr) 2773ce316b51SGreg Kurz { 2774ce316b51SGreg Kurz MachineState *machine = MACHINE(spapr); 2775ce316b51SGreg Kurz int i; 2776ce316b51SGreg Kurz 2777ce316b51SGreg Kurz for (i = 0; i < machine->ram_slots; i++) { 2778ce316b51SGreg Kurz spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_PMEM, i); 2779ce316b51SGreg Kurz } 2780ce316b51SGreg Kurz } 2781ce316b51SGreg Kurz 278253018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */ 2783bcb5ce08SDavid Gibson static void spapr_machine_init(MachineState *machine) 278453018216SPaolo Bonzini { 2785ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(machine); 2786ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 2787ee3a71e3SShivaprasad G Bhat MachineClass *mc = MACHINE_GET_CLASS(machine); 2788fc8c745dSAlexey Kardashevskiy const char *bios_default = spapr->vof ? FW_FILE_NAME_VOF : FW_FILE_NAME; 2789fc8c745dSAlexey Kardashevskiy const char *bios_name = machine->firmware ?: bios_default; 27905f2b96b3SDaniel Henrique Barboza g_autofree char *filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 27913ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 27923ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 279353018216SPaolo Bonzini PCIHostState *phb; 2794f73eb948SPaolo Bonzini bool has_vga; 279553018216SPaolo Bonzini int i; 279653018216SPaolo Bonzini MemoryRegion *sysmem = get_system_memory(); 2797b7d1f77aSBenjamin Herrenschmidt long load_limit, fw_size; 279830f4b05bSDavid Gibson Error *resize_hpt_err = NULL; 279953018216SPaolo Bonzini 28005f2b96b3SDaniel Henrique Barboza if (!filename) { 28015f2b96b3SDaniel Henrique Barboza error_report("Could not find LPAR firmware '%s'", bios_name); 28025f2b96b3SDaniel Henrique Barboza exit(1); 28035f2b96b3SDaniel Henrique Barboza } 28045f2b96b3SDaniel Henrique Barboza fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); 28055f2b96b3SDaniel Henrique Barboza if (fw_size <= 0) { 28065f2b96b3SDaniel Henrique Barboza error_report("Could not load LPAR firmware '%s'", filename); 28075f2b96b3SDaniel Henrique Barboza exit(1); 28085f2b96b3SDaniel Henrique Barboza } 28095f2b96b3SDaniel Henrique Barboza 28106c8ebe30SDavid Gibson /* 28116c8ebe30SDavid Gibson * if Secure VM (PEF) support is configured, then initialize it 28126c8ebe30SDavid Gibson */ 28136c8ebe30SDavid Gibson pef_kvm_init(machine->cgs, &error_fatal); 28146c8ebe30SDavid Gibson 2815226419d6SMichael S. Tsirkin msi_nonbroken = true; 281653018216SPaolo Bonzini 281753018216SPaolo Bonzini QLIST_INIT(&spapr->phbs); 28180cffce56SDavid Gibson QTAILQ_INIT(&spapr->pending_dimm_unplugs); 281953018216SPaolo Bonzini 28209f6edd06SDavid Gibson /* Determine capabilities to run with */ 28219f6edd06SDavid Gibson spapr_caps_init(spapr); 28229f6edd06SDavid Gibson 282330f4b05bSDavid Gibson kvmppc_check_papr_resize_hpt(&resize_hpt_err); 282430f4b05bSDavid Gibson if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) { 282530f4b05bSDavid Gibson /* 282630f4b05bSDavid Gibson * If the user explicitly requested a mode we should either 282730f4b05bSDavid Gibson * supply it, or fail completely (which we do below). But if 282830f4b05bSDavid Gibson * it's not set explicitly, we reset our mode to something 282930f4b05bSDavid Gibson * that works 283030f4b05bSDavid Gibson */ 283130f4b05bSDavid Gibson if (resize_hpt_err) { 283230f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 283330f4b05bSDavid Gibson error_free(resize_hpt_err); 283430f4b05bSDavid Gibson resize_hpt_err = NULL; 283530f4b05bSDavid Gibson } else { 283630f4b05bSDavid Gibson spapr->resize_hpt = smc->resize_hpt_default; 283730f4b05bSDavid Gibson } 283830f4b05bSDavid Gibson } 283930f4b05bSDavid Gibson 284030f4b05bSDavid Gibson assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT); 284130f4b05bSDavid Gibson 284230f4b05bSDavid Gibson if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && resize_hpt_err) { 284330f4b05bSDavid Gibson /* 284430f4b05bSDavid Gibson * User requested HPT resize, but this host can't supply it. Bail out 284530f4b05bSDavid Gibson */ 284630f4b05bSDavid Gibson error_report_err(resize_hpt_err); 284730f4b05bSDavid Gibson exit(1); 284830f4b05bSDavid Gibson } 284914963c34SMarkus Armbruster error_free(resize_hpt_err); 285030f4b05bSDavid Gibson 2851425f0b7aSDavid Gibson spapr->rma_size = spapr_rma_size(spapr, &error_fatal); 2852c4177479SAlexey Kardashevskiy 2853b7d1f77aSBenjamin Herrenschmidt /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */ 28544b98e72dSAlexey Kardashevskiy load_limit = MIN(spapr->rma_size, FDT_MAX_ADDR) - FW_OVERHEAD; 285553018216SPaolo Bonzini 2856482969d6SCédric Le Goater /* 2857482969d6SCédric Le Goater * VSMT must be set in order to be able to compute VCPU ids, ie to 28581a518e76SCédric Le Goater * call spapr_max_server_number() or spapr_vcpu_id(). 2859482969d6SCédric Le Goater */ 2860482969d6SCédric Le Goater spapr_set_vsmt_mode(spapr, &error_fatal); 2861482969d6SCédric Le Goater 28627b565160SDavid Gibson /* Set up Interrupt Controller before we create the VCPUs */ 2863fab397d8SCédric Le Goater spapr_irq_init(spapr, &error_fatal); 28647b565160SDavid Gibson 2865dc1b5eeeSGreg Kurz /* Set up containers for ibm,client-architecture-support negotiated options 2866dc1b5eeeSGreg Kurz */ 2867facdb8b6SMichael Roth spapr->ov5 = spapr_ovec_new(); 2868facdb8b6SMichael Roth spapr->ov5_cas = spapr_ovec_new(); 2869facdb8b6SMichael Roth 2870224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2871facdb8b6SMichael Roth spapr_ovec_set(spapr->ov5, OV5_DRCONF_MEMORY); 28727c150d6fSDavid Gibson spapr_validate_node_memory(machine, &error_fatal); 2873224245bfSDavid Gibson } 2874224245bfSDavid Gibson 2875417ece33SMichael Roth spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY); 2876417ece33SMichael Roth 2877e0eb84d4SDaniel Henrique Barboza /* Do not advertise FORM2 NUMA support for pseries-6.1 and older */ 2878e0eb84d4SDaniel Henrique Barboza if (!smc->pre_6_2_numa_affinity) { 2879e0eb84d4SDaniel Henrique Barboza spapr_ovec_set(spapr->ov5, OV5_FORM2_AFFINITY); 2880e0eb84d4SDaniel Henrique Barboza } 2881e0eb84d4SDaniel Henrique Barboza 2882ffbb1705SMichael Roth /* advertise support for dedicated HP event source to guests */ 2883ffbb1705SMichael Roth if (spapr->use_hotplug_event_source) { 2884ffbb1705SMichael Roth spapr_ovec_set(spapr->ov5, OV5_HP_EVT); 2885ffbb1705SMichael Roth } 2886ffbb1705SMichael Roth 28872772cf6bSDavid Gibson /* advertise support for HPT resizing */ 28882772cf6bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { 28892772cf6bSDavid Gibson spapr_ovec_set(spapr->ov5, OV5_HPT_RESIZE); 28902772cf6bSDavid Gibson } 28912772cf6bSDavid Gibson 2892a324d6f1SBharata B Rao /* advertise support for ibm,dyamic-memory-v2 */ 2893a324d6f1SBharata B Rao spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2); 2894a324d6f1SBharata B Rao 2895db592b5bSCédric Le Goater /* advertise XIVE on POWER9 machines */ 2896ca62823bSDavid Gibson if (spapr->irq->xive) { 2897db592b5bSCédric Le Goater spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT); 2898db592b5bSCédric Le Goater } 2899db592b5bSCédric Le Goater 290053018216SPaolo Bonzini /* init CPUs */ 29010c86d0fdSDavid Gibson spapr_init_cpus(spapr); 290253018216SPaolo Bonzini 2903f1aa45ffSDaniel Henrique Barboza /* Init numa_assoc_array */ 2904f1aa45ffSDaniel Henrique Barboza spapr_numa_associativity_init(spapr, machine); 2905f1aa45ffSDaniel Henrique Barboza 29060550b120SGreg Kurz if ((!kvm_enabled() || kvmppc_has_cap_mmu_radix()) && 2907ad99d04cSDavid Gibson ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, 29080550b120SGreg Kurz spapr->max_compat_pvr)) { 2909b4b83312SGreg Kurz spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_300); 29100550b120SGreg Kurz /* KVM and TCG always allow GTSE with radix... */ 29110550b120SGreg Kurz spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE); 29120550b120SGreg Kurz } 29130550b120SGreg Kurz /* ... but not with hash (currently). */ 29140550b120SGreg Kurz 2915026bfd89SDavid Gibson if (kvm_enabled()) { 2916026bfd89SDavid Gibson /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ 2917026bfd89SDavid Gibson kvmppc_enable_logical_ci_hcalls(); 2918ef9971ddSAlexey Kardashevskiy kvmppc_enable_set_mode_hcall(); 29195145ad4fSNathan Whitehorn 29205145ad4fSNathan Whitehorn /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */ 29215145ad4fSNathan Whitehorn kvmppc_enable_clear_ref_mod_hcalls(); 292268f9f708SSuraj Jitindar Singh 292368f9f708SSuraj Jitindar Singh /* Enable H_PAGE_INIT */ 292468f9f708SSuraj Jitindar Singh kvmppc_enable_h_page_init(); 2925026bfd89SDavid Gibson } 2926026bfd89SDavid Gibson 2927ab74e543SIgor Mammedov /* map RAM */ 2928ab74e543SIgor Mammedov memory_region_add_subregion(sysmem, 0, machine->ram); 292953018216SPaolo Bonzini 29304a1c9cf0SBharata B Rao /* initialize hotplug memory address space */ 29314a1c9cf0SBharata B Rao if (machine->ram_size < machine->maxram_size) { 29320c9269a5SDavid Hildenbrand ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size; 2933c0ce7b4aSDavid Hildenbrand hwaddr device_mem_base; 2934c0ce7b4aSDavid Hildenbrand 293571c9a3ddSBharata B Rao /* 293671c9a3ddSBharata B Rao * Limit the number of hotpluggable memory slots to half the number 293771c9a3ddSBharata B Rao * slots that KVM supports, leaving the other half for PCI and other 293871c9a3ddSBharata B Rao * devices. However ensure that number of slots doesn't drop below 32. 293971c9a3ddSBharata B Rao */ 294071c9a3ddSBharata B Rao int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 : 294171c9a3ddSBharata B Rao SPAPR_MAX_RAM_SLOTS; 29424a1c9cf0SBharata B Rao 294371c9a3ddSBharata B Rao if (max_memslots < SPAPR_MAX_RAM_SLOTS) { 294471c9a3ddSBharata B Rao max_memslots = SPAPR_MAX_RAM_SLOTS; 294571c9a3ddSBharata B Rao } 294671c9a3ddSBharata B Rao if (machine->ram_slots > max_memslots) { 2947d54e4d76SDavid Gibson error_report("Specified number of memory slots %" 2948d54e4d76SDavid Gibson PRIu64" exceeds max supported %d", 294971c9a3ddSBharata B Rao machine->ram_slots, max_memslots); 2950d54e4d76SDavid Gibson exit(1); 29514a1c9cf0SBharata B Rao } 29524a1c9cf0SBharata B Rao 2953c0ce7b4aSDavid Hildenbrand device_mem_base = ROUND_UP(machine->ram_size, SPAPR_DEVICE_MEM_ALIGN); 2954c0ce7b4aSDavid Hildenbrand machine_memory_devices_init(machine, device_mem_base, device_mem_size); 29554a1c9cf0SBharata B Rao } 29564a1c9cf0SBharata B Rao 2957224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2958224245bfSDavid Gibson spapr_create_lmb_dr_connectors(spapr); 2959224245bfSDavid Gibson } 2960224245bfSDavid Gibson 2961ee3a71e3SShivaprasad G Bhat if (mc->nvdimm_supported) { 2962ee3a71e3SShivaprasad G Bhat spapr_create_nvdimm_dr_connectors(spapr); 2963ee3a71e3SShivaprasad G Bhat } 2964ee3a71e3SShivaprasad G Bhat 2965ffbb1705SMichael Roth /* Set up RTAS event infrastructure */ 296653018216SPaolo Bonzini spapr_events_init(spapr); 296753018216SPaolo Bonzini 296812f42174SDavid Gibson /* Set up the RTC RTAS interfaces */ 296928df36a1SDavid Gibson spapr_rtc_create(spapr); 297012f42174SDavid Gibson 297153018216SPaolo Bonzini /* Set up VIO bus */ 297253018216SPaolo Bonzini spapr->vio_bus = spapr_vio_bus_init(); 297353018216SPaolo Bonzini 297446ee119fSPaolo Bonzini for (i = 0; serial_hd(i); i++) { 29759bca0edbSPeter Maydell spapr_vty_create(spapr->vio_bus, serial_hd(i)); 297653018216SPaolo Bonzini } 297753018216SPaolo Bonzini 297853018216SPaolo Bonzini /* We always have at least the nvram device on VIO */ 297953018216SPaolo Bonzini spapr_create_nvram(spapr); 298053018216SPaolo Bonzini 2981962b6c36SMichael Roth /* 2982962b6c36SMichael Roth * Setup hotplug / dynamic-reconfiguration connectors. top-level 2983962b6c36SMichael Roth * connectors (described in root DT node's "ibm,drc-types" property) 2984962b6c36SMichael Roth * are pre-initialized here. additional child connectors (such as 2985962b6c36SMichael Roth * connectors for a PHBs PCI slots) are added as needed during their 2986962b6c36SMichael Roth * parent's realization. 2987962b6c36SMichael Roth */ 2988962b6c36SMichael Roth if (smc->dr_phb_enabled) { 2989962b6c36SMichael Roth for (i = 0; i < SPAPR_MAX_PHBS; i++) { 2990962b6c36SMichael Roth spapr_dr_connector_new(OBJECT(machine), TYPE_SPAPR_DRC_PHB, i); 2991962b6c36SMichael Roth } 2992962b6c36SMichael Roth } 2993962b6c36SMichael Roth 299453018216SPaolo Bonzini /* Set up PCI */ 299553018216SPaolo Bonzini spapr_pci_rtas_init(); 299653018216SPaolo Bonzini 2997999c9cafSGreg Kurz phb = spapr_create_default_phb(); 299853018216SPaolo Bonzini 299953018216SPaolo Bonzini for (i = 0; i < nb_nics; i++) { 300053018216SPaolo Bonzini NICInfo *nd = &nd_table[i]; 300153018216SPaolo Bonzini 300253018216SPaolo Bonzini if (!nd->model) { 30033c3a4e7aSThomas Huth nd->model = g_strdup("spapr-vlan"); 300453018216SPaolo Bonzini } 300553018216SPaolo Bonzini 30063c3a4e7aSThomas Huth if (g_str_equal(nd->model, "spapr-vlan") || 30073c3a4e7aSThomas Huth g_str_equal(nd->model, "ibmveth")) { 300853018216SPaolo Bonzini spapr_vlan_create(spapr->vio_bus, nd); 300953018216SPaolo Bonzini } else { 301029b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL); 301153018216SPaolo Bonzini } 301253018216SPaolo Bonzini } 301353018216SPaolo Bonzini 301453018216SPaolo Bonzini for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { 301553018216SPaolo Bonzini spapr_vscsi_create(spapr->vio_bus); 301653018216SPaolo Bonzini } 301753018216SPaolo Bonzini 301853018216SPaolo Bonzini /* Graphics */ 3019f73eb948SPaolo Bonzini has_vga = spapr_vga_init(phb->bus, &error_fatal); 3020f73eb948SPaolo Bonzini if (has_vga) { 3021f73eb948SPaolo Bonzini spapr->want_stdout_path = !machine->enable_graphics; 3022c6e76503SPaolo Bonzini machine->usb |= defaults_enabled() && !machine->usb_disabled; 3023f73eb948SPaolo Bonzini } else { 3024f73eb948SPaolo Bonzini spapr->want_stdout_path = true; 302553018216SPaolo Bonzini } 302653018216SPaolo Bonzini 30274ee9ced9SMarcel Apfelbaum if (machine->usb) { 302857040d45SThomas Huth if (smc->use_ohci_by_default) { 302953018216SPaolo Bonzini pci_create_simple(phb->bus, -1, "pci-ohci"); 303057040d45SThomas Huth } else { 303157040d45SThomas Huth pci_create_simple(phb->bus, -1, "nec-usb-xhci"); 303257040d45SThomas Huth } 3033c86580b8SMarkus Armbruster 3034f73eb948SPaolo Bonzini if (has_vga) { 3035c86580b8SMarkus Armbruster USBBus *usb_bus = usb_bus_find(-1); 3036c86580b8SMarkus Armbruster 3037c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-kbd"); 3038c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-mouse"); 303953018216SPaolo Bonzini } 304053018216SPaolo Bonzini } 304153018216SPaolo Bonzini 304253018216SPaolo Bonzini if (kernel_filename) { 30435bb55f3eSAlexey Kardashevskiy uint64_t loaded_addr = 0; 30445bb55f3eSAlexey Kardashevskiy 30454366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL, 304687262806SAlexey Kardashevskiy translate_kernel_address, spapr, 30475bb55f3eSAlexey Kardashevskiy NULL, &loaded_addr, NULL, NULL, 1, 3048a19f7fb0SDavid Gibson PPC_ELF_MACHINE, 0, 0); 3049a19f7fb0SDavid Gibson if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) { 30504366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL, 3051617160c9SBALATON Zoltan translate_kernel_address, spapr, 30525bb55f3eSAlexey Kardashevskiy NULL, &loaded_addr, NULL, NULL, 0, 3053617160c9SBALATON Zoltan PPC_ELF_MACHINE, 0, 0); 3054a19f7fb0SDavid Gibson spapr->kernel_le = spapr->kernel_size > 0; 305516457e7fSBenjamin Herrenschmidt } 3056a19f7fb0SDavid Gibson if (spapr->kernel_size < 0) { 3057a19f7fb0SDavid Gibson error_report("error loading %s: %s", kernel_filename, 3058a19f7fb0SDavid Gibson load_elf_strerror(spapr->kernel_size)); 305953018216SPaolo Bonzini exit(1); 306053018216SPaolo Bonzini } 306153018216SPaolo Bonzini 30625bb55f3eSAlexey Kardashevskiy if (spapr->kernel_addr != loaded_addr) { 30635bb55f3eSAlexey Kardashevskiy warn_report("spapr: kernel_addr changed from 0x%"PRIx64 30645bb55f3eSAlexey Kardashevskiy " to 0x%"PRIx64, 30655bb55f3eSAlexey Kardashevskiy spapr->kernel_addr, loaded_addr); 30665bb55f3eSAlexey Kardashevskiy spapr->kernel_addr = loaded_addr; 30675bb55f3eSAlexey Kardashevskiy } 30685bb55f3eSAlexey Kardashevskiy 306953018216SPaolo Bonzini /* load initrd */ 307053018216SPaolo Bonzini if (initrd_filename) { 307153018216SPaolo Bonzini /* Try to locate the initrd in the gap between the kernel 307253018216SPaolo Bonzini * and the firmware. Add a bit of space just in case 307353018216SPaolo Bonzini */ 307487262806SAlexey Kardashevskiy spapr->initrd_base = (spapr->kernel_addr + spapr->kernel_size 3075a19f7fb0SDavid Gibson + 0x1ffff) & ~0xffff; 3076a19f7fb0SDavid Gibson spapr->initrd_size = load_image_targphys(initrd_filename, 3077a19f7fb0SDavid Gibson spapr->initrd_base, 3078a19f7fb0SDavid Gibson load_limit 3079a19f7fb0SDavid Gibson - spapr->initrd_base); 3080a19f7fb0SDavid Gibson if (spapr->initrd_size < 0) { 3081d54e4d76SDavid Gibson error_report("could not load initial ram disk '%s'", 308253018216SPaolo Bonzini initrd_filename); 308353018216SPaolo Bonzini exit(1); 308453018216SPaolo Bonzini } 308553018216SPaolo Bonzini } 308653018216SPaolo Bonzini } 308753018216SPaolo Bonzini 308828e02042SDavid Gibson /* FIXME: Should register things through the MachineState's qdev 308928e02042SDavid Gibson * interface, this is a legacy from the sPAPREnvironment structure 309028e02042SDavid Gibson * which predated MachineState but had a similar function */ 30914be21d56SDavid Gibson vmstate_register(NULL, 0, &vmstate_spapr, spapr); 30921df2c9a2SPeter Xu register_savevm_live("spapr/htab", VMSTATE_INSTANCE_ID_ANY, 1, 30934be21d56SDavid Gibson &savevm_htab_handlers, spapr); 30944be21d56SDavid Gibson 30959bc6bfdfSMarkus Armbruster qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine)); 3096bb2bdd81SGreg Kurz 30975b2128d2SAlexander Graf qemu_register_boot_set(spapr_boot_set, spapr); 309842043e4fSLaurent Vivier 309993eac7b8SNicholas Piggin /* 310093eac7b8SNicholas Piggin * Nothing needs to be done to resume a suspended guest because 310193eac7b8SNicholas Piggin * suspending does not change the machine state, so no need for 310293eac7b8SNicholas Piggin * a ->wakeup method. 310393eac7b8SNicholas Piggin */ 310493eac7b8SNicholas Piggin qemu_register_wakeup_support(); 310593eac7b8SNicholas Piggin 310642043e4fSLaurent Vivier if (kvm_enabled()) { 31073dc410aeSAlexey Kardashevskiy /* to stop and start vmclock */ 310842043e4fSLaurent Vivier qemu_add_vm_change_state_handler(cpu_ppc_clock_vm_state_change, 310942043e4fSLaurent Vivier &spapr->tb); 31103dc410aeSAlexey Kardashevskiy 31113dc410aeSAlexey Kardashevskiy kvmppc_spapr_enable_inkernel_multitce(); 311242043e4fSLaurent Vivier } 31139ac703acSAravinda Prasad 31148af7e1feSNicholas Piggin qemu_cond_init(&spapr->fwnmi_machine_check_interlock_cond); 3115fc8c745dSAlexey Kardashevskiy if (spapr->vof) { 3116fc8c745dSAlexey Kardashevskiy spapr->vof->fw_size = fw_size; /* for claim() on itself */ 3117fc8c745dSAlexey Kardashevskiy spapr_register_hypercall(KVMPPC_H_VOF_CLIENT, spapr_h_vof_client); 3118fc8c745dSAlexey Kardashevskiy } 311981b205ceSAlexey Kardashevskiy 312081b205ceSAlexey Kardashevskiy spapr_watchdog_init(spapr); 312153018216SPaolo Bonzini } 312253018216SPaolo Bonzini 312307b10bc4SDaniel Henrique Barboza #define DEFAULT_KVM_TYPE "auto" 3124dc0ca80eSEric Auger static int spapr_kvm_type(MachineState *machine, const char *vm_type) 3125135a129aSAneesh Kumar K.V { 312607b10bc4SDaniel Henrique Barboza /* 312707b10bc4SDaniel Henrique Barboza * The use of g_ascii_strcasecmp() for 'hv' and 'pr' is to 3128e6a19a64SMichael Tokarev * accommodate the 'HV' and 'PV' formats that exists in the 312907b10bc4SDaniel Henrique Barboza * wild. The 'auto' mode is being introduced already as 313007b10bc4SDaniel Henrique Barboza * lower-case, thus we don't need to bother checking for 313107b10bc4SDaniel Henrique Barboza * "AUTO". 313207b10bc4SDaniel Henrique Barboza */ 313307b10bc4SDaniel Henrique Barboza if (!vm_type || !strcmp(vm_type, DEFAULT_KVM_TYPE)) { 3134135a129aSAneesh Kumar K.V return 0; 3135135a129aSAneesh Kumar K.V } 3136135a129aSAneesh Kumar K.V 313707b10bc4SDaniel Henrique Barboza if (!g_ascii_strcasecmp(vm_type, "hv")) { 3138135a129aSAneesh Kumar K.V return 1; 3139135a129aSAneesh Kumar K.V } 3140135a129aSAneesh Kumar K.V 314107b10bc4SDaniel Henrique Barboza if (!g_ascii_strcasecmp(vm_type, "pr")) { 3142135a129aSAneesh Kumar K.V return 2; 3143135a129aSAneesh Kumar K.V } 3144135a129aSAneesh Kumar K.V 3145135a129aSAneesh Kumar K.V error_report("Unknown kvm-type specified '%s'", vm_type); 3146bc3e41a0SAkihiko Odaki return -1; 3147135a129aSAneesh Kumar K.V } 3148135a129aSAneesh Kumar K.V 314971461b0fSAlexey Kardashevskiy /* 3150627b84f4SGonglei * Implementation of an interface to adjust firmware path 315171461b0fSAlexey Kardashevskiy * for the bootindex property handling. 315271461b0fSAlexey Kardashevskiy */ 315371461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, 315471461b0fSAlexey Kardashevskiy DeviceState *dev) 315571461b0fSAlexey Kardashevskiy { 315671461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \ 315771461b0fSAlexey Kardashevskiy ((type *)object_dynamic_cast(OBJECT(obj), (name))) 315871461b0fSAlexey Kardashevskiy SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); 3159ce2918cbSDavid Gibson SpaprPhbState *phb = CAST(SpaprPhbState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); 3160c4e13492SFelipe Franciosi VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON); 3161040bdafcSGreg Kurz PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); 316271461b0fSAlexey Kardashevskiy 31631977434bSDaniel Henrique Barboza if (d && bus) { 316471461b0fSAlexey Kardashevskiy void *spapr = CAST(void, bus->parent, "spapr-vscsi"); 316571461b0fSAlexey Kardashevskiy VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); 316671461b0fSAlexey Kardashevskiy USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); 316771461b0fSAlexey Kardashevskiy 316871461b0fSAlexey Kardashevskiy if (spapr) { 316971461b0fSAlexey Kardashevskiy /* 317071461b0fSAlexey Kardashevskiy * Replace "channel@0/disk@0,0" with "disk@8000000000000000": 31711ac24c91SThomas Huth * In the top 16 bits of the 64-bit LUN, we use SRP luns of the form 31721ac24c91SThomas Huth * 0x8000 | (target << 8) | (bus << 5) | lun 31731ac24c91SThomas Huth * (see the "Logical unit addressing format" table in SAM5) 317471461b0fSAlexey Kardashevskiy */ 31751ac24c91SThomas Huth unsigned id = 0x8000 | (d->id << 8) | (d->channel << 5) | d->lun; 317671461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 317771461b0fSAlexey Kardashevskiy (uint64_t)id << 48); 317871461b0fSAlexey Kardashevskiy } else if (virtio) { 317971461b0fSAlexey Kardashevskiy /* 318071461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (target << 8) | lun 318171461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 318271461b0fSAlexey Kardashevskiy * Note: the quote above is from SLOF and it is wrong, 318371461b0fSAlexey Kardashevskiy * the actual binding is: 318471461b0fSAlexey Kardashevskiy * swap 0100 or 10 << or 20 << ( target lun-id -- srplun ) 318571461b0fSAlexey Kardashevskiy */ 318671461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (d->id << 16) | d->lun; 3187bac658d1SThomas Huth if (d->lun >= 256) { 3188bac658d1SThomas Huth /* Use the LUN "flat space addressing method" */ 3189bac658d1SThomas Huth id |= 0x4000; 3190bac658d1SThomas Huth } 319171461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 319271461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 319371461b0fSAlexey Kardashevskiy } else if (usb) { 319471461b0fSAlexey Kardashevskiy /* 319571461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (usb-port << 16) | lun 319671461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 319771461b0fSAlexey Kardashevskiy */ 319871461b0fSAlexey Kardashevskiy unsigned usb_port = atoi(usb->port->path); 319971461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (usb_port << 16) | d->lun; 320071461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 320171461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 320271461b0fSAlexey Kardashevskiy } 320371461b0fSAlexey Kardashevskiy } 320471461b0fSAlexey Kardashevskiy 3205b99260ebSThomas Huth /* 3206b99260ebSThomas Huth * SLOF probes the USB devices, and if it recognizes that the device is a 3207b99260ebSThomas Huth * storage device, it changes its name to "storage" instead of "usb-host", 3208b99260ebSThomas Huth * and additionally adds a child node for the SCSI LUN, so the correct 3209b99260ebSThomas Huth * boot path in SLOF is something like .../storage@1/disk@xxx" instead. 3210b99260ebSThomas Huth */ 3211b99260ebSThomas Huth if (strcmp("usb-host", qdev_fw_name(dev)) == 0) { 3212b99260ebSThomas Huth USBDevice *usbdev = CAST(USBDevice, dev, TYPE_USB_DEVICE); 3213b7b2a60bSGerd Hoffmann if (usb_device_is_scsi_storage(usbdev)) { 3214b99260ebSThomas Huth return g_strdup_printf("storage@%s/disk", usbdev->port->path); 3215b99260ebSThomas Huth } 3216b99260ebSThomas Huth } 3217b99260ebSThomas Huth 321871461b0fSAlexey Kardashevskiy if (phb) { 321971461b0fSAlexey Kardashevskiy /* Replace "pci" with "pci@800000020000000" */ 322071461b0fSAlexey Kardashevskiy return g_strdup_printf("pci@%"PRIX64, phb->buid); 322171461b0fSAlexey Kardashevskiy } 322271461b0fSAlexey Kardashevskiy 3223c4e13492SFelipe Franciosi if (vsc) { 3224c4e13492SFelipe Franciosi /* Same logic as virtio above */ 3225c4e13492SFelipe Franciosi unsigned id = 0x1000000 | (vsc->target << 16) | vsc->lun; 3226c4e13492SFelipe Franciosi return g_strdup_printf("disk@%"PRIX64, (uint64_t)id << 32); 3227c4e13492SFelipe Franciosi } 3228c4e13492SFelipe Franciosi 32294871dd4cSThomas Huth if (g_str_equal("pci-bridge", qdev_fw_name(dev))) { 32304871dd4cSThomas Huth /* SLOF uses "pci" instead of "pci-bridge" for PCI bridges */ 323101a78f23SCédric Le Goater PCIDevice *pdev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); 323201a78f23SCédric Le Goater return g_strdup_printf("pci@%x", PCI_SLOT(pdev->devfn)); 32334871dd4cSThomas Huth } 32344871dd4cSThomas Huth 3235040bdafcSGreg Kurz if (pcidev) { 3236040bdafcSGreg Kurz return spapr_pci_fw_dev_name(pcidev); 3237040bdafcSGreg Kurz } 3238040bdafcSGreg Kurz 323971461b0fSAlexey Kardashevskiy return NULL; 324071461b0fSAlexey Kardashevskiy } 324171461b0fSAlexey Kardashevskiy 324223825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp) 324323825581SEduardo Habkost { 3244ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 324523825581SEduardo Habkost 324628e02042SDavid Gibson return g_strdup(spapr->kvm_type); 324723825581SEduardo Habkost } 324823825581SEduardo Habkost 324923825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp) 325023825581SEduardo Habkost { 3251ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 325223825581SEduardo Habkost 325328e02042SDavid Gibson g_free(spapr->kvm_type); 325428e02042SDavid Gibson spapr->kvm_type = g_strdup(value); 325523825581SEduardo Habkost } 325623825581SEduardo Habkost 3257f6229214SMichael Roth static bool spapr_get_modern_hotplug_events(Object *obj, Error **errp) 3258f6229214SMichael Roth { 3259ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3260f6229214SMichael Roth 3261f6229214SMichael Roth return spapr->use_hotplug_event_source; 3262f6229214SMichael Roth } 3263f6229214SMichael Roth 3264f6229214SMichael Roth static void spapr_set_modern_hotplug_events(Object *obj, bool value, 3265f6229214SMichael Roth Error **errp) 3266f6229214SMichael Roth { 3267ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3268f6229214SMichael Roth 3269f6229214SMichael Roth spapr->use_hotplug_event_source = value; 3270f6229214SMichael Roth } 3271f6229214SMichael Roth 3272fcad0d21SAlexey Kardashevskiy static bool spapr_get_msix_emulation(Object *obj, Error **errp) 3273fcad0d21SAlexey Kardashevskiy { 3274fcad0d21SAlexey Kardashevskiy return true; 3275fcad0d21SAlexey Kardashevskiy } 3276fcad0d21SAlexey Kardashevskiy 327730f4b05bSDavid Gibson static char *spapr_get_resize_hpt(Object *obj, Error **errp) 327830f4b05bSDavid Gibson { 3279ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 328030f4b05bSDavid Gibson 328130f4b05bSDavid Gibson switch (spapr->resize_hpt) { 328230f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DEFAULT: 328330f4b05bSDavid Gibson return g_strdup("default"); 328430f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DISABLED: 328530f4b05bSDavid Gibson return g_strdup("disabled"); 328630f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_ENABLED: 328730f4b05bSDavid Gibson return g_strdup("enabled"); 328830f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_REQUIRED: 328930f4b05bSDavid Gibson return g_strdup("required"); 329030f4b05bSDavid Gibson } 329130f4b05bSDavid Gibson g_assert_not_reached(); 329230f4b05bSDavid Gibson } 329330f4b05bSDavid Gibson 329430f4b05bSDavid Gibson static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp) 329530f4b05bSDavid Gibson { 3296ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 329730f4b05bSDavid Gibson 329830f4b05bSDavid Gibson if (strcmp(value, "default") == 0) { 329930f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DEFAULT; 330030f4b05bSDavid Gibson } else if (strcmp(value, "disabled") == 0) { 330130f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 330230f4b05bSDavid Gibson } else if (strcmp(value, "enabled") == 0) { 330330f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_ENABLED; 330430f4b05bSDavid Gibson } else if (strcmp(value, "required") == 0) { 330530f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_REQUIRED; 330630f4b05bSDavid Gibson } else { 330730f4b05bSDavid Gibson error_setg(errp, "Bad value for \"resize-hpt\" property"); 330830f4b05bSDavid Gibson } 330930f4b05bSDavid Gibson } 331030f4b05bSDavid Gibson 3311fc8c745dSAlexey Kardashevskiy static bool spapr_get_vof(Object *obj, Error **errp) 3312fc8c745dSAlexey Kardashevskiy { 3313fc8c745dSAlexey Kardashevskiy SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3314fc8c745dSAlexey Kardashevskiy 3315fc8c745dSAlexey Kardashevskiy return spapr->vof != NULL; 3316fc8c745dSAlexey Kardashevskiy } 3317fc8c745dSAlexey Kardashevskiy 3318fc8c745dSAlexey Kardashevskiy static void spapr_set_vof(Object *obj, bool value, Error **errp) 3319fc8c745dSAlexey Kardashevskiy { 3320fc8c745dSAlexey Kardashevskiy SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3321fc8c745dSAlexey Kardashevskiy 3322fc8c745dSAlexey Kardashevskiy if (spapr->vof) { 3323fc8c745dSAlexey Kardashevskiy vof_cleanup(spapr->vof); 3324fc8c745dSAlexey Kardashevskiy g_free(spapr->vof); 3325fc8c745dSAlexey Kardashevskiy spapr->vof = NULL; 3326fc8c745dSAlexey Kardashevskiy } 3327fc8c745dSAlexey Kardashevskiy if (!value) { 3328fc8c745dSAlexey Kardashevskiy return; 3329fc8c745dSAlexey Kardashevskiy } 3330fc8c745dSAlexey Kardashevskiy spapr->vof = g_malloc0(sizeof(*spapr->vof)); 3331fc8c745dSAlexey Kardashevskiy } 3332fc8c745dSAlexey Kardashevskiy 33333ba3d0bcSCédric Le Goater static char *spapr_get_ic_mode(Object *obj, Error **errp) 33343ba3d0bcSCédric Le Goater { 3335ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 33363ba3d0bcSCédric Le Goater 33373ba3d0bcSCédric Le Goater if (spapr->irq == &spapr_irq_xics_legacy) { 33383ba3d0bcSCédric Le Goater return g_strdup("legacy"); 33393ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xics) { 33403ba3d0bcSCédric Le Goater return g_strdup("xics"); 33413ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xive) { 33423ba3d0bcSCédric Le Goater return g_strdup("xive"); 334313db0cd9SCédric Le Goater } else if (spapr->irq == &spapr_irq_dual) { 334413db0cd9SCédric Le Goater return g_strdup("dual"); 33453ba3d0bcSCédric Le Goater } 33463ba3d0bcSCédric Le Goater g_assert_not_reached(); 33473ba3d0bcSCédric Le Goater } 33483ba3d0bcSCédric Le Goater 33493ba3d0bcSCédric Le Goater static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp) 33503ba3d0bcSCédric Le Goater { 3351ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 33523ba3d0bcSCédric Le Goater 335321df5e4fSGreg Kurz if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { 335421df5e4fSGreg Kurz error_setg(errp, "This machine only uses the legacy XICS backend, don't pass ic-mode"); 335521df5e4fSGreg Kurz return; 335621df5e4fSGreg Kurz } 335721df5e4fSGreg Kurz 33583ba3d0bcSCédric Le Goater /* The legacy IRQ backend can not be set */ 33593ba3d0bcSCédric Le Goater if (strcmp(value, "xics") == 0) { 33603ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xics; 33613ba3d0bcSCédric Le Goater } else if (strcmp(value, "xive") == 0) { 33623ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xive; 336313db0cd9SCédric Le Goater } else if (strcmp(value, "dual") == 0) { 336413db0cd9SCédric Le Goater spapr->irq = &spapr_irq_dual; 33653ba3d0bcSCédric Le Goater } else { 33663ba3d0bcSCédric Le Goater error_setg(errp, "Bad value for \"ic-mode\" property"); 33673ba3d0bcSCédric Le Goater } 33683ba3d0bcSCédric Le Goater } 33693ba3d0bcSCédric Le Goater 337027461d69SPrasad J Pandit static char *spapr_get_host_model(Object *obj, Error **errp) 337127461d69SPrasad J Pandit { 3372ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 337327461d69SPrasad J Pandit 337427461d69SPrasad J Pandit return g_strdup(spapr->host_model); 337527461d69SPrasad J Pandit } 337627461d69SPrasad J Pandit 337727461d69SPrasad J Pandit static void spapr_set_host_model(Object *obj, const char *value, Error **errp) 337827461d69SPrasad J Pandit { 3379ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 338027461d69SPrasad J Pandit 338127461d69SPrasad J Pandit g_free(spapr->host_model); 338227461d69SPrasad J Pandit spapr->host_model = g_strdup(value); 338327461d69SPrasad J Pandit } 338427461d69SPrasad J Pandit 338527461d69SPrasad J Pandit static char *spapr_get_host_serial(Object *obj, Error **errp) 338627461d69SPrasad J Pandit { 3387ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 338827461d69SPrasad J Pandit 338927461d69SPrasad J Pandit return g_strdup(spapr->host_serial); 339027461d69SPrasad J Pandit } 339127461d69SPrasad J Pandit 339227461d69SPrasad J Pandit static void spapr_set_host_serial(Object *obj, const char *value, Error **errp) 339327461d69SPrasad J Pandit { 3394ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 339527461d69SPrasad J Pandit 339627461d69SPrasad J Pandit g_free(spapr->host_serial); 339727461d69SPrasad J Pandit spapr->host_serial = g_strdup(value); 339827461d69SPrasad J Pandit } 339927461d69SPrasad J Pandit 3400bcb5ce08SDavid Gibson static void spapr_instance_init(Object *obj) 340123825581SEduardo Habkost { 3402ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 3403ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 340455810e90SIgor Mammedov MachineState *ms = MACHINE(spapr); 340555810e90SIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(ms); 340655810e90SIgor Mammedov 340755810e90SIgor Mammedov /* 340855810e90SIgor Mammedov * NVDIMM support went live in 5.1 without considering that, in 340955810e90SIgor Mammedov * other archs, the user needs to enable NVDIMM support with the 341055810e90SIgor Mammedov * 'nvdimm' machine option and the default behavior is NVDIMM 341155810e90SIgor Mammedov * support disabled. It is too late to roll back to the standard 341255810e90SIgor Mammedov * behavior without breaking 5.1 guests. 341355810e90SIgor Mammedov */ 341455810e90SIgor Mammedov if (mc->nvdimm_supported) { 341555810e90SIgor Mammedov ms->nvdimms_state->is_enabled = true; 341655810e90SIgor Mammedov } 3417715c5407SDavid Gibson 3418715c5407SDavid Gibson spapr->htab_fd = -1; 3419f6229214SMichael Roth spapr->use_hotplug_event_source = true; 342007b10bc4SDaniel Henrique Barboza spapr->kvm_type = g_strdup(DEFAULT_KVM_TYPE); 342123825581SEduardo Habkost object_property_add_str(obj, "kvm-type", 3422d2623129SMarkus Armbruster spapr_get_kvm_type, spapr_set_kvm_type); 342349d2e648SMarcel Apfelbaum object_property_set_description(obj, "kvm-type", 342407b10bc4SDaniel Henrique Barboza "Specifies the KVM virtualization mode (auto," 342507b10bc4SDaniel Henrique Barboza " hv, pr). Defaults to 'auto'. This mode will use" 342607b10bc4SDaniel Henrique Barboza " any available KVM module loaded in the host," 342707b10bc4SDaniel Henrique Barboza " where kvm_hv takes precedence if both kvm_hv and" 342807b10bc4SDaniel Henrique Barboza " kvm_pr are loaded."); 3429f6229214SMichael Roth object_property_add_bool(obj, "modern-hotplug-events", 3430f6229214SMichael Roth spapr_get_modern_hotplug_events, 3431d2623129SMarkus Armbruster spapr_set_modern_hotplug_events); 3432f6229214SMichael Roth object_property_set_description(obj, "modern-hotplug-events", 3433f6229214SMichael Roth "Use dedicated hotplug event mechanism in" 3434f6229214SMichael Roth " place of standard EPOW events when possible" 34357eecec7dSMarkus Armbruster " (required for memory hot-unplug support)"); 34367843c0d6SDavid Gibson ppc_compat_add_property(obj, "max-cpu-compat", &spapr->max_compat_pvr, 343740c2281cSMarkus Armbruster "Maximum permitted CPU compatibility mode"); 343830f4b05bSDavid Gibson 343930f4b05bSDavid Gibson object_property_add_str(obj, "resize-hpt", 3440d2623129SMarkus Armbruster spapr_get_resize_hpt, spapr_set_resize_hpt); 344130f4b05bSDavid Gibson object_property_set_description(obj, "resize-hpt", 34427eecec7dSMarkus Armbruster "Resizing of the Hash Page Table (enabled, disabled, required)"); 344364a7b8deSFelipe Franciosi object_property_add_uint32_ptr(obj, "vsmt", 3444d2623129SMarkus Armbruster &spapr->vsmt, OBJ_PROP_FLAG_READWRITE); 3445fa98fbfcSSam Bobroff object_property_set_description(obj, "vsmt", 3446fa98fbfcSSam Bobroff "Virtual SMT: KVM behaves as if this were" 34477eecec7dSMarkus Armbruster " the host's SMT mode"); 344864a7b8deSFelipe Franciosi 3449fcad0d21SAlexey Kardashevskiy object_property_add_bool(obj, "vfio-no-msix-emulation", 3450d2623129SMarkus Armbruster spapr_get_msix_emulation, NULL); 34513ba3d0bcSCédric Le Goater 345264a7b8deSFelipe Franciosi object_property_add_uint64_ptr(obj, "kernel-addr", 3453d2623129SMarkus Armbruster &spapr->kernel_addr, OBJ_PROP_FLAG_READWRITE); 345487262806SAlexey Kardashevskiy object_property_set_description(obj, "kernel-addr", 345587262806SAlexey Kardashevskiy stringify(KERNEL_LOAD_ADDR) 34567eecec7dSMarkus Armbruster " for -kernel is the default"); 345787262806SAlexey Kardashevskiy spapr->kernel_addr = KERNEL_LOAD_ADDR; 3458fc8c745dSAlexey Kardashevskiy 3459fc8c745dSAlexey Kardashevskiy object_property_add_bool(obj, "x-vof", spapr_get_vof, spapr_set_vof); 3460fc8c745dSAlexey Kardashevskiy object_property_set_description(obj, "x-vof", 3461fc8c745dSAlexey Kardashevskiy "Enable Virtual Open Firmware (experimental)"); 3462fc8c745dSAlexey Kardashevskiy 34633ba3d0bcSCédric Le Goater /* The machine class defines the default interrupt controller mode */ 34643ba3d0bcSCédric Le Goater spapr->irq = smc->irq; 34653ba3d0bcSCédric Le Goater object_property_add_str(obj, "ic-mode", spapr_get_ic_mode, 3466d2623129SMarkus Armbruster spapr_set_ic_mode); 34673ba3d0bcSCédric Le Goater object_property_set_description(obj, "ic-mode", 34687eecec7dSMarkus Armbruster "Specifies the interrupt controller mode (xics, xive, dual)"); 346927461d69SPrasad J Pandit 347027461d69SPrasad J Pandit object_property_add_str(obj, "host-model", 3471d2623129SMarkus Armbruster spapr_get_host_model, spapr_set_host_model); 347227461d69SPrasad J Pandit object_property_set_description(obj, "host-model", 34737eecec7dSMarkus Armbruster "Host model to advertise in guest device tree"); 347427461d69SPrasad J Pandit object_property_add_str(obj, "host-serial", 3475d2623129SMarkus Armbruster spapr_get_host_serial, spapr_set_host_serial); 347627461d69SPrasad J Pandit object_property_set_description(obj, "host-serial", 34777eecec7dSMarkus Armbruster "Host serial number to advertise in guest device tree"); 347823825581SEduardo Habkost } 347923825581SEduardo Habkost 348087bbdd9cSDavid Gibson static void spapr_machine_finalizefn(Object *obj) 348187bbdd9cSDavid Gibson { 3482ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 348387bbdd9cSDavid Gibson 348487bbdd9cSDavid Gibson g_free(spapr->kvm_type); 348587bbdd9cSDavid Gibson } 348687bbdd9cSDavid Gibson 34871c7ad77eSNicholas Piggin void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg) 348834316482SAlexey Kardashevskiy { 34890e236d34SNicholas Piggin SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 3490b5b7f391SNicholas Piggin PowerPCCPU *cpu = POWERPC_CPU(cs); 3491b5b7f391SNicholas Piggin CPUPPCState *env = &cpu->env; 34920e236d34SNicholas Piggin 349334316482SAlexey Kardashevskiy cpu_synchronize_state(cs); 34940e236d34SNicholas Piggin /* If FWNMI is inactive, addr will be -1, which will deliver to 0x100 */ 34950e236d34SNicholas Piggin if (spapr->fwnmi_system_reset_addr != -1) { 34960e236d34SNicholas Piggin uint64_t rtas_addr, addr; 34970e236d34SNicholas Piggin 34980e236d34SNicholas Piggin /* get rtas addr from fdt */ 34990e236d34SNicholas Piggin rtas_addr = spapr_get_rtas_addr(); 35000e236d34SNicholas Piggin if (!rtas_addr) { 35010e236d34SNicholas Piggin qemu_system_guest_panicked(NULL); 35020e236d34SNicholas Piggin return; 35030e236d34SNicholas Piggin } 35040e236d34SNicholas Piggin 35050e236d34SNicholas Piggin addr = rtas_addr + RTAS_ERROR_LOG_MAX + cs->cpu_index * sizeof(uint64_t)*2; 35060e236d34SNicholas Piggin stq_be_phys(&address_space_memory, addr, env->gpr[3]); 35070e236d34SNicholas Piggin stq_be_phys(&address_space_memory, addr + sizeof(uint64_t), 0); 35080e236d34SNicholas Piggin env->gpr[3] = addr; 35090e236d34SNicholas Piggin } 3510b5b7f391SNicholas Piggin ppc_cpu_do_system_reset(cs); 3511b5b7f391SNicholas Piggin if (spapr->fwnmi_system_reset_addr != -1) { 3512b5b7f391SNicholas Piggin env->nip = spapr->fwnmi_system_reset_addr; 3513b5b7f391SNicholas Piggin } 351434316482SAlexey Kardashevskiy } 351534316482SAlexey Kardashevskiy 351634316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) 351734316482SAlexey Kardashevskiy { 351834316482SAlexey Kardashevskiy CPUState *cs; 351934316482SAlexey Kardashevskiy 352034316482SAlexey Kardashevskiy CPU_FOREACH(cs) { 35211c7ad77eSNicholas Piggin async_run_on_cpu(cs, spapr_do_system_reset_on_cpu, RUN_ON_CPU_NULL); 352234316482SAlexey Kardashevskiy } 352334316482SAlexey Kardashevskiy } 352434316482SAlexey Kardashevskiy 3525ce2918cbSDavid Gibson int spapr_lmb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 352662d38c9bSGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 352762d38c9bSGreg Kurz { 352862d38c9bSGreg Kurz uint64_t addr; 352962d38c9bSGreg Kurz uint32_t node; 353062d38c9bSGreg Kurz 353162d38c9bSGreg Kurz addr = spapr_drc_index(drc) * SPAPR_MEMORY_BLOCK_SIZE; 353262d38c9bSGreg Kurz node = object_property_get_uint(OBJECT(drc->dev), PC_DIMM_NODE_PROP, 353362d38c9bSGreg Kurz &error_abort); 3534f1aa45ffSDaniel Henrique Barboza *fdt_start_offset = spapr_dt_memory_node(spapr, fdt, node, addr, 353562d38c9bSGreg Kurz SPAPR_MEMORY_BLOCK_SIZE); 353662d38c9bSGreg Kurz return 0; 353762d38c9bSGreg Kurz } 353862d38c9bSGreg Kurz 3539ea042c53SGreg Kurz static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, 3540ea042c53SGreg Kurz bool dedicated_hp_event_source) 3541c20d332aSBharata B Rao { 3542ce2918cbSDavid Gibson SpaprDrc *drc; 3543c20d332aSBharata B Rao uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; 354462d38c9bSGreg Kurz int i; 354579b78a6bSMichael Roth uint64_t addr = addr_start; 354694fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 3547c20d332aSBharata B Rao 3548c20d332aSBharata B Rao for (i = 0; i < nr_lmbs; i++) { 3549fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 3550c20d332aSBharata B Rao addr / SPAPR_MEMORY_BLOCK_SIZE); 3551c20d332aSBharata B Rao g_assert(drc); 3552c20d332aSBharata B Rao 3553ea042c53SGreg Kurz /* 3554ea042c53SGreg Kurz * memory_device_get_free_addr() provided a range of free addresses 3555ea042c53SGreg Kurz * that doesn't overlap with any existing mapping at pre-plug. The 3556ea042c53SGreg Kurz * corresponding LMB DRCs are thus assumed to be all attachable. 3557ea042c53SGreg Kurz */ 3558bc370a65SGreg Kurz spapr_drc_attach(drc, dev); 355994fd9cbaSLaurent Vivier if (!hotplugged) { 356094fd9cbaSLaurent Vivier spapr_drc_reset(drc); 356194fd9cbaSLaurent Vivier } 3562c20d332aSBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE; 3563c20d332aSBharata B Rao } 35645dd5238cSJianjun Duan /* send hotplug notification to the 35655dd5238cSJianjun Duan * guest only in case of hotplugged memory 35665dd5238cSJianjun Duan */ 356794fd9cbaSLaurent Vivier if (hotplugged) { 356879b78a6bSMichael Roth if (dedicated_hp_event_source) { 3569fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 357079b78a6bSMichael Roth addr_start / SPAPR_MEMORY_BLOCK_SIZE); 357173231f7cSGreg Kurz g_assert(drc); 357279b78a6bSMichael Roth spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 357379b78a6bSMichael Roth nr_lmbs, 35740b55aa91SDavid Gibson spapr_drc_index(drc)); 357579b78a6bSMichael Roth } else { 357679b78a6bSMichael Roth spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, 357779b78a6bSMichael Roth nr_lmbs); 357879b78a6bSMichael Roth } 3579c20d332aSBharata B Rao } 35805dd5238cSJianjun Duan } 3581c20d332aSBharata B Rao 3582ea042c53SGreg Kurz static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev) 3583c20d332aSBharata B Rao { 3584ce2918cbSDavid Gibson SpaprMachineState *ms = SPAPR_MACHINE(hotplug_dev); 3585c20d332aSBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 3586581778ddSGreg Kurz uint64_t size, addr; 3587581778ddSGreg Kurz int64_t slot; 3588ee3a71e3SShivaprasad G Bhat bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); 358904790978SThomas Huth 3590946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dev), &error_abort); 3591df587133SThomas Huth 359284fd5496SGreg Kurz pc_dimm_plug(dimm, MACHINE(ms)); 3593c20d332aSBharata B Rao 3594ee3a71e3SShivaprasad G Bhat if (!is_nvdimm) { 35959ed442b8SMarc-André Lureau addr = object_property_get_uint(OBJECT(dimm), 3596271ced1dSGreg Kurz PC_DIMM_ADDR_PROP, &error_abort); 3597ea042c53SGreg Kurz spapr_add_lmbs(dev, addr, size, 3598ea042c53SGreg Kurz spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT)); 3599ee3a71e3SShivaprasad G Bhat } else { 3600581778ddSGreg Kurz slot = object_property_get_int(OBJECT(dimm), 3601271ced1dSGreg Kurz PC_DIMM_SLOT_PROP, &error_abort); 3602581778ddSGreg Kurz /* We should have valid slot number at this point */ 3603581778ddSGreg Kurz g_assert(slot >= 0); 3604ea042c53SGreg Kurz spapr_add_nvdimm(dev, slot); 3605160bb678SGreg Kurz } 36066e837f98SGreg Kurz } 3607c20d332aSBharata B Rao 3608c871bc70SLaurent Vivier static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3609c871bc70SLaurent Vivier Error **errp) 3610c871bc70SLaurent Vivier { 3611ce2918cbSDavid Gibson const SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev); 3612ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3613ee3a71e3SShivaprasad G Bhat bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); 3614c871bc70SLaurent Vivier PCDIMMDevice *dimm = PC_DIMM(dev); 36158f1ffe5bSDavid Hildenbrand Error *local_err = NULL; 361604790978SThomas Huth uint64_t size; 3617123eec65SDavid Gibson Object *memdev; 3618123eec65SDavid Gibson hwaddr pagesize; 3619c871bc70SLaurent Vivier 36204e8a01bdSDavid Hildenbrand if (!smc->dr_lmb_enabled) { 36214e8a01bdSDavid Hildenbrand error_setg(errp, "Memory hotplug not supported for this machine"); 36224e8a01bdSDavid Hildenbrand return; 36234e8a01bdSDavid Hildenbrand } 36244e8a01bdSDavid Hildenbrand 3625946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &local_err); 3626946d6154SDavid Hildenbrand if (local_err) { 3627946d6154SDavid Hildenbrand error_propagate(errp, local_err); 362804790978SThomas Huth return; 362904790978SThomas Huth } 363004790978SThomas Huth 3631beb6073fSDaniel Henrique Barboza if (is_nvdimm) { 3632451c6905SGreg Kurz if (!spapr_nvdimm_validate(hotplug_dev, NVDIMM(dev), size, errp)) { 3633ee3a71e3SShivaprasad G Bhat return; 3634ee3a71e3SShivaprasad G Bhat } 3635beb6073fSDaniel Henrique Barboza } else if (size % SPAPR_MEMORY_BLOCK_SIZE) { 3636beb6073fSDaniel Henrique Barboza error_setg(errp, "Hotplugged memory size must be a multiple of " 3637beb6073fSDaniel Henrique Barboza "%" PRIu64 " MB", SPAPR_MEMORY_BLOCK_SIZE / MiB); 3638beb6073fSDaniel Henrique Barboza return; 3639c871bc70SLaurent Vivier } 3640c871bc70SLaurent Vivier 3641123eec65SDavid Gibson memdev = object_property_get_link(OBJECT(dimm), PC_DIMM_MEMDEV_PROP, 3642123eec65SDavid Gibson &error_abort); 3643123eec65SDavid Gibson pagesize = host_memory_backend_pagesize(MEMORY_BACKEND(memdev)); 364435dce34fSGreg Kurz if (!spapr_check_pagesize(spapr, pagesize, errp)) { 36458f1ffe5bSDavid Hildenbrand return; 36468f1ffe5bSDavid Hildenbrand } 36478f1ffe5bSDavid Hildenbrand 3648fd3416f5SDavid Hildenbrand pc_dimm_pre_plug(dimm, MACHINE(hotplug_dev), NULL, errp); 3649c871bc70SLaurent Vivier } 3650c871bc70SLaurent Vivier 3651ce2918cbSDavid Gibson struct SpaprDimmState { 36520cffce56SDavid Gibson PCDIMMDevice *dimm; 3653cf632463SBharata B Rao uint32_t nr_lmbs; 3654ce2918cbSDavid Gibson QTAILQ_ENTRY(SpaprDimmState) next; 36550cffce56SDavid Gibson }; 36560cffce56SDavid Gibson 3657ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_find(SpaprMachineState *s, 36580cffce56SDavid Gibson PCDIMMDevice *dimm) 36590cffce56SDavid Gibson { 3660ce2918cbSDavid Gibson SpaprDimmState *dimm_state = NULL; 36610cffce56SDavid Gibson 36620cffce56SDavid Gibson QTAILQ_FOREACH(dimm_state, &s->pending_dimm_unplugs, next) { 36630cffce56SDavid Gibson if (dimm_state->dimm == dimm) { 36640cffce56SDavid Gibson break; 36650cffce56SDavid Gibson } 36660cffce56SDavid Gibson } 36670cffce56SDavid Gibson return dimm_state; 36680cffce56SDavid Gibson } 36690cffce56SDavid Gibson 3670ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_add(SpaprMachineState *spapr, 36718d5981c4SBharata B Rao uint32_t nr_lmbs, 36728d5981c4SBharata B Rao PCDIMMDevice *dimm) 36730cffce56SDavid Gibson { 3674ce2918cbSDavid Gibson SpaprDimmState *ds = NULL; 36758d5981c4SBharata B Rao 36768d5981c4SBharata B Rao /* 36778d5981c4SBharata B Rao * If this request is for a DIMM whose removal had failed earlier 36788d5981c4SBharata B Rao * (due to guest's refusal to remove the LMBs), we would have this 36798d5981c4SBharata B Rao * dimm already in the pending_dimm_unplugs list. In that 36808d5981c4SBharata B Rao * case don't add again. 36818d5981c4SBharata B Rao */ 36828d5981c4SBharata B Rao ds = spapr_pending_dimm_unplugs_find(spapr, dimm); 36838d5981c4SBharata B Rao if (!ds) { 3684b21e2380SMarkus Armbruster ds = g_new0(SpaprDimmState, 1); 36858d5981c4SBharata B Rao ds->nr_lmbs = nr_lmbs; 36868d5981c4SBharata B Rao ds->dimm = dimm; 36878d5981c4SBharata B Rao QTAILQ_INSERT_HEAD(&spapr->pending_dimm_unplugs, ds, next); 36888d5981c4SBharata B Rao } 36898d5981c4SBharata B Rao return ds; 36900cffce56SDavid Gibson } 36910cffce56SDavid Gibson 3692ce2918cbSDavid Gibson static void spapr_pending_dimm_unplugs_remove(SpaprMachineState *spapr, 3693ce2918cbSDavid Gibson SpaprDimmState *dimm_state) 36940cffce56SDavid Gibson { 36950cffce56SDavid Gibson QTAILQ_REMOVE(&spapr->pending_dimm_unplugs, dimm_state, next); 36960cffce56SDavid Gibson g_free(dimm_state); 36970cffce56SDavid Gibson } 3698cf632463SBharata B Rao 3699ce2918cbSDavid Gibson static SpaprDimmState *spapr_recover_pending_dimm_state(SpaprMachineState *ms, 370016ee9980SDaniel Henrique Barboza PCDIMMDevice *dimm) 370116ee9980SDaniel Henrique Barboza { 3702ce2918cbSDavid Gibson SpaprDrc *drc; 3703946d6154SDavid Hildenbrand uint64_t size = memory_device_get_region_size(MEMORY_DEVICE(dimm), 3704946d6154SDavid Hildenbrand &error_abort); 370516ee9980SDaniel Henrique Barboza uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 370616ee9980SDaniel Henrique Barboza uint32_t avail_lmbs = 0; 370716ee9980SDaniel Henrique Barboza uint64_t addr_start, addr; 370816ee9980SDaniel Henrique Barboza int i; 370916ee9980SDaniel Henrique Barboza 371065226afdSGreg Kurz addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, 371116ee9980SDaniel Henrique Barboza &error_abort); 371216ee9980SDaniel Henrique Barboza 371316ee9980SDaniel Henrique Barboza addr = addr_start; 371416ee9980SDaniel Henrique Barboza for (i = 0; i < nr_lmbs; i++) { 3715fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 371616ee9980SDaniel Henrique Barboza addr / SPAPR_MEMORY_BLOCK_SIZE); 371716ee9980SDaniel Henrique Barboza g_assert(drc); 3718454b580aSDavid Gibson if (drc->dev) { 371916ee9980SDaniel Henrique Barboza avail_lmbs++; 372016ee9980SDaniel Henrique Barboza } 372116ee9980SDaniel Henrique Barboza addr += SPAPR_MEMORY_BLOCK_SIZE; 372216ee9980SDaniel Henrique Barboza } 372316ee9980SDaniel Henrique Barboza 37248d5981c4SBharata B Rao return spapr_pending_dimm_unplugs_add(ms, avail_lmbs, dimm); 372516ee9980SDaniel Henrique Barboza } 372616ee9980SDaniel Henrique Barboza 3727eb7f80fdSDaniel Henrique Barboza void spapr_memory_unplug_rollback(SpaprMachineState *spapr, DeviceState *dev) 3728fe1831efSDaniel Henrique Barboza { 3729fe1831efSDaniel Henrique Barboza SpaprDimmState *ds; 3730fe1831efSDaniel Henrique Barboza PCDIMMDevice *dimm; 3731fe1831efSDaniel Henrique Barboza SpaprDrc *drc; 3732fe1831efSDaniel Henrique Barboza uint32_t nr_lmbs; 3733fe1831efSDaniel Henrique Barboza uint64_t size, addr_start, addr; 3734eb7f80fdSDaniel Henrique Barboza g_autofree char *qapi_error = NULL; 3735fe1831efSDaniel Henrique Barboza int i; 3736fe1831efSDaniel Henrique Barboza 3737fe1831efSDaniel Henrique Barboza if (!dev) { 3738fe1831efSDaniel Henrique Barboza return; 3739fe1831efSDaniel Henrique Barboza } 3740fe1831efSDaniel Henrique Barboza 3741fe1831efSDaniel Henrique Barboza dimm = PC_DIMM(dev); 3742fe1831efSDaniel Henrique Barboza ds = spapr_pending_dimm_unplugs_find(spapr, dimm); 3743fe1831efSDaniel Henrique Barboza 3744fe1831efSDaniel Henrique Barboza /* 3745fe1831efSDaniel Henrique Barboza * 'ds == NULL' would mean that the DIMM doesn't have a pending 3746fe1831efSDaniel Henrique Barboza * unplug state, but one of its DRC is marked as unplug_requested. 3747fe1831efSDaniel Henrique Barboza * This is bad and weird enough to g_assert() out. 3748fe1831efSDaniel Henrique Barboza */ 3749fe1831efSDaniel Henrique Barboza g_assert(ds); 3750fe1831efSDaniel Henrique Barboza 3751fe1831efSDaniel Henrique Barboza spapr_pending_dimm_unplugs_remove(spapr, ds); 3752fe1831efSDaniel Henrique Barboza 3753fe1831efSDaniel Henrique Barboza size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &error_abort); 3754fe1831efSDaniel Henrique Barboza nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 3755fe1831efSDaniel Henrique Barboza 3756fe1831efSDaniel Henrique Barboza addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, 3757fe1831efSDaniel Henrique Barboza &error_abort); 3758fe1831efSDaniel Henrique Barboza 3759fe1831efSDaniel Henrique Barboza addr = addr_start; 3760fe1831efSDaniel Henrique Barboza for (i = 0; i < nr_lmbs; i++) { 3761fe1831efSDaniel Henrique Barboza drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 3762fe1831efSDaniel Henrique Barboza addr / SPAPR_MEMORY_BLOCK_SIZE); 3763fe1831efSDaniel Henrique Barboza g_assert(drc); 3764fe1831efSDaniel Henrique Barboza 3765fe1831efSDaniel Henrique Barboza drc->unplug_requested = false; 3766fe1831efSDaniel Henrique Barboza addr += SPAPR_MEMORY_BLOCK_SIZE; 3767fe1831efSDaniel Henrique Barboza } 3768eb7f80fdSDaniel Henrique Barboza 3769eb7f80fdSDaniel Henrique Barboza /* 3770eb7f80fdSDaniel Henrique Barboza * Tell QAPI that something happened and the memory 37714b08cd56SDaniel Henrique Barboza * hotunplug wasn't successful. Keep sending 37724b08cd56SDaniel Henrique Barboza * MEM_UNPLUG_ERROR even while sending 37734b08cd56SDaniel Henrique Barboza * DEVICE_UNPLUG_GUEST_ERROR until the deprecation of 37744b08cd56SDaniel Henrique Barboza * MEM_UNPLUG_ERROR is due. 3775eb7f80fdSDaniel Henrique Barboza */ 3776eb7f80fdSDaniel Henrique Barboza qapi_error = g_strdup_printf("Memory hotunplug rejected by the guest " 3777eb7f80fdSDaniel Henrique Barboza "for device %s", dev->id); 37784b08cd56SDaniel Henrique Barboza 377944d886abSDaniel Henrique Barboza qapi_event_send_mem_unplug_error(dev->id ? : "", qapi_error); 37804b08cd56SDaniel Henrique Barboza 3781047f2ca1SMarkus Armbruster qapi_event_send_device_unplug_guest_error(dev->id, 37824b08cd56SDaniel Henrique Barboza dev->canonical_path); 3783fe1831efSDaniel Henrique Barboza } 3784fe1831efSDaniel Henrique Barboza 378531834723SDaniel Henrique Barboza /* Callback to be called during DRC release. */ 378631834723SDaniel Henrique Barboza void spapr_lmb_release(DeviceState *dev) 3787cf632463SBharata B Rao { 37883ec71474SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3789ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl); 3790ce2918cbSDavid Gibson SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); 3791cf632463SBharata B Rao 379216ee9980SDaniel Henrique Barboza /* This information will get lost if a migration occurs 379316ee9980SDaniel Henrique Barboza * during the unplug process. In this case recover it. */ 379416ee9980SDaniel Henrique Barboza if (ds == NULL) { 379516ee9980SDaniel Henrique Barboza ds = spapr_recover_pending_dimm_state(spapr, PC_DIMM(dev)); 37968d5981c4SBharata B Rao g_assert(ds); 3797454b580aSDavid Gibson /* The DRC being examined by the caller at least must be counted */ 3798454b580aSDavid Gibson g_assert(ds->nr_lmbs); 379916ee9980SDaniel Henrique Barboza } 3800454b580aSDavid Gibson 3801454b580aSDavid Gibson if (--ds->nr_lmbs) { 3802cf632463SBharata B Rao return; 3803cf632463SBharata B Rao } 3804cf632463SBharata B Rao 3805cf632463SBharata B Rao /* 3806cf632463SBharata B Rao * Now that all the LMBs have been removed by the guest, call the 38073ec71474SDavid Hildenbrand * unplug handler chain. This can never fail. 3808cf632463SBharata B Rao */ 38093ec71474SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 381007578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 38113ec71474SDavid Hildenbrand } 38123ec71474SDavid Hildenbrand 38133ec71474SDavid Hildenbrand static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 38143ec71474SDavid Hildenbrand { 3815ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3816ce2918cbSDavid Gibson SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); 38173ec71474SDavid Hildenbrand 3818df2d7ca7SGreg Kurz /* We really shouldn't get this far without anything to unplug */ 3819df2d7ca7SGreg Kurz g_assert(ds); 3820df2d7ca7SGreg Kurz 3821fd3416f5SDavid Hildenbrand pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev)); 3822981c3dcdSMarkus Armbruster qdev_unrealize(dev); 38232a129767SDaniel Henrique Barboza spapr_pending_dimm_unplugs_remove(spapr, ds); 3824cf632463SBharata B Rao } 3825cf632463SBharata B Rao 3826cf632463SBharata B Rao static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, 3827cf632463SBharata B Rao DeviceState *dev, Error **errp) 3828cf632463SBharata B Rao { 3829ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3830cf632463SBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 383104790978SThomas Huth uint32_t nr_lmbs; 383204790978SThomas Huth uint64_t size, addr_start, addr; 38330cffce56SDavid Gibson int i; 3834ce2918cbSDavid Gibson SpaprDrc *drc; 383504790978SThomas Huth 3836ee3a71e3SShivaprasad G Bhat if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { 3837dcfe4805SMarkus Armbruster error_setg(errp, "nvdimm device hot unplug is not supported yet."); 3838dcfe4805SMarkus Armbruster return; 3839ee3a71e3SShivaprasad G Bhat } 3840ee3a71e3SShivaprasad G Bhat 3841946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &error_abort); 384204790978SThomas Huth nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 384304790978SThomas Huth 38449ed442b8SMarc-André Lureau addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, 3845271ced1dSGreg Kurz &error_abort); 3846cf632463SBharata B Rao 38472a129767SDaniel Henrique Barboza /* 38482a129767SDaniel Henrique Barboza * An existing pending dimm state for this DIMM means that there is an 38492a129767SDaniel Henrique Barboza * unplug operation in progress, waiting for the spapr_lmb_release 38502a129767SDaniel Henrique Barboza * callback to complete the job (BQL can't cover that far). In this case, 38512a129767SDaniel Henrique Barboza * bail out to avoid detaching DRCs that were already released. 38522a129767SDaniel Henrique Barboza */ 38532a129767SDaniel Henrique Barboza if (spapr_pending_dimm_unplugs_find(spapr, dimm)) { 3854dcfe4805SMarkus Armbruster error_setg(errp, "Memory unplug already in progress for device %s", 38552a129767SDaniel Henrique Barboza dev->id); 3856dcfe4805SMarkus Armbruster return; 38572a129767SDaniel Henrique Barboza } 38582a129767SDaniel Henrique Barboza 38598d5981c4SBharata B Rao spapr_pending_dimm_unplugs_add(spapr, nr_lmbs, dimm); 38600cffce56SDavid Gibson 38610cffce56SDavid Gibson addr = addr_start; 38620cffce56SDavid Gibson for (i = 0; i < nr_lmbs; i++) { 3863fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 38640cffce56SDavid Gibson addr / SPAPR_MEMORY_BLOCK_SIZE); 38650cffce56SDavid Gibson g_assert(drc); 38660cffce56SDavid Gibson 3867a03509cdSDaniel Henrique Barboza spapr_drc_unplug_request(drc); 38680cffce56SDavid Gibson addr += SPAPR_MEMORY_BLOCK_SIZE; 38690cffce56SDavid Gibson } 38700cffce56SDavid Gibson 3871fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 38720cffce56SDavid Gibson addr_start / SPAPR_MEMORY_BLOCK_SIZE); 38730cffce56SDavid Gibson spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 38740b55aa91SDavid Gibson nr_lmbs, spapr_drc_index(drc)); 3875cf632463SBharata B Rao } 3876cf632463SBharata B Rao 3877765d1bddSDavid Gibson /* Callback to be called during DRC release. */ 3878765d1bddSDavid Gibson void spapr_core_release(DeviceState *dev) 3879ff9006ddSIgor Mammedov { 3880a4261be1SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 3881a4261be1SDavid Hildenbrand 3882a4261be1SDavid Hildenbrand /* Call the unplug handler chain. This can never fail. */ 3883a4261be1SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 388407578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 3885a4261be1SDavid Hildenbrand } 3886a4261be1SDavid Hildenbrand 3887a4261be1SDavid Hildenbrand static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 3888a4261be1SDavid Hildenbrand { 3889a4261be1SDavid Hildenbrand MachineState *ms = MACHINE(hotplug_dev); 3890ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms); 3891ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3892535455fdSIgor Mammedov CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL); 3893ff9006ddSIgor Mammedov 389446f7afa3SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 3895ce2918cbSDavid Gibson SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); 389646f7afa3SGreg Kurz int i; 389746f7afa3SGreg Kurz 389846f7afa3SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 389994ad93bdSGreg Kurz CPUState *cs = CPU(sc->threads[i]); 390046f7afa3SGreg Kurz 390146f7afa3SGreg Kurz pre_2_10_vmstate_register_dummy_icp(cs->cpu_index); 390246f7afa3SGreg Kurz } 390346f7afa3SGreg Kurz } 390446f7afa3SGreg Kurz 390507572c06SGreg Kurz assert(core_slot); 3906535455fdSIgor Mammedov core_slot->cpu = NULL; 3907981c3dcdSMarkus Armbruster qdev_unrealize(dev); 3908ff9006ddSIgor Mammedov } 3909ff9006ddSIgor Mammedov 3910115debf2SIgor Mammedov static 3911115debf2SIgor Mammedov void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, 3912ff9006ddSIgor Mammedov Error **errp) 3913ff9006ddSIgor Mammedov { 3914ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3915535455fdSIgor Mammedov int index; 3916ce2918cbSDavid Gibson SpaprDrc *drc; 3917535455fdSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3918ff9006ddSIgor Mammedov 3919535455fdSIgor Mammedov if (!spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index)) { 3920535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 3921535455fdSIgor Mammedov cc->core_id); 3922535455fdSIgor Mammedov return; 3923535455fdSIgor Mammedov } 3924ff9006ddSIgor Mammedov if (index == 0) { 3925ff9006ddSIgor Mammedov error_setg(errp, "Boot CPU core may not be unplugged"); 3926ff9006ddSIgor Mammedov return; 3927ff9006ddSIgor Mammedov } 3928ff9006ddSIgor Mammedov 39295d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 39305d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 3931ff9006ddSIgor Mammedov g_assert(drc); 3932ff9006ddSIgor Mammedov 393347c8c915SGreg Kurz if (!spapr_drc_unplug_requested(drc)) { 3934a03509cdSDaniel Henrique Barboza spapr_drc_unplug_request(drc); 3935ff9006ddSIgor Mammedov } 39362b18fc79SDaniel Henrique Barboza 39372b18fc79SDaniel Henrique Barboza /* 39382b18fc79SDaniel Henrique Barboza * spapr_hotplug_req_remove_by_index is left unguarded, out of the 39392b18fc79SDaniel Henrique Barboza * "!spapr_drc_unplug_requested" check, to allow for multiple IRQ 39402b18fc79SDaniel Henrique Barboza * pulses removing the same CPU. Otherwise, in an failed hotunplug 39412b18fc79SDaniel Henrique Barboza * attempt (e.g. the kernel will refuse to remove the last online 39422b18fc79SDaniel Henrique Barboza * CPU), we will never attempt it again because unplug_requested 39432b18fc79SDaniel Henrique Barboza * will still be 'true' in that case. 39442b18fc79SDaniel Henrique Barboza */ 39452b18fc79SDaniel Henrique Barboza spapr_hotplug_req_remove_by_index(drc); 394647c8c915SGreg Kurz } 3947ff9006ddSIgor Mammedov 3948ce2918cbSDavid Gibson int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 3949345b12b9SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 3950345b12b9SGreg Kurz { 3951ce2918cbSDavid Gibson SpaprCpuCore *core = SPAPR_CPU_CORE(drc->dev); 3952345b12b9SGreg Kurz CPUState *cs = CPU(core->threads[0]); 3953345b12b9SGreg Kurz PowerPCCPU *cpu = POWERPC_CPU(cs); 3954345b12b9SGreg Kurz DeviceClass *dc = DEVICE_GET_CLASS(cs); 3955345b12b9SGreg Kurz int id = spapr_get_vcpu_id(cpu); 39567265bc3eSDaniel Henrique Barboza g_autofree char *nodename = NULL; 3957345b12b9SGreg Kurz int offset; 3958345b12b9SGreg Kurz 3959345b12b9SGreg Kurz nodename = g_strdup_printf("%s@%x", dc->fw_name, id); 3960345b12b9SGreg Kurz offset = fdt_add_subnode(fdt, 0, nodename); 3961345b12b9SGreg Kurz 396291335a5eSDavid Gibson spapr_dt_cpu(cs, fdt, offset, spapr); 3963345b12b9SGreg Kurz 3964a85bb34eSDaniel Henrique Barboza /* 3965a85bb34eSDaniel Henrique Barboza * spapr_dt_cpu() does not fill the 'name' property in the 3966a85bb34eSDaniel Henrique Barboza * CPU node. The function is called during boot process, before 3967a85bb34eSDaniel Henrique Barboza * and after CAS, and overwriting the 'name' property written 3968a85bb34eSDaniel Henrique Barboza * by SLOF is not allowed. 3969a85bb34eSDaniel Henrique Barboza * 3970a85bb34eSDaniel Henrique Barboza * Write it manually after spapr_dt_cpu(). This makes the hotplug 3971a85bb34eSDaniel Henrique Barboza * CPUs more compatible with the coldplugged ones, which have 3972a85bb34eSDaniel Henrique Barboza * the 'name' property. Linux Kernel also relies on this 3973a85bb34eSDaniel Henrique Barboza * property to identify CPU nodes. 3974a85bb34eSDaniel Henrique Barboza */ 3975a85bb34eSDaniel Henrique Barboza _FDT((fdt_setprop_string(fdt, offset, "name", nodename))); 3976a85bb34eSDaniel Henrique Barboza 3977345b12b9SGreg Kurz *fdt_start_offset = offset; 3978345b12b9SGreg Kurz return 0; 3979345b12b9SGreg Kurz } 3980345b12b9SGreg Kurz 3981f9b43958SGreg Kurz static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev) 3982ff9006ddSIgor Mammedov { 3983ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3984ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(spapr); 3985ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 3986ce2918cbSDavid Gibson SpaprCpuCore *core = SPAPR_CPU_CORE(OBJECT(dev)); 3987ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3988345b12b9SGreg Kurz CPUState *cs; 3989ce2918cbSDavid Gibson SpaprDrc *drc; 3990535455fdSIgor Mammedov CPUArchId *core_slot; 3991535455fdSIgor Mammedov int index; 399294fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 3993b1e81567SGreg Kurz int i; 3994ff9006ddSIgor Mammedov 3995535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 3996f9b43958SGreg Kurz g_assert(core_slot); /* Already checked in spapr_core_pre_plug() */ 3997f9b43958SGreg Kurz 39985d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 39995d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 4000ff9006ddSIgor Mammedov 4001c5514d0eSIgor Mammedov g_assert(drc || !mc->has_hotpluggable_cpus); 4002ff9006ddSIgor Mammedov 4003e49c63d5SGreg Kurz if (drc) { 4004f9b43958SGreg Kurz /* 4005f9b43958SGreg Kurz * spapr_core_pre_plug() already buys us this is a brand new 4006f9b43958SGreg Kurz * core being plugged into a free slot. Nothing should already 4007f9b43958SGreg Kurz * be attached to the corresponding DRC. 4008f9b43958SGreg Kurz */ 4009bc370a65SGreg Kurz spapr_drc_attach(drc, dev); 4010ff9006ddSIgor Mammedov 401194fd9cbaSLaurent Vivier if (hotplugged) { 4012ff9006ddSIgor Mammedov /* 401394fd9cbaSLaurent Vivier * Send hotplug notification interrupt to the guest only 401494fd9cbaSLaurent Vivier * in case of hotplugged CPUs. 4015ff9006ddSIgor Mammedov */ 4016ff9006ddSIgor Mammedov spapr_hotplug_req_add_by_index(drc); 401794fd9cbaSLaurent Vivier } else { 401894fd9cbaSLaurent Vivier spapr_drc_reset(drc); 4019ff9006ddSIgor Mammedov } 402094fd9cbaSLaurent Vivier } 402194fd9cbaSLaurent Vivier 4022535455fdSIgor Mammedov core_slot->cpu = OBJECT(dev); 402346f7afa3SGreg Kurz 4024b1e81567SGreg Kurz /* 4025b1e81567SGreg Kurz * Set compatibility mode to match the boot CPU, which was either set 402637641213SGreg Kurz * by the machine reset code or by CAS. This really shouldn't fail at 402737641213SGreg Kurz * this point. 4028b1e81567SGreg Kurz */ 4029b1e81567SGreg Kurz if (hotplugged) { 4030b1e81567SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 403137641213SGreg Kurz ppc_set_compat(core->threads[i], POWERPC_CPU(first_cpu)->compat_pvr, 403237641213SGreg Kurz &error_abort); 4033b1e81567SGreg Kurz } 4034b1e81567SGreg Kurz } 40351b4ab514SGreg Kurz 40361b4ab514SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 40371b4ab514SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 40381b4ab514SGreg Kurz cs = CPU(core->threads[i]); 40391b4ab514SGreg Kurz pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index); 40401b4ab514SGreg Kurz } 40411b4ab514SGreg Kurz } 4042ff9006ddSIgor Mammedov } 4043ff9006ddSIgor Mammedov 4044ff9006ddSIgor Mammedov static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 4045ff9006ddSIgor Mammedov Error **errp) 4046ff9006ddSIgor Mammedov { 4047ff9006ddSIgor Mammedov MachineState *machine = MACHINE(OBJECT(hotplug_dev)); 4048ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); 4049ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 40502e9c10ebSIgor Mammedov const char *base_core_type = spapr_get_cpu_core_type(machine->cpu_type); 4051ff9006ddSIgor Mammedov const char *type = object_get_typename(OBJECT(dev)); 4052535455fdSIgor Mammedov CPUArchId *core_slot; 4053535455fdSIgor Mammedov int index; 4054fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 4055ff9006ddSIgor Mammedov 4056c5514d0eSIgor Mammedov if (dev->hotplugged && !mc->has_hotpluggable_cpus) { 4057dcfe4805SMarkus Armbruster error_setg(errp, "CPU hotplug not supported for this machine"); 4058dcfe4805SMarkus Armbruster return; 4059ff9006ddSIgor Mammedov } 4060ff9006ddSIgor Mammedov 4061ff9006ddSIgor Mammedov if (strcmp(base_core_type, type)) { 4062dcfe4805SMarkus Armbruster error_setg(errp, "CPU core type should be %s", base_core_type); 4063dcfe4805SMarkus Armbruster return; 4064ff9006ddSIgor Mammedov } 4065ff9006ddSIgor Mammedov 4066ff9006ddSIgor Mammedov if (cc->core_id % smp_threads) { 4067dcfe4805SMarkus Armbruster error_setg(errp, "invalid core id %d", cc->core_id); 4068dcfe4805SMarkus Armbruster return; 4069ff9006ddSIgor Mammedov } 4070ff9006ddSIgor Mammedov 4071459264efSDavid Gibson /* 4072459264efSDavid Gibson * In general we should have homogeneous threads-per-core, but old 4073459264efSDavid Gibson * (pre hotplug support) machine types allow the last core to have 4074459264efSDavid Gibson * reduced threads as a compatibility hack for when we allowed 4075459264efSDavid Gibson * total vcpus not a multiple of threads-per-core. 4076459264efSDavid Gibson */ 4077459264efSDavid Gibson if (mc->has_hotpluggable_cpus && (cc->nr_threads != smp_threads)) { 4078dcfe4805SMarkus Armbruster error_setg(errp, "invalid nr-threads %d, must be %d", cc->nr_threads, 4079dcfe4805SMarkus Armbruster smp_threads); 4080dcfe4805SMarkus Armbruster return; 40818149e299SDavid Gibson } 40828149e299SDavid Gibson 4083535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 4084535455fdSIgor Mammedov if (!core_slot) { 4085dcfe4805SMarkus Armbruster error_setg(errp, "core id %d out of range", cc->core_id); 4086dcfe4805SMarkus Armbruster return; 4087ff9006ddSIgor Mammedov } 4088ff9006ddSIgor Mammedov 4089535455fdSIgor Mammedov if (core_slot->cpu) { 4090dcfe4805SMarkus Armbruster error_setg(errp, "core %d already populated", cc->core_id); 4091dcfe4805SMarkus Armbruster return; 4092ff9006ddSIgor Mammedov } 4093ff9006ddSIgor Mammedov 4094dcfe4805SMarkus Armbruster numa_cpu_pre_plug(core_slot, dev, errp); 4095ff9006ddSIgor Mammedov } 4096ff9006ddSIgor Mammedov 4097ce2918cbSDavid Gibson int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 4098bb2bdd81SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp) 4099bb2bdd81SGreg Kurz { 4100ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(drc->dev); 4101bb2bdd81SGreg Kurz int intc_phandle; 4102bb2bdd81SGreg Kurz 4103bb2bdd81SGreg Kurz intc_phandle = spapr_irq_get_phandle(spapr, spapr->fdt_blob, errp); 4104bb2bdd81SGreg Kurz if (intc_phandle <= 0) { 4105bb2bdd81SGreg Kurz return -1; 4106bb2bdd81SGreg Kurz } 4107bb2bdd81SGreg Kurz 41088cbe71ecSDavid Gibson if (spapr_dt_phb(spapr, sphb, intc_phandle, fdt, fdt_start_offset)) { 4109bb2bdd81SGreg Kurz error_setg(errp, "unable to create FDT node for PHB %d", sphb->index); 4110bb2bdd81SGreg Kurz return -1; 4111bb2bdd81SGreg Kurz } 4112bb2bdd81SGreg Kurz 4113bb2bdd81SGreg Kurz /* generally SLOF creates these, for hotplug it's up to QEMU */ 4114bb2bdd81SGreg Kurz _FDT(fdt_setprop_string(fdt, *fdt_start_offset, "name", "pci")); 4115bb2bdd81SGreg Kurz 4116bb2bdd81SGreg Kurz return 0; 4117bb2bdd81SGreg Kurz } 4118bb2bdd81SGreg Kurz 4119f5598c92SGreg Kurz static bool spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 4120bb2bdd81SGreg Kurz Error **errp) 4121bb2bdd81SGreg Kurz { 4122ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 4123ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 4124ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 4125bb2bdd81SGreg Kurz const unsigned windows_supported = spapr_phb_windows_supported(sphb); 41269a070699SGreg Kurz SpaprDrc *drc; 4127bb2bdd81SGreg Kurz 4128bb2bdd81SGreg Kurz if (dev->hotplugged && !smc->dr_phb_enabled) { 4129bb2bdd81SGreg Kurz error_setg(errp, "PHB hotplug not supported for this machine"); 4130f5598c92SGreg Kurz return false; 4131bb2bdd81SGreg Kurz } 4132bb2bdd81SGreg Kurz 4133bb2bdd81SGreg Kurz if (sphb->index == (uint32_t)-1) { 4134bb2bdd81SGreg Kurz error_setg(errp, "\"index\" for PAPR PHB is mandatory"); 4135f5598c92SGreg Kurz return false; 4136bb2bdd81SGreg Kurz } 4137bb2bdd81SGreg Kurz 41389a070699SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); 41399a070699SGreg Kurz if (drc && drc->dev) { 41409a070699SGreg Kurz error_setg(errp, "PHB %d already attached", sphb->index); 41419a070699SGreg Kurz return false; 41429a070699SGreg Kurz } 41439a070699SGreg Kurz 4144bb2bdd81SGreg Kurz /* 4145bb2bdd81SGreg Kurz * This will check that sphb->index doesn't exceed the maximum number of 4146bb2bdd81SGreg Kurz * PHBs for the current machine type. 4147bb2bdd81SGreg Kurz */ 4148f5598c92SGreg Kurz return 4149bb2bdd81SGreg Kurz smc->phb_placement(spapr, sphb->index, 4150bb2bdd81SGreg Kurz &sphb->buid, &sphb->io_win_addr, 4151bb2bdd81SGreg Kurz &sphb->mem_win_addr, &sphb->mem64_win_addr, 4152ec132efaSAlexey Kardashevskiy windows_supported, sphb->dma_liobn, 4153ec132efaSAlexey Kardashevskiy errp); 4154bb2bdd81SGreg Kurz } 4155bb2bdd81SGreg Kurz 41569a070699SGreg Kurz static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev) 4157bb2bdd81SGreg Kurz { 4158ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 4159ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 4160ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 4161ce2918cbSDavid Gibson SpaprDrc *drc; 4162bb2bdd81SGreg Kurz bool hotplugged = spapr_drc_hotplugged(dev); 4163bb2bdd81SGreg Kurz 4164bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) { 4165bb2bdd81SGreg Kurz return; 4166bb2bdd81SGreg Kurz } 4167bb2bdd81SGreg Kurz 4168bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); 4169bb2bdd81SGreg Kurz /* hotplug hooks should check it's enabled before getting this far */ 4170bb2bdd81SGreg Kurz assert(drc); 4171bb2bdd81SGreg Kurz 41729a070699SGreg Kurz /* spapr_phb_pre_plug() already checked the DRC is attachable */ 4173bc370a65SGreg Kurz spapr_drc_attach(drc, dev); 4174bb2bdd81SGreg Kurz 4175bb2bdd81SGreg Kurz if (hotplugged) { 4176bb2bdd81SGreg Kurz spapr_hotplug_req_add_by_index(drc); 4177bb2bdd81SGreg Kurz } else { 4178bb2bdd81SGreg Kurz spapr_drc_reset(drc); 4179bb2bdd81SGreg Kurz } 4180bb2bdd81SGreg Kurz } 4181bb2bdd81SGreg Kurz 4182bb2bdd81SGreg Kurz void spapr_phb_release(DeviceState *dev) 4183bb2bdd81SGreg Kurz { 4184bb2bdd81SGreg Kurz HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); 4185bb2bdd81SGreg Kurz 4186bb2bdd81SGreg Kurz hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 418707578b0aSDavid Hildenbrand object_unparent(OBJECT(dev)); 4188bb2bdd81SGreg Kurz } 4189bb2bdd81SGreg Kurz 4190bb2bdd81SGreg Kurz static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 4191bb2bdd81SGreg Kurz { 4192981c3dcdSMarkus Armbruster qdev_unrealize(dev); 4193bb2bdd81SGreg Kurz } 4194bb2bdd81SGreg Kurz 4195bb2bdd81SGreg Kurz static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev, 4196bb2bdd81SGreg Kurz DeviceState *dev, Error **errp) 4197bb2bdd81SGreg Kurz { 4198ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); 4199ce2918cbSDavid Gibson SpaprDrc *drc; 4200bb2bdd81SGreg Kurz 4201bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); 4202bb2bdd81SGreg Kurz assert(drc); 4203bb2bdd81SGreg Kurz 4204bb2bdd81SGreg Kurz if (!spapr_drc_unplug_requested(drc)) { 4205a03509cdSDaniel Henrique Barboza spapr_drc_unplug_request(drc); 4206bb2bdd81SGreg Kurz spapr_hotplug_req_remove_by_index(drc); 42077420033eSDaniel Henrique Barboza } else { 42087420033eSDaniel Henrique Barboza error_setg(errp, 42097420033eSDaniel Henrique Barboza "PCI Host Bridge unplug already in progress for device %s", 42107420033eSDaniel Henrique Barboza dev->id); 4211bb2bdd81SGreg Kurz } 4212bb2bdd81SGreg Kurz } 4213bb2bdd81SGreg Kurz 4214ac96807bSGreg Kurz static 4215ac96807bSGreg Kurz bool spapr_tpm_proxy_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 42160fb6bd07SMichael Roth Error **errp) 42170fb6bd07SMichael Roth { 42180fb6bd07SMichael Roth SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 4219ac96807bSGreg Kurz 4220ac96807bSGreg Kurz if (spapr->tpm_proxy != NULL) { 4221ac96807bSGreg Kurz error_setg(errp, "Only one TPM proxy can be specified for this machine"); 4222ac96807bSGreg Kurz return false; 4223ac96807bSGreg Kurz } 4224ac96807bSGreg Kurz 4225ac96807bSGreg Kurz return true; 4226ac96807bSGreg Kurz } 4227ac96807bSGreg Kurz 4228ac96807bSGreg Kurz static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev) 4229ac96807bSGreg Kurz { 4230ac96807bSGreg Kurz SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 42310fb6bd07SMichael Roth SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(dev); 42320fb6bd07SMichael Roth 4233ac96807bSGreg Kurz /* Already checked in spapr_tpm_proxy_pre_plug() */ 4234ac96807bSGreg Kurz g_assert(spapr->tpm_proxy == NULL); 42350fb6bd07SMichael Roth 42360fb6bd07SMichael Roth spapr->tpm_proxy = tpm_proxy; 42370fb6bd07SMichael Roth } 42380fb6bd07SMichael Roth 42390fb6bd07SMichael Roth static void spapr_tpm_proxy_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) 42400fb6bd07SMichael Roth { 42410fb6bd07SMichael Roth SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 42420fb6bd07SMichael Roth 4243981c3dcdSMarkus Armbruster qdev_unrealize(dev); 42440fb6bd07SMichael Roth object_unparent(OBJECT(dev)); 42450fb6bd07SMichael Roth spapr->tpm_proxy = NULL; 42460fb6bd07SMichael Roth } 42470fb6bd07SMichael Roth 4248c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, 4249c20d332aSBharata B Rao DeviceState *dev, Error **errp) 4250c20d332aSBharata B Rao { 4251c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 4252ea042c53SGreg Kurz spapr_memory_plug(hotplug_dev, dev); 4253af81cf32SBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4254f9b43958SGreg Kurz spapr_core_plug(hotplug_dev, dev); 4255bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 42569a070699SGreg Kurz spapr_phb_plug(hotplug_dev, dev); 42570fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 4258ac96807bSGreg Kurz spapr_tpm_proxy_plug(hotplug_dev, dev); 4259c20d332aSBharata B Rao } 4260c20d332aSBharata B Rao } 4261c20d332aSBharata B Rao 426288432f44SDavid Hildenbrand static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, 426388432f44SDavid Hildenbrand DeviceState *dev, Error **errp) 426488432f44SDavid Hildenbrand { 42653ec71474SDavid Hildenbrand if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 42663ec71474SDavid Hildenbrand spapr_memory_unplug(hotplug_dev, dev); 4267a4261be1SDavid Hildenbrand } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4268a4261be1SDavid Hildenbrand spapr_core_unplug(hotplug_dev, dev); 4269bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4270bb2bdd81SGreg Kurz spapr_phb_unplug(hotplug_dev, dev); 42710fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 42720fb6bd07SMichael Roth spapr_tpm_proxy_unplug(hotplug_dev, dev); 42733ec71474SDavid Hildenbrand } 427488432f44SDavid Hildenbrand } 427588432f44SDavid Hildenbrand 427673598c75SGreg Kurz bool spapr_memory_hot_unplug_supported(SpaprMachineState *spapr) 427773598c75SGreg Kurz { 427873598c75SGreg Kurz return spapr_ovec_test(spapr->ov5_cas, OV5_HP_EVT) || 427973598c75SGreg Kurz /* 428073598c75SGreg Kurz * CAS will process all pending unplug requests. 428173598c75SGreg Kurz * 428273598c75SGreg Kurz * HACK: a guest could theoretically have cleared all bits in OV5, 428373598c75SGreg Kurz * but none of the guests we care for do. 428473598c75SGreg Kurz */ 428573598c75SGreg Kurz spapr_ovec_empty(spapr->ov5_cas); 428673598c75SGreg Kurz } 428773598c75SGreg Kurz 4288cf632463SBharata B Rao static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev, 4289cf632463SBharata B Rao DeviceState *dev, Error **errp) 4290cf632463SBharata B Rao { 4291ce2918cbSDavid Gibson SpaprMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev)); 4292c86c1affSDaniel Henrique Barboza MachineClass *mc = MACHINE_GET_CLASS(sms); 4293ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4294cf632463SBharata B Rao 4295cf632463SBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 429673598c75SGreg Kurz if (spapr_memory_hot_unplug_supported(sms)) { 4297cf632463SBharata B Rao spapr_memory_unplug_request(hotplug_dev, dev, errp); 4298cf632463SBharata B Rao } else { 4299cf632463SBharata B Rao error_setg(errp, "Memory hot unplug not supported for this guest"); 4300cf632463SBharata B Rao } 43016f4b5c3eSBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 4302c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 43036f4b5c3eSBharata B Rao error_setg(errp, "CPU hot unplug not supported on this machine"); 43046f4b5c3eSBharata B Rao return; 43056f4b5c3eSBharata B Rao } 4306115debf2SIgor Mammedov spapr_core_unplug_request(hotplug_dev, dev, errp); 4307bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4308bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) { 4309bb2bdd81SGreg Kurz error_setg(errp, "PHB hot unplug not supported on this machine"); 4310bb2bdd81SGreg Kurz return; 4311bb2bdd81SGreg Kurz } 4312bb2bdd81SGreg Kurz spapr_phb_unplug_request(hotplug_dev, dev, errp); 43130fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 43140fb6bd07SMichael Roth spapr_tpm_proxy_unplug(hotplug_dev, dev); 4315c20d332aSBharata B Rao } 4316c20d332aSBharata B Rao } 4317c20d332aSBharata B Rao 431894a94e4cSBharata B Rao static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, 431994a94e4cSBharata B Rao DeviceState *dev, Error **errp) 432094a94e4cSBharata B Rao { 4321c871bc70SLaurent Vivier if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 4322c871bc70SLaurent Vivier spapr_memory_pre_plug(hotplug_dev, dev, errp); 4323c871bc70SLaurent Vivier } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 432494a94e4cSBharata B Rao spapr_core_pre_plug(hotplug_dev, dev, errp); 4325bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 4326bb2bdd81SGreg Kurz spapr_phb_pre_plug(hotplug_dev, dev, errp); 4327ac96807bSGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 4328ac96807bSGreg Kurz spapr_tpm_proxy_pre_plug(hotplug_dev, dev, errp); 432994a94e4cSBharata B Rao } 433094a94e4cSBharata B Rao } 433194a94e4cSBharata B Rao 43327ebaf795SBharata B Rao static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine, 4333c20d332aSBharata B Rao DeviceState *dev) 4334c20d332aSBharata B Rao { 433594a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || 4336bb2bdd81SGreg Kurz object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE) || 43370fb6bd07SMichael Roth object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE) || 43380fb6bd07SMichael Roth object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { 4339c20d332aSBharata B Rao return HOTPLUG_HANDLER(machine); 4340c20d332aSBharata B Rao } 4341cb600087SDavid Gibson if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { 4342cb600087SDavid Gibson PCIDevice *pcidev = PCI_DEVICE(dev); 4343cb600087SDavid Gibson PCIBus *root = pci_device_root_bus(pcidev); 4344cb600087SDavid Gibson SpaprPhbState *phb = 4345cb600087SDavid Gibson (SpaprPhbState *)object_dynamic_cast(OBJECT(BUS(root)->parent), 4346cb600087SDavid Gibson TYPE_SPAPR_PCI_HOST_BRIDGE); 4347cb600087SDavid Gibson 4348cb600087SDavid Gibson if (phb) { 4349cb600087SDavid Gibson return HOTPLUG_HANDLER(phb); 4350cb600087SDavid Gibson } 4351cb600087SDavid Gibson } 4352c20d332aSBharata B Rao return NULL; 4353c20d332aSBharata B Rao } 4354c20d332aSBharata B Rao 4355ea089eebSIgor Mammedov static CpuInstanceProperties 4356ea089eebSIgor Mammedov spapr_cpu_index_to_props(MachineState *machine, unsigned cpu_index) 435720bb648dSDavid Gibson { 4358ea089eebSIgor Mammedov CPUArchId *core_slot; 4359ea089eebSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 4360ea089eebSIgor Mammedov 4361e6a19a64SMichael Tokarev /* make sure possible_cpu are initialized */ 4362ea089eebSIgor Mammedov mc->possible_cpu_arch_ids(machine); 4363ea089eebSIgor Mammedov /* get CPU core slot containing thread that matches cpu_index */ 4364ea089eebSIgor Mammedov core_slot = spapr_find_cpu_slot(machine, cpu_index, NULL); 4365ea089eebSIgor Mammedov assert(core_slot); 4366ea089eebSIgor Mammedov return core_slot->props; 436720bb648dSDavid Gibson } 436820bb648dSDavid Gibson 436979e07936SIgor Mammedov static int64_t spapr_get_default_cpu_node_id(const MachineState *ms, int idx) 437079e07936SIgor Mammedov { 4371aa570207STao Xu return idx / ms->smp.cores % ms->numa_state->num_nodes; 437279e07936SIgor Mammedov } 437379e07936SIgor Mammedov 4374535455fdSIgor Mammedov static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine) 4375535455fdSIgor Mammedov { 4376535455fdSIgor Mammedov int i; 4377fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads; 4378fe6b6346SLike Xu unsigned int smp_cpus = machine->smp.cpus; 4379d342eb76SIgor Mammedov const char *core_type; 4380fe6b6346SLike Xu int spapr_max_cores = machine->smp.max_cpus / smp_threads; 4381535455fdSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 4382535455fdSIgor Mammedov 4383c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 4384535455fdSIgor Mammedov spapr_max_cores = QEMU_ALIGN_UP(smp_cpus, smp_threads) / smp_threads; 4385535455fdSIgor Mammedov } 4386535455fdSIgor Mammedov if (machine->possible_cpus) { 4387535455fdSIgor Mammedov assert(machine->possible_cpus->len == spapr_max_cores); 4388535455fdSIgor Mammedov return machine->possible_cpus; 4389535455fdSIgor Mammedov } 4390535455fdSIgor Mammedov 4391d342eb76SIgor Mammedov core_type = spapr_get_cpu_core_type(machine->cpu_type); 4392d342eb76SIgor Mammedov if (!core_type) { 4393d342eb76SIgor Mammedov error_report("Unable to find sPAPR CPU Core definition"); 4394d342eb76SIgor Mammedov exit(1); 4395d342eb76SIgor Mammedov } 4396d342eb76SIgor Mammedov 4397535455fdSIgor Mammedov machine->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + 4398535455fdSIgor Mammedov sizeof(CPUArchId) * spapr_max_cores); 4399535455fdSIgor Mammedov machine->possible_cpus->len = spapr_max_cores; 4400535455fdSIgor Mammedov for (i = 0; i < machine->possible_cpus->len; i++) { 4401535455fdSIgor Mammedov int core_id = i * smp_threads; 4402535455fdSIgor Mammedov 4403d342eb76SIgor Mammedov machine->possible_cpus->cpus[i].type = core_type; 4404f2d672c2SIgor Mammedov machine->possible_cpus->cpus[i].vcpus_count = smp_threads; 4405535455fdSIgor Mammedov machine->possible_cpus->cpus[i].arch_id = core_id; 4406535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.has_core_id = true; 4407535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.core_id = core_id; 4408535455fdSIgor Mammedov } 4409535455fdSIgor Mammedov return machine->possible_cpus; 4410535455fdSIgor Mammedov } 4411535455fdSIgor Mammedov 4412f5598c92SGreg Kurz static bool spapr_phb_placement(SpaprMachineState *spapr, uint32_t index, 4413daa23699SDavid Gibson uint64_t *buid, hwaddr *pio, 4414daa23699SDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 441544fa20c9SCédric Le Goater unsigned n_dma, uint32_t *liobns, Error **errp) 44166737d9adSDavid Gibson { 4417357d1e3bSDavid Gibson /* 4418357d1e3bSDavid Gibson * New-style PHB window placement. 4419357d1e3bSDavid Gibson * 4420357d1e3bSDavid Gibson * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window 4421357d1e3bSDavid Gibson * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO 4422357d1e3bSDavid Gibson * windows. 4423357d1e3bSDavid Gibson * 4424357d1e3bSDavid Gibson * Some guest kernels can't work with MMIO windows above 1<<46 4425357d1e3bSDavid Gibson * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB 4426357d1e3bSDavid Gibson * 4427357d1e3bSDavid Gibson * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each 4428357d1e3bSDavid Gibson * PHB stacked together. (32TiB+2GiB)..(32TiB+64GiB) contains the 4429357d1e3bSDavid Gibson * 2GiB 32-bit MMIO windows for each PHB. Then 33..64TiB has the 4430357d1e3bSDavid Gibson * 1TiB 64-bit MMIO windows for each PHB. 4431357d1e3bSDavid Gibson */ 44326737d9adSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 44336737d9adSDavid Gibson int i; 44346737d9adSDavid Gibson 4435357d1e3bSDavid Gibson /* Sanity check natural alignments */ 4436357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 4437357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 4438357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0); 4439357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0); 4440357d1e3bSDavid Gibson /* Sanity check bounds */ 444125e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_IO_WIN_SIZE) > 444225e6a118SMichael S. Tsirkin SPAPR_PCI_MEM32_WIN_SIZE); 444325e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_MEM32_WIN_SIZE) > 444425e6a118SMichael S. Tsirkin SPAPR_PCI_MEM64_WIN_SIZE); 44452efff1c0SDavid Gibson 444625e6a118SMichael S. Tsirkin if (index >= SPAPR_MAX_PHBS) { 444725e6a118SMichael S. Tsirkin error_setg(errp, "\"index\" for PAPR PHB is too large (max %llu)", 444825e6a118SMichael S. Tsirkin SPAPR_MAX_PHBS - 1); 4449f5598c92SGreg Kurz return false; 44506737d9adSDavid Gibson } 44516737d9adSDavid Gibson 44526737d9adSDavid Gibson *buid = base_buid + index; 44536737d9adSDavid Gibson for (i = 0; i < n_dma; ++i) { 44546737d9adSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 44556737d9adSDavid Gibson } 44566737d9adSDavid Gibson 4457357d1e3bSDavid Gibson *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE; 4458357d1e3bSDavid Gibson *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE; 4459357d1e3bSDavid Gibson *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE; 4460f5598c92SGreg Kurz return true; 44616737d9adSDavid Gibson } 44626737d9adSDavid Gibson 44637844e12bSCédric Le Goater static ICSState *spapr_ics_get(XICSFabric *dev, int irq) 44647844e12bSCédric Le Goater { 4465ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(dev); 44667844e12bSCédric Le Goater 44677844e12bSCédric Le Goater return ics_valid_irq(spapr->ics, irq) ? spapr->ics : NULL; 44687844e12bSCédric Le Goater } 44697844e12bSCédric Le Goater 44707844e12bSCédric Le Goater static void spapr_ics_resend(XICSFabric *dev) 44717844e12bSCédric Le Goater { 4472ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(dev); 44737844e12bSCédric Le Goater 44747844e12bSCédric Le Goater ics_resend(spapr->ics); 44757844e12bSCédric Le Goater } 44767844e12bSCédric Le Goater 447781210c20SSam Bobroff static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id) 4478b2fc59aaSCédric Le Goater { 44792e886fb3SSam Bobroff PowerPCCPU *cpu = spapr_find_cpu(vcpu_id); 4480b2fc59aaSCédric Le Goater 4481a28b9a5aSCédric Le Goater return cpu ? spapr_cpu_state(cpu)->icp : NULL; 4482b2fc59aaSCédric Le Goater } 4483b2fc59aaSCédric Le Goater 44846449da45SCédric Le Goater static void spapr_pic_print_info(InterruptStatsProvider *obj, 44856449da45SCédric Le Goater Monitor *mon) 44866449da45SCédric Le Goater { 4487ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj); 44886449da45SCédric Le Goater 4489328d8eb2SDavid Gibson spapr_irq_print_info(spapr, mon); 4490f041d6afSGreg Kurz monitor_printf(mon, "irqchip: %s\n", 4491f041d6afSGreg Kurz kvm_irqchip_in_kernel() ? "in-kernel" : "emulated"); 44926449da45SCédric Le Goater } 44936449da45SCédric Le Goater 4494baa45b17SCédric Le Goater /* 4495baa45b17SCédric Le Goater * This is a XIVE only operation 4496baa45b17SCédric Le Goater */ 4497932de7aeSCédric Le Goater static int spapr_match_nvt(XiveFabric *xfb, uint8_t format, 4498932de7aeSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 4499932de7aeSCédric Le Goater bool cam_ignore, uint8_t priority, 4500932de7aeSCédric Le Goater uint32_t logic_serv, XiveTCTXMatch *match) 4501932de7aeSCédric Le Goater { 4502932de7aeSCédric Le Goater SpaprMachineState *spapr = SPAPR_MACHINE(xfb); 4503baa45b17SCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(spapr->active_intc); 4504932de7aeSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 4505932de7aeSCédric Le Goater int count; 4506932de7aeSCédric Le Goater 4507932de7aeSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 4508932de7aeSCédric Le Goater priority, logic_serv, match); 4509932de7aeSCédric Le Goater if (count < 0) { 4510932de7aeSCédric Le Goater return count; 4511932de7aeSCédric Le Goater } 4512932de7aeSCédric Le Goater 4513932de7aeSCédric Le Goater /* 4514932de7aeSCédric Le Goater * When we implement the save and restore of the thread interrupt 4515932de7aeSCédric Le Goater * contexts in the enter/exit CPU handlers of the machine and the 4516932de7aeSCédric Le Goater * escalations in QEMU, we should be able to handle non dispatched 4517932de7aeSCédric Le Goater * vCPUs. 4518932de7aeSCédric Le Goater * 4519932de7aeSCédric Le Goater * Until this is done, the sPAPR machine should find at least one 4520932de7aeSCédric Le Goater * matching context always. 4521932de7aeSCédric Le Goater */ 4522932de7aeSCédric Le Goater if (count == 0) { 4523932de7aeSCédric Le Goater qemu_log_mask(LOG_GUEST_ERROR, "XIVE: NVT %x/%x is not dispatched\n", 4524932de7aeSCédric Le Goater nvt_blk, nvt_idx); 4525932de7aeSCédric Le Goater } 4526932de7aeSCédric Le Goater 4527932de7aeSCédric Le Goater return count; 4528932de7aeSCédric Le Goater } 4529932de7aeSCédric Le Goater 453014bb4486SGreg Kurz int spapr_get_vcpu_id(PowerPCCPU *cpu) 45312e886fb3SSam Bobroff { 4532b1a568c1SGreg Kurz return cpu->vcpu_id; 45332e886fb3SSam Bobroff } 45342e886fb3SSam Bobroff 4535cfdc5274SGreg Kurz bool spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp) 4536648edb64SGreg Kurz { 4537ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 4538fe6b6346SLike Xu MachineState *ms = MACHINE(spapr); 4539648edb64SGreg Kurz int vcpu_id; 4540648edb64SGreg Kurz 45415d0fb150SGreg Kurz vcpu_id = spapr_vcpu_id(spapr, cpu_index); 4542648edb64SGreg Kurz 4543648edb64SGreg Kurz if (kvm_enabled() && !kvm_vcpu_id_is_valid(vcpu_id)) { 4544648edb64SGreg Kurz error_setg(errp, "Can't create CPU with id %d in KVM", vcpu_id); 4545648edb64SGreg Kurz error_append_hint(errp, "Adjust the number of cpus to %d " 4546648edb64SGreg Kurz "or try to raise the number of threads per core\n", 4547fe6b6346SLike Xu vcpu_id * ms->smp.threads / spapr->vsmt); 4548cfdc5274SGreg Kurz return false; 4549648edb64SGreg Kurz } 4550648edb64SGreg Kurz 4551648edb64SGreg Kurz cpu->vcpu_id = vcpu_id; 4552cfdc5274SGreg Kurz return true; 4553648edb64SGreg Kurz } 4554648edb64SGreg Kurz 45552e886fb3SSam Bobroff PowerPCCPU *spapr_find_cpu(int vcpu_id) 45562e886fb3SSam Bobroff { 45572e886fb3SSam Bobroff CPUState *cs; 45582e886fb3SSam Bobroff 45592e886fb3SSam Bobroff CPU_FOREACH(cs) { 45602e886fb3SSam Bobroff PowerPCCPU *cpu = POWERPC_CPU(cs); 45612e886fb3SSam Bobroff 456214bb4486SGreg Kurz if (spapr_get_vcpu_id(cpu) == vcpu_id) { 45632e886fb3SSam Bobroff return cpu; 45642e886fb3SSam Bobroff } 45652e886fb3SSam Bobroff } 45662e886fb3SSam Bobroff 45672e886fb3SSam Bobroff return NULL; 45682e886fb3SSam Bobroff } 45692e886fb3SSam Bobroff 45707cebc5dbSNicholas Piggin static bool spapr_cpu_in_nested(PowerPCCPU *cpu) 45717cebc5dbSNicholas Piggin { 4572120f738aSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 4573120f738aSNicholas Piggin 4574120f738aSNicholas Piggin return spapr_cpu->in_nested; 45757cebc5dbSNicholas Piggin } 45767cebc5dbSNicholas Piggin 457703ef074cSNicholas Piggin static void spapr_cpu_exec_enter(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) 457803ef074cSNicholas Piggin { 457903ef074cSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 458003ef074cSNicholas Piggin 458103ef074cSNicholas Piggin /* These are only called by TCG, KVM maintains dispatch state */ 458203ef074cSNicholas Piggin 45833a6e6224SNicholas Piggin spapr_cpu->prod = false; 458403ef074cSNicholas Piggin if (spapr_cpu->vpa_addr) { 458503ef074cSNicholas Piggin CPUState *cs = CPU(cpu); 458603ef074cSNicholas Piggin uint32_t dispatch; 458703ef074cSNicholas Piggin 458803ef074cSNicholas Piggin dispatch = ldl_be_phys(cs->as, 458903ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER); 459003ef074cSNicholas Piggin dispatch++; 459103ef074cSNicholas Piggin if ((dispatch & 1) != 0) { 459203ef074cSNicholas Piggin qemu_log_mask(LOG_GUEST_ERROR, 459303ef074cSNicholas Piggin "VPA: incorrect dispatch counter value for " 459403ef074cSNicholas Piggin "dispatched partition %u, correcting.\n", dispatch); 459503ef074cSNicholas Piggin dispatch++; 459603ef074cSNicholas Piggin } 459703ef074cSNicholas Piggin stl_be_phys(cs->as, 459803ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch); 459903ef074cSNicholas Piggin } 460003ef074cSNicholas Piggin } 460103ef074cSNicholas Piggin 460203ef074cSNicholas Piggin static void spapr_cpu_exec_exit(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) 460303ef074cSNicholas Piggin { 460403ef074cSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 460503ef074cSNicholas Piggin 460603ef074cSNicholas Piggin if (spapr_cpu->vpa_addr) { 460703ef074cSNicholas Piggin CPUState *cs = CPU(cpu); 460803ef074cSNicholas Piggin uint32_t dispatch; 460903ef074cSNicholas Piggin 461003ef074cSNicholas Piggin dispatch = ldl_be_phys(cs->as, 461103ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER); 461203ef074cSNicholas Piggin dispatch++; 461303ef074cSNicholas Piggin if ((dispatch & 1) != 1) { 461403ef074cSNicholas Piggin qemu_log_mask(LOG_GUEST_ERROR, 461503ef074cSNicholas Piggin "VPA: incorrect dispatch counter value for " 461603ef074cSNicholas Piggin "preempted partition %u, correcting.\n", dispatch); 461703ef074cSNicholas Piggin dispatch++; 461803ef074cSNicholas Piggin } 461903ef074cSNicholas Piggin stl_be_phys(cs->as, 462003ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch); 462103ef074cSNicholas Piggin } 462203ef074cSNicholas Piggin } 462303ef074cSNicholas Piggin 462429ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data) 462553018216SPaolo Bonzini { 462629ee3247SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 4627ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(oc); 462871461b0fSAlexey Kardashevskiy FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); 462934316482SAlexey Kardashevskiy NMIClass *nc = NMI_CLASS(oc); 4630c20d332aSBharata B Rao HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); 46311d1be34dSDavid Gibson PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc); 46327844e12bSCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 46336449da45SCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 4634932de7aeSCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 4635fc8c745dSAlexey Kardashevskiy VofMachineIfClass *vmc = VOF_MACHINE_CLASS(oc); 463629ee3247SAlexey Kardashevskiy 46370eb9054cSDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant)"; 4638907aac2fSMark Cave-Ayland mc->ignore_boot_device_suffixes = true; 4639fc9f38c3SDavid Gibson 4640fc9f38c3SDavid Gibson /* 4641fc9f38c3SDavid Gibson * We set up the default / latest behaviour here. The class_init 4642fc9f38c3SDavid Gibson * functions for the specific versioned machine types can override 4643fc9f38c3SDavid Gibson * these details for backwards compatibility 4644fc9f38c3SDavid Gibson */ 4645bcb5ce08SDavid Gibson mc->init = spapr_machine_init; 4646bcb5ce08SDavid Gibson mc->reset = spapr_machine_reset; 4647958db90cSMarcel Apfelbaum mc->block_default_type = IF_SCSI; 46485642e451SDaniel Henrique Barboza 46495642e451SDaniel Henrique Barboza /* 46505642e451SDaniel Henrique Barboza * Setting max_cpus to INT32_MAX. Both KVM and TCG max_cpus values 46515642e451SDaniel Henrique Barboza * should be limited by the host capability instead of hardcoded. 46525642e451SDaniel Henrique Barboza * max_cpus for KVM guests will be checked in kvm_init(), and TCG 46535642e451SDaniel Henrique Barboza * guests are welcome to have as many CPUs as the host are capable 46545642e451SDaniel Henrique Barboza * of emulate. 46555642e451SDaniel Henrique Barboza */ 46565642e451SDaniel Henrique Barboza mc->max_cpus = INT32_MAX; 46575642e451SDaniel Henrique Barboza 4658958db90cSMarcel Apfelbaum mc->no_parallel = 1; 46595b2128d2SAlexander Graf mc->default_boot_order = ""; 4660d23b6caaSPhilippe Mathieu-Daudé mc->default_ram_size = 512 * MiB; 4661ab74e543SIgor Mammedov mc->default_ram_id = "ppc_spapr.ram"; 466229f9cef3SSebastian Bauer mc->default_display = "std"; 4663958db90cSMarcel Apfelbaum mc->kvm_type = spapr_kvm_type; 46647da79a16SEduardo Habkost machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SPAPR_PCI_HOST_BRIDGE); 4665e4024630SLaurent Vivier mc->pci_allow_0_address = true; 4666debbdc00SIgor Mammedov assert(!mc->get_hotplug_handler); 46677ebaf795SBharata B Rao mc->get_hotplug_handler = spapr_get_hotplug_handler; 466894a94e4cSBharata B Rao hc->pre_plug = spapr_machine_device_pre_plug; 4669c20d332aSBharata B Rao hc->plug = spapr_machine_device_plug; 4670ea089eebSIgor Mammedov mc->cpu_index_to_instance_props = spapr_cpu_index_to_props; 467179e07936SIgor Mammedov mc->get_default_cpu_node_id = spapr_get_default_cpu_node_id; 4672535455fdSIgor Mammedov mc->possible_cpu_arch_ids = spapr_possible_cpu_arch_ids; 4673cf632463SBharata B Rao hc->unplug_request = spapr_machine_device_unplug_request; 467488432f44SDavid Hildenbrand hc->unplug = spapr_machine_device_unplug; 467500b4fbe2SMarcel Apfelbaum 4676fc9f38c3SDavid Gibson smc->dr_lmb_enabled = true; 4677fea35ca4SAlexey Kardashevskiy smc->update_dt_enabled = true; 4678277ee172SNicholas Piggin mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.2"); 4679c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = true; 4680ee3a71e3SShivaprasad G Bhat mc->nvdimm_supported = true; 468152b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED; 468271461b0fSAlexey Kardashevskiy fwc->get_dev_path = spapr_get_fw_dev_path; 468334316482SAlexey Kardashevskiy nc->nmi_monitor_handler = spapr_nmi; 46846737d9adSDavid Gibson smc->phb_placement = spapr_phb_placement; 46857cebc5dbSNicholas Piggin vhc->cpu_in_nested = spapr_cpu_in_nested; 4686120f738aSNicholas Piggin vhc->deliver_hv_excp = spapr_exit_nested; 46871d1be34dSDavid Gibson vhc->hypercall = emulate_spapr_hypercall; 4688e57ca75cSDavid Gibson vhc->hpt_mask = spapr_hpt_mask; 4689e57ca75cSDavid Gibson vhc->map_hptes = spapr_map_hptes; 4690e57ca75cSDavid Gibson vhc->unmap_hptes = spapr_unmap_hptes; 4691a2dd4e83SBenjamin Herrenschmidt vhc->hpte_set_c = spapr_hpte_set_c; 4692a2dd4e83SBenjamin Herrenschmidt vhc->hpte_set_r = spapr_hpte_set_r; 469379825f4dSBenjamin Herrenschmidt vhc->get_pate = spapr_get_pate; 46941ec26c75SGreg Kurz vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr; 469503ef074cSNicholas Piggin vhc->cpu_exec_enter = spapr_cpu_exec_enter; 469603ef074cSNicholas Piggin vhc->cpu_exec_exit = spapr_cpu_exec_exit; 46977844e12bSCédric Le Goater xic->ics_get = spapr_ics_get; 46987844e12bSCédric Le Goater xic->ics_resend = spapr_ics_resend; 4699b2fc59aaSCédric Le Goater xic->icp_get = spapr_icp_get; 47006449da45SCédric Le Goater ispc->print_info = spapr_pic_print_info; 470155641213SLaurent Vivier /* Force NUMA node memory size to be a multiple of 470255641213SLaurent Vivier * SPAPR_MEMORY_BLOCK_SIZE (256M) since that's the granularity 470355641213SLaurent Vivier * in which LMBs are represented and hot-added 470455641213SLaurent Vivier */ 470555641213SLaurent Vivier mc->numa_mem_align_shift = 28; 47060533ef5fSTao Xu mc->auto_enable_numa = true; 470733face6bSDavid Gibson 47084e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF; 47094e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON; 47104e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON; 47112782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND; 47122782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND; 47132782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_WORKAROUND; 47142309832aSDavid Gibson smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */ 4715b9a477b7SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF; 4716edaa7995SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON; 471737965dfeSDavid Gibson smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_ON; 47188af7e1feSNicholas Piggin smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_ON; 471982123b75SBharata B Rao smc->default_caps.caps[SPAPR_CAP_RPT_INVALIDATE] = SPAPR_CAP_OFF; 4720ccc5a4c5SNicholas Piggin 4721ccc5a4c5SNicholas Piggin /* 4722ccc5a4c5SNicholas Piggin * This cap specifies whether the AIL 3 mode for 4723ccc5a4c5SNicholas Piggin * H_SET_RESOURCE is supported. The default is modified 4724ccc5a4c5SNicholas Piggin * by default_caps_with_cpu(). 4725ccc5a4c5SNicholas Piggin */ 4726ccc5a4c5SNicholas Piggin smc->default_caps.caps[SPAPR_CAP_AIL_MODE_3] = SPAPR_CAP_ON; 472740c2281cSMarkus Armbruster spapr_caps_add_properties(smc); 4728bd94bc06SCédric Le Goater smc->irq = &spapr_irq_dual; 4729dae5e39aSMichael Roth smc->dr_phb_enabled = true; 47306c3829a2SAlexey Kardashevskiy smc->linux_pci_probe = true; 473129cb4187SGreg Kurz smc->smp_threads_vsmt = true; 473254255c1fSDavid Gibson smc->nr_xirqs = SPAPR_NR_XIRQS; 4733932de7aeSCédric Le Goater xfc->match_nvt = spapr_match_nvt; 4734fc8c745dSAlexey Kardashevskiy vmc->client_architecture_support = spapr_vof_client_architecture_support; 4735fc8c745dSAlexey Kardashevskiy vmc->quiesce = spapr_vof_quiesce; 4736fc8c745dSAlexey Kardashevskiy vmc->setprop = spapr_vof_setprop; 473753018216SPaolo Bonzini } 473853018216SPaolo Bonzini 473929ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = { 474029ee3247SAlexey Kardashevskiy .name = TYPE_SPAPR_MACHINE, 474129ee3247SAlexey Kardashevskiy .parent = TYPE_MACHINE, 47424aee7362SDavid Gibson .abstract = true, 4743ce2918cbSDavid Gibson .instance_size = sizeof(SpaprMachineState), 4744bcb5ce08SDavid Gibson .instance_init = spapr_instance_init, 474587bbdd9cSDavid Gibson .instance_finalize = spapr_machine_finalizefn, 4746ce2918cbSDavid Gibson .class_size = sizeof(SpaprMachineClass), 474729ee3247SAlexey Kardashevskiy .class_init = spapr_machine_class_init, 474871461b0fSAlexey Kardashevskiy .interfaces = (InterfaceInfo[]) { 474971461b0fSAlexey Kardashevskiy { TYPE_FW_PATH_PROVIDER }, 475034316482SAlexey Kardashevskiy { TYPE_NMI }, 4751c20d332aSBharata B Rao { TYPE_HOTPLUG_HANDLER }, 47521d1be34dSDavid Gibson { TYPE_PPC_VIRTUAL_HYPERVISOR }, 47537844e12bSCédric Le Goater { TYPE_XICS_FABRIC }, 47546449da45SCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 4755932de7aeSCédric Le Goater { TYPE_XIVE_FABRIC }, 4756fc8c745dSAlexey Kardashevskiy { TYPE_VOF_MACHINE_IF }, 475771461b0fSAlexey Kardashevskiy { } 475871461b0fSAlexey Kardashevskiy }, 475929ee3247SAlexey Kardashevskiy }; 476029ee3247SAlexey Kardashevskiy 4761a7849268SMichael S. Tsirkin static void spapr_machine_latest_class_options(MachineClass *mc) 4762a7849268SMichael S. Tsirkin { 4763a7849268SMichael S. Tsirkin mc->alias = "pseries"; 4764ea0ac7f6SPhilippe Mathieu-Daudé mc->is_default = true; 4765a7849268SMichael S. Tsirkin } 4766a7849268SMichael S. Tsirkin 4767fccbc785SDavid Gibson #define DEFINE_SPAPR_MACHINE(suffix, verstr, latest) \ 47685013c547SDavid Gibson static void spapr_machine_##suffix##_class_init(ObjectClass *oc, \ 47695013c547SDavid Gibson void *data) \ 47705013c547SDavid Gibson { \ 47715013c547SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); \ 47725013c547SDavid Gibson spapr_machine_##suffix##_class_options(mc); \ 4773fccbc785SDavid Gibson if (latest) { \ 4774a7849268SMichael S. Tsirkin spapr_machine_latest_class_options(mc); \ 4775fccbc785SDavid Gibson } \ 47765013c547SDavid Gibson } \ 47775013c547SDavid Gibson static const TypeInfo spapr_machine_##suffix##_info = { \ 47785013c547SDavid Gibson .name = MACHINE_TYPE_NAME("pseries-" verstr), \ 47795013c547SDavid Gibson .parent = TYPE_SPAPR_MACHINE, \ 47805013c547SDavid Gibson .class_init = spapr_machine_##suffix##_class_init, \ 47815013c547SDavid Gibson }; \ 47825013c547SDavid Gibson static void spapr_machine_register_##suffix(void) \ 47835013c547SDavid Gibson { \ 47845013c547SDavid Gibson type_register(&spapr_machine_##suffix##_info); \ 47855013c547SDavid Gibson } \ 47860e6aac87SEduardo Habkost type_init(spapr_machine_register_##suffix) 47875013c547SDavid Gibson 47881c5f29bbSDavid Gibson /* 478995f5c89eSCornelia Huck * pseries-8.2 47903eb74d20SCornelia Huck */ 479195f5c89eSCornelia Huck static void spapr_machine_8_2_class_options(MachineClass *mc) 47923eb74d20SCornelia Huck { 47933eb74d20SCornelia Huck /* Defaults for the latest behaviour inherited from the base class */ 47943eb74d20SCornelia Huck } 47953eb74d20SCornelia Huck 479695f5c89eSCornelia Huck DEFINE_SPAPR_MACHINE(8_2, "8.2", true); 479795f5c89eSCornelia Huck 479895f5c89eSCornelia Huck /* 479995f5c89eSCornelia Huck * pseries-8.1 480095f5c89eSCornelia Huck */ 480195f5c89eSCornelia Huck static void spapr_machine_8_1_class_options(MachineClass *mc) 480295f5c89eSCornelia Huck { 480395f5c89eSCornelia Huck spapr_machine_8_2_class_options(mc); 480495f5c89eSCornelia Huck compat_props_add(mc->compat_props, hw_compat_8_1, hw_compat_8_1_len); 480595f5c89eSCornelia Huck } 480695f5c89eSCornelia Huck 480795f5c89eSCornelia Huck DEFINE_SPAPR_MACHINE(8_1, "8.1", false); 4808f9be4771SCornelia Huck 4809f9be4771SCornelia Huck /* 4810f9be4771SCornelia Huck * pseries-8.0 4811f9be4771SCornelia Huck */ 4812f9be4771SCornelia Huck static void spapr_machine_8_0_class_options(MachineClass *mc) 4813f9be4771SCornelia Huck { 4814f9be4771SCornelia Huck spapr_machine_8_1_class_options(mc); 4815f9be4771SCornelia Huck compat_props_add(mc->compat_props, hw_compat_8_0, hw_compat_8_0_len); 4816f9be4771SCornelia Huck } 4817f9be4771SCornelia Huck 4818f9be4771SCornelia Huck DEFINE_SPAPR_MACHINE(8_0, "8.0", false); 4819db723c80SCornelia Huck 4820db723c80SCornelia Huck /* 4821db723c80SCornelia Huck * pseries-7.2 4822db723c80SCornelia Huck */ 4823db723c80SCornelia Huck static void spapr_machine_7_2_class_options(MachineClass *mc) 4824db723c80SCornelia Huck { 4825db723c80SCornelia Huck spapr_machine_8_0_class_options(mc); 4826db723c80SCornelia Huck compat_props_add(mc->compat_props, hw_compat_7_2, hw_compat_7_2_len); 4827db723c80SCornelia Huck } 4828db723c80SCornelia Huck 4829db723c80SCornelia Huck DEFINE_SPAPR_MACHINE(7_2, "7.2", false); 4830f514e147SCornelia Huck 4831f514e147SCornelia Huck /* 4832f514e147SCornelia Huck * pseries-7.1 4833f514e147SCornelia Huck */ 4834f514e147SCornelia Huck static void spapr_machine_7_1_class_options(MachineClass *mc) 4835f514e147SCornelia Huck { 4836f514e147SCornelia Huck spapr_machine_7_2_class_options(mc); 4837f514e147SCornelia Huck compat_props_add(mc->compat_props, hw_compat_7_1, hw_compat_7_1_len); 4838f514e147SCornelia Huck } 4839f514e147SCornelia Huck 4840f514e147SCornelia Huck DEFINE_SPAPR_MACHINE(7_1, "7.1", false); 48410ca70366SCornelia Huck 48420ca70366SCornelia Huck /* 48430ca70366SCornelia Huck * pseries-7.0 48440ca70366SCornelia Huck */ 48450ca70366SCornelia Huck static void spapr_machine_7_0_class_options(MachineClass *mc) 48460ca70366SCornelia Huck { 48470ca70366SCornelia Huck spapr_machine_7_1_class_options(mc); 48480ca70366SCornelia Huck compat_props_add(mc->compat_props, hw_compat_7_0, hw_compat_7_0_len); 48490ca70366SCornelia Huck } 48500ca70366SCornelia Huck 48510ca70366SCornelia Huck DEFINE_SPAPR_MACHINE(7_0, "7.0", false); 485201854af2SCornelia Huck 485301854af2SCornelia Huck /* 485401854af2SCornelia Huck * pseries-6.2 485501854af2SCornelia Huck */ 485601854af2SCornelia Huck static void spapr_machine_6_2_class_options(MachineClass *mc) 485701854af2SCornelia Huck { 485801854af2SCornelia Huck spapr_machine_7_0_class_options(mc); 485901854af2SCornelia Huck compat_props_add(mc->compat_props, hw_compat_6_2, hw_compat_6_2_len); 486001854af2SCornelia Huck } 486101854af2SCornelia Huck 486201854af2SCornelia Huck DEFINE_SPAPR_MACHINE(6_2, "6.2", false); 486352e64f5bSYanan Wang 486452e64f5bSYanan Wang /* 486552e64f5bSYanan Wang * pseries-6.1 486652e64f5bSYanan Wang */ 486752e64f5bSYanan Wang static void spapr_machine_6_1_class_options(MachineClass *mc) 486852e64f5bSYanan Wang { 4869e0eb84d4SDaniel Henrique Barboza SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4870e0eb84d4SDaniel Henrique Barboza 487152e64f5bSYanan Wang spapr_machine_6_2_class_options(mc); 487252e64f5bSYanan Wang compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len); 4873e0eb84d4SDaniel Henrique Barboza smc->pre_6_2_numa_affinity = true; 48742b526199SYanan Wang mc->smp_props.prefer_sockets = true; 487552e64f5bSYanan Wang } 487652e64f5bSYanan Wang 487752e64f5bSYanan Wang DEFINE_SPAPR_MACHINE(6_1, "6.1", false); 4878da7e13c0SCornelia Huck 4879da7e13c0SCornelia Huck /* 4880da7e13c0SCornelia Huck * pseries-6.0 4881da7e13c0SCornelia Huck */ 4882da7e13c0SCornelia Huck static void spapr_machine_6_0_class_options(MachineClass *mc) 4883da7e13c0SCornelia Huck { 4884da7e13c0SCornelia Huck spapr_machine_6_1_class_options(mc); 4885da7e13c0SCornelia Huck compat_props_add(mc->compat_props, hw_compat_6_0, hw_compat_6_0_len); 4886da7e13c0SCornelia Huck } 4887da7e13c0SCornelia Huck 4888da7e13c0SCornelia Huck DEFINE_SPAPR_MACHINE(6_0, "6.0", false); 4889576a00bdSCornelia Huck 4890576a00bdSCornelia Huck /* 4891576a00bdSCornelia Huck * pseries-5.2 4892576a00bdSCornelia Huck */ 4893576a00bdSCornelia Huck static void spapr_machine_5_2_class_options(MachineClass *mc) 4894576a00bdSCornelia Huck { 4895576a00bdSCornelia Huck spapr_machine_6_0_class_options(mc); 4896576a00bdSCornelia Huck compat_props_add(mc->compat_props, hw_compat_5_2, hw_compat_5_2_len); 4897576a00bdSCornelia Huck } 4898576a00bdSCornelia Huck 4899576a00bdSCornelia Huck DEFINE_SPAPR_MACHINE(5_2, "5.2", false); 49003ff3c5d3SCornelia Huck 49013ff3c5d3SCornelia Huck /* 49023ff3c5d3SCornelia Huck * pseries-5.1 49033ff3c5d3SCornelia Huck */ 49043ff3c5d3SCornelia Huck static void spapr_machine_5_1_class_options(MachineClass *mc) 49053ff3c5d3SCornelia Huck { 490629bfe52aSDaniel Henrique Barboza SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 490729bfe52aSDaniel Henrique Barboza 49083ff3c5d3SCornelia Huck spapr_machine_5_2_class_options(mc); 49093ff3c5d3SCornelia Huck compat_props_add(mc->compat_props, hw_compat_5_1, hw_compat_5_1_len); 491029bfe52aSDaniel Henrique Barboza smc->pre_5_2_numa_associativity = true; 49113ff3c5d3SCornelia Huck } 49123ff3c5d3SCornelia Huck 49133ff3c5d3SCornelia Huck DEFINE_SPAPR_MACHINE(5_1, "5.1", false); 4914541aaa1dSCornelia Huck 4915541aaa1dSCornelia Huck /* 4916541aaa1dSCornelia Huck * pseries-5.0 4917541aaa1dSCornelia Huck */ 4918541aaa1dSCornelia Huck static void spapr_machine_5_0_class_options(MachineClass *mc) 4919541aaa1dSCornelia Huck { 4920a6030d7eSReza Arbab SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4921a6030d7eSReza Arbab static GlobalProperty compat[] = { 4922a6030d7eSReza Arbab { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-5.1-associativity", "on" }, 4923a6030d7eSReza Arbab }; 4924a6030d7eSReza Arbab 4925541aaa1dSCornelia Huck spapr_machine_5_1_class_options(mc); 4926541aaa1dSCornelia Huck compat_props_add(mc->compat_props, hw_compat_5_0, hw_compat_5_0_len); 4927a6030d7eSReza Arbab compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 492832a354dcSIgor Mammedov mc->numa_mem_supported = true; 4929a6030d7eSReza Arbab smc->pre_5_1_assoc_refpoints = true; 4930541aaa1dSCornelia Huck } 4931541aaa1dSCornelia Huck 4932541aaa1dSCornelia Huck DEFINE_SPAPR_MACHINE(5_0, "5.0", false); 49333eb74d20SCornelia Huck 49343eb74d20SCornelia Huck /* 49359aec2e52SCornelia Huck * pseries-4.2 4936e2676b16SGreg Kurz */ 49379aec2e52SCornelia Huck static void spapr_machine_4_2_class_options(MachineClass *mc) 4938e2676b16SGreg Kurz { 493937965dfeSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 494037965dfeSDavid Gibson 49413eb74d20SCornelia Huck spapr_machine_5_0_class_options(mc); 49425f258577SEvgeny Yakovlev compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len); 494337965dfeSDavid Gibson smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF; 49448af7e1feSNicholas Piggin smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_OFF; 49451052ab67SDavid Gibson smc->rma_limit = 16 * GiB; 4946ee3a71e3SShivaprasad G Bhat mc->nvdimm_supported = false; 4947e2676b16SGreg Kurz } 4948e2676b16SGreg Kurz 49493eb74d20SCornelia Huck DEFINE_SPAPR_MACHINE(4_2, "4.2", false); 49509aec2e52SCornelia Huck 49519aec2e52SCornelia Huck /* 49529aec2e52SCornelia Huck * pseries-4.1 49539aec2e52SCornelia Huck */ 49549aec2e52SCornelia Huck static void spapr_machine_4_1_class_options(MachineClass *mc) 49559aec2e52SCornelia Huck { 49566c3829a2SAlexey Kardashevskiy SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4957d15d4ad6SDavid Gibson static GlobalProperty compat[] = { 4958d15d4ad6SDavid Gibson /* Only allow 4kiB and 64kiB IOMMU pagesizes */ 4959d15d4ad6SDavid Gibson { TYPE_SPAPR_PCI_HOST_BRIDGE, "pgsz", "0x11000" }, 4960d15d4ad6SDavid Gibson }; 4961d15d4ad6SDavid Gibson 49629aec2e52SCornelia Huck spapr_machine_4_2_class_options(mc); 49636c3829a2SAlexey Kardashevskiy smc->linux_pci_probe = false; 496429cb4187SGreg Kurz smc->smp_threads_vsmt = false; 49659aec2e52SCornelia Huck compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len); 4966d15d4ad6SDavid Gibson compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 49679aec2e52SCornelia Huck } 49689aec2e52SCornelia Huck 49699aec2e52SCornelia Huck DEFINE_SPAPR_MACHINE(4_1, "4.1", false); 49709bf2650bSCornelia Huck 49719bf2650bSCornelia Huck /* 49729bf2650bSCornelia Huck * pseries-4.0 49739bf2650bSCornelia Huck */ 4974f5598c92SGreg Kurz static bool phb_placement_4_0(SpaprMachineState *spapr, uint32_t index, 4975ec132efaSAlexey Kardashevskiy uint64_t *buid, hwaddr *pio, 4976ec132efaSAlexey Kardashevskiy hwaddr *mmio32, hwaddr *mmio64, 497744fa20c9SCédric Le Goater unsigned n_dma, uint32_t *liobns, Error **errp) 4978ec132efaSAlexey Kardashevskiy { 4979f5598c92SGreg Kurz if (!spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma, 498044fa20c9SCédric Le Goater liobns, errp)) { 4981f5598c92SGreg Kurz return false; 4982ec132efaSAlexey Kardashevskiy } 4983f5598c92SGreg Kurz return true; 4984f5598c92SGreg Kurz } 4985eb3cba82SDavid Gibson static void spapr_machine_4_0_class_options(MachineClass *mc) 4986eb3cba82SDavid Gibson { 4987eb3cba82SDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4988eb3cba82SDavid Gibson 4989eb3cba82SDavid Gibson spapr_machine_4_1_class_options(mc); 4990eb3cba82SDavid Gibson compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); 4991eb3cba82SDavid Gibson smc->phb_placement = phb_placement_4_0; 4992bd94bc06SCédric Le Goater smc->irq = &spapr_irq_xics; 49933725ef1aSGreg Kurz smc->pre_4_1_migration = true; 4994eb3cba82SDavid Gibson } 4995eb3cba82SDavid Gibson 4996eb3cba82SDavid Gibson DEFINE_SPAPR_MACHINE(4_0, "4.0", false); 4997eb3cba82SDavid Gibson 4998eb3cba82SDavid Gibson /* 4999eb3cba82SDavid Gibson * pseries-3.1 5000eb3cba82SDavid Gibson */ 500188cbe073SMarc-André Lureau static void spapr_machine_3_1_class_options(MachineClass *mc) 500288cbe073SMarc-André Lureau { 5003ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 5004fea35ca4SAlexey Kardashevskiy 500584e060bfSAlex Williamson spapr_machine_4_0_class_options(mc); 5006abd93cc7SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len); 500727461d69SPrasad J Pandit 500834a6b015SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 5009fea35ca4SAlexey Kardashevskiy smc->update_dt_enabled = false; 5010dae5e39aSMichael Roth smc->dr_phb_enabled = false; 50110a794529SDavid Gibson smc->broken_host_serial_model = true; 50122782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN; 50132782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN; 50142782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN; 5015edaa7995SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF; 501684e060bfSAlex Williamson } 501784e060bfSAlex Williamson 501884e060bfSAlex Williamson DEFINE_SPAPR_MACHINE(3_1, "3.1", false); 5019d45360d9SCédric Le Goater 5020d45360d9SCédric Le Goater /* 5021d45360d9SCédric Le Goater * pseries-3.0 5022d45360d9SCédric Le Goater */ 5023d45360d9SCédric Le Goater 5024d45360d9SCédric Le Goater static void spapr_machine_3_0_class_options(MachineClass *mc) 5025d45360d9SCédric Le Goater { 5026ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 502782cffa2eSCédric Le Goater 5028d45360d9SCédric Le Goater spapr_machine_3_1_class_options(mc); 5029ddb3235dSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len); 503082cffa2eSCédric Le Goater 503182cffa2eSCédric Le Goater smc->legacy_irq_allocation = true; 503254255c1fSDavid Gibson smc->nr_xirqs = 0x400; 5033ae837402SCédric Le Goater smc->irq = &spapr_irq_xics_legacy; 5034d45360d9SCédric Le Goater } 5035d45360d9SCédric Le Goater 5036d45360d9SCédric Le Goater DEFINE_SPAPR_MACHINE(3_0, "3.0", false); 50378a4fd427SDavid Gibson 50388a4fd427SDavid Gibson /* 50398a4fd427SDavid Gibson * pseries-2.12 50408a4fd427SDavid Gibson */ 504188cbe073SMarc-André Lureau static void spapr_machine_2_12_class_options(MachineClass *mc) 504288cbe073SMarc-André Lureau { 5043ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 504488cbe073SMarc-André Lureau static GlobalProperty compat[] = { 50456c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-3.0-migration", "on" }, 50466c36bddfSEduardo Habkost { TYPE_SPAPR_CPU_CORE, "pre-3.0-migration", "on" }, 5047fa386d98SMarc-André Lureau }; 50488a4fd427SDavid Gibson 5049d8c0c7afSPeter Maydell spapr_machine_3_0_class_options(mc); 50500d47310bSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_12, hw_compat_2_12_len); 505188cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 50522309832aSDavid Gibson 5053e8937295SGreg Kurz /* We depend on kvm_enabled() to choose a default value for the 5054e8937295SGreg Kurz * hpt-max-page-size capability. Of course we can't do it here 5055e6a19a64SMichael Tokarev * because this is too early and the HW accelerator isn't initialized 5056e8937295SGreg Kurz * yet. Postpone this to machine init (see default_caps_with_cpu()). 5057e8937295SGreg Kurz */ 5058e8937295SGreg Kurz smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 0; 50598a4fd427SDavid Gibson } 50608a4fd427SDavid Gibson 50618a4fd427SDavid Gibson DEFINE_SPAPR_MACHINE(2_12, "2.12", false); 50622b615412SDavid Gibson 5063813f3cf6SSuraj Jitindar Singh static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc) 5064813f3cf6SSuraj Jitindar Singh { 5065ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 5066813f3cf6SSuraj Jitindar Singh 5067813f3cf6SSuraj Jitindar Singh spapr_machine_2_12_class_options(mc); 5068813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND; 5069813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND; 5070813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_FIXED_CCD; 5071813f3cf6SSuraj Jitindar Singh } 5072813f3cf6SSuraj Jitindar Singh 5073813f3cf6SSuraj Jitindar Singh DEFINE_SPAPR_MACHINE(2_12_sxxm, "2.12-sxxm", false); 5074813f3cf6SSuraj Jitindar Singh 50752b615412SDavid Gibson /* 50762b615412SDavid Gibson * pseries-2.11 50772b615412SDavid Gibson */ 50782b615412SDavid Gibson 50792b615412SDavid Gibson static void spapr_machine_2_11_class_options(MachineClass *mc) 50802b615412SDavid Gibson { 5081ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 5082ee76a09fSDavid Gibson 50832b615412SDavid Gibson spapr_machine_2_12_class_options(mc); 50844e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON; 508543df70a9SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len); 50862b615412SDavid Gibson } 50872b615412SDavid Gibson 50882b615412SDavid Gibson DEFINE_SPAPR_MACHINE(2_11, "2.11", false); 5089e2676b16SGreg Kurz 5090e2676b16SGreg Kurz /* 50913fa14fbeSDavid Gibson * pseries-2.10 5092db800b21SDavid Gibson */ 5093e2676b16SGreg Kurz 50943fa14fbeSDavid Gibson static void spapr_machine_2_10_class_options(MachineClass *mc) 5095db800b21SDavid Gibson { 5096e2676b16SGreg Kurz spapr_machine_2_11_class_options(mc); 5097503224f4SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_10, hw_compat_2_10_len); 5098db800b21SDavid Gibson } 5099db800b21SDavid Gibson 5100e2676b16SGreg Kurz DEFINE_SPAPR_MACHINE(2_10, "2.10", false); 51013fa14fbeSDavid Gibson 51023fa14fbeSDavid Gibson /* 51033fa14fbeSDavid Gibson * pseries-2.9 51043fa14fbeSDavid Gibson */ 510588cbe073SMarc-André Lureau 510688cbe073SMarc-André Lureau static void spapr_machine_2_9_class_options(MachineClass *mc) 510788cbe073SMarc-André Lureau { 5108ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 510988cbe073SMarc-André Lureau static GlobalProperty compat[] = { 51106c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-2.10-migration", "on" }, 5111fa386d98SMarc-André Lureau }; 51123fa14fbeSDavid Gibson 51133fa14fbeSDavid Gibson spapr_machine_2_10_class_options(mc); 51143e803152SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len); 511588cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 511646f7afa3SGreg Kurz smc->pre_2_10_has_unused_icps = true; 511752b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED; 51183fa14fbeSDavid Gibson } 51193fa14fbeSDavid Gibson 51203fa14fbeSDavid Gibson DEFINE_SPAPR_MACHINE(2_9, "2.9", false); 5121fa325e6cSDavid Gibson 5122fa325e6cSDavid Gibson /* 5123fa325e6cSDavid Gibson * pseries-2.8 5124fa325e6cSDavid Gibson */ 512588cbe073SMarc-André Lureau 512688cbe073SMarc-André Lureau static void spapr_machine_2_8_class_options(MachineClass *mc) 512788cbe073SMarc-André Lureau { 512888cbe073SMarc-André Lureau static GlobalProperty compat[] = { 51296c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "pcie-extended-configuration-space", "off" }, 5130fa386d98SMarc-André Lureau }; 5131fa325e6cSDavid Gibson 5132fa325e6cSDavid Gibson spapr_machine_2_9_class_options(mc); 5133edc24ccdSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len); 513488cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 513555641213SLaurent Vivier mc->numa_mem_align_shift = 23; 5136fa325e6cSDavid Gibson } 5137fa325e6cSDavid Gibson 5138fa325e6cSDavid Gibson DEFINE_SPAPR_MACHINE(2_8, "2.8", false); 5139db800b21SDavid Gibson 5140db800b21SDavid Gibson /* 51411ea1eefcSBharata B Rao * pseries-2.7 51421ea1eefcSBharata B Rao */ 5143357d1e3bSDavid Gibson 5144f5598c92SGreg Kurz static bool phb_placement_2_7(SpaprMachineState *spapr, uint32_t index, 5145357d1e3bSDavid Gibson uint64_t *buid, hwaddr *pio, 5146357d1e3bSDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 514744fa20c9SCédric Le Goater unsigned n_dma, uint32_t *liobns, Error **errp) 5148357d1e3bSDavid Gibson { 5149357d1e3bSDavid Gibson /* Legacy PHB placement for pseries-2.7 and earlier machine types */ 5150357d1e3bSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 5151357d1e3bSDavid Gibson const hwaddr phb_spacing = 0x1000000000ULL; /* 64 GiB */ 5152357d1e3bSDavid Gibson const hwaddr mmio_offset = 0xa0000000; /* 2 GiB + 512 MiB */ 5153357d1e3bSDavid Gibson const hwaddr pio_offset = 0x80000000; /* 2 GiB */ 5154357d1e3bSDavid Gibson const uint32_t max_index = 255; 5155357d1e3bSDavid Gibson const hwaddr phb0_alignment = 0x10000000000ULL; /* 1 TiB */ 5156357d1e3bSDavid Gibson 5157357d1e3bSDavid Gibson uint64_t ram_top = MACHINE(spapr)->ram_size; 5158357d1e3bSDavid Gibson hwaddr phb0_base, phb_base; 5159357d1e3bSDavid Gibson int i; 5160357d1e3bSDavid Gibson 51610c9269a5SDavid Hildenbrand /* Do we have device memory? */ 5162c0ce7b4aSDavid Hildenbrand if (MACHINE(spapr)->device_memory) { 5163357d1e3bSDavid Gibson /* Can't just use maxram_size, because there may be an 51640c9269a5SDavid Hildenbrand * alignment gap between normal and device memory regions 51650c9269a5SDavid Hildenbrand */ 5166b0c14ec4SDavid Hildenbrand ram_top = MACHINE(spapr)->device_memory->base + 5167b0c14ec4SDavid Hildenbrand memory_region_size(&MACHINE(spapr)->device_memory->mr); 5168357d1e3bSDavid Gibson } 5169357d1e3bSDavid Gibson 5170357d1e3bSDavid Gibson phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment); 5171357d1e3bSDavid Gibson 5172357d1e3bSDavid Gibson if (index > max_index) { 5173357d1e3bSDavid Gibson error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", 5174357d1e3bSDavid Gibson max_index); 5175f5598c92SGreg Kurz return false; 5176357d1e3bSDavid Gibson } 5177357d1e3bSDavid Gibson 5178357d1e3bSDavid Gibson *buid = base_buid + index; 5179357d1e3bSDavid Gibson for (i = 0; i < n_dma; ++i) { 5180357d1e3bSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 5181357d1e3bSDavid Gibson } 5182357d1e3bSDavid Gibson 5183357d1e3bSDavid Gibson phb_base = phb0_base + index * phb_spacing; 5184357d1e3bSDavid Gibson *pio = phb_base + pio_offset; 5185357d1e3bSDavid Gibson *mmio32 = phb_base + mmio_offset; 5186357d1e3bSDavid Gibson /* 5187357d1e3bSDavid Gibson * We don't set the 64-bit MMIO window, relying on the PHB's 5188357d1e3bSDavid Gibson * fallback behaviour of automatically splitting a large "32-bit" 5189357d1e3bSDavid Gibson * window into contiguous 32-bit and 64-bit windows 5190357d1e3bSDavid Gibson */ 5191ec132efaSAlexey Kardashevskiy 5192f5598c92SGreg Kurz return true; 5193357d1e3bSDavid Gibson } 5194db800b21SDavid Gibson 51951ea1eefcSBharata B Rao static void spapr_machine_2_7_class_options(MachineClass *mc) 51961ea1eefcSBharata B Rao { 5197ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 519888cbe073SMarc-André Lureau static GlobalProperty compat[] = { 51996c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0xf80000000", }, 52006c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem64_win_size", "0", }, 52016c36bddfSEduardo Habkost { TYPE_POWERPC_CPU, "pre-2.8-migration", "on", }, 52026c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-2.8-migration", "on", }, 520388cbe073SMarc-André Lureau }; 52043daa4a9fSThomas Huth 5205db800b21SDavid Gibson spapr_machine_2_8_class_options(mc); 52062e9c10ebSIgor Mammedov mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power7_v2.3"); 5207a140c199SEduardo Habkost mc->default_machine_opts = "modern-hotplug-events=off"; 52085a995064SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_7, hw_compat_2_7_len); 520988cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 5210357d1e3bSDavid Gibson smc->phb_placement = phb_placement_2_7; 52111ea1eefcSBharata B Rao } 52121ea1eefcSBharata B Rao 5213db800b21SDavid Gibson DEFINE_SPAPR_MACHINE(2_7, "2.7", false); 52141ea1eefcSBharata B Rao 52151ea1eefcSBharata B Rao /* 52164b23699cSDavid Gibson * pseries-2.6 52174b23699cSDavid Gibson */ 521888cbe073SMarc-André Lureau 521988cbe073SMarc-André Lureau static void spapr_machine_2_6_class_options(MachineClass *mc) 522088cbe073SMarc-André Lureau { 522188cbe073SMarc-André Lureau static GlobalProperty compat[] = { 52226c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "ddw", "off" }, 5223fa386d98SMarc-André Lureau }; 52241ea1eefcSBharata B Rao 52251ea1eefcSBharata B Rao spapr_machine_2_7_class_options(mc); 5226c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = false; 5227ff8f261fSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_6, hw_compat_2_6_len); 522888cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 52294b23699cSDavid Gibson } 52304b23699cSDavid Gibson 52311ea1eefcSBharata B Rao DEFINE_SPAPR_MACHINE(2_6, "2.6", false); 52324b23699cSDavid Gibson 52334b23699cSDavid Gibson /* 52341c5f29bbSDavid Gibson * pseries-2.5 52351c5f29bbSDavid Gibson */ 523688cbe073SMarc-André Lureau 523788cbe073SMarc-André Lureau static void spapr_machine_2_5_class_options(MachineClass *mc) 523888cbe073SMarc-André Lureau { 5239ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 524088cbe073SMarc-André Lureau static GlobalProperty compat[] = { 52416c36bddfSEduardo Habkost { "spapr-vlan", "use-rx-buffer-pools", "off" }, 5242fa386d98SMarc-André Lureau }; 52434b23699cSDavid Gibson 52444b23699cSDavid Gibson spapr_machine_2_6_class_options(mc); 524557040d45SThomas Huth smc->use_ohci_by_default = true; 5246fe759610SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_5, hw_compat_2_5_len); 524788cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 52481c5f29bbSDavid Gibson } 52491c5f29bbSDavid Gibson 52504b23699cSDavid Gibson DEFINE_SPAPR_MACHINE(2_5, "2.5", false); 52511c5f29bbSDavid Gibson 52521c5f29bbSDavid Gibson /* 52531c5f29bbSDavid Gibson * pseries-2.4 52541c5f29bbSDavid Gibson */ 525580fd50f9SCornelia Huck 52565013c547SDavid Gibson static void spapr_machine_2_4_class_options(MachineClass *mc) 52575013c547SDavid Gibson { 5258ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 5259fc9f38c3SDavid Gibson 5260fc9f38c3SDavid Gibson spapr_machine_2_5_class_options(mc); 5261fc9f38c3SDavid Gibson smc->dr_lmb_enabled = false; 52622f99b9c2SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_4, hw_compat_2_4_len); 52631c5f29bbSDavid Gibson } 52641c5f29bbSDavid Gibson 5265fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_4, "2.4", false); 52661c5f29bbSDavid Gibson 52671c5f29bbSDavid Gibson /* 52681c5f29bbSDavid Gibson * pseries-2.3 52691c5f29bbSDavid Gibson */ 527088cbe073SMarc-André Lureau 527188cbe073SMarc-André Lureau static void spapr_machine_2_3_class_options(MachineClass *mc) 527288cbe073SMarc-André Lureau { 527388cbe073SMarc-André Lureau static GlobalProperty compat[] = { 52746c36bddfSEduardo Habkost { "spapr-pci-host-bridge", "dynamic-reconfiguration", "off" }, 5275fa386d98SMarc-André Lureau }; 5276fc9f38c3SDavid Gibson spapr_machine_2_4_class_options(mc); 52778995dd90SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_3, hw_compat_2_3_len); 527888cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 52791c5f29bbSDavid Gibson } 5280fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_3, "2.3", false); 52811c5f29bbSDavid Gibson 52821c5f29bbSDavid Gibson /* 52831c5f29bbSDavid Gibson * pseries-2.2 52841c5f29bbSDavid Gibson */ 528588cbe073SMarc-André Lureau 528688cbe073SMarc-André Lureau static void spapr_machine_2_2_class_options(MachineClass *mc) 528788cbe073SMarc-André Lureau { 528888cbe073SMarc-André Lureau static GlobalProperty compat[] = { 52896c36bddfSEduardo Habkost { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0x20000000" }, 5290fa386d98SMarc-André Lureau }; 5291b194df47SAlexey Kardashevskiy 5292fc9f38c3SDavid Gibson spapr_machine_2_3_class_options(mc); 52931c30044eSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_2, hw_compat_2_2_len); 529488cbe073SMarc-André Lureau compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 5295f6d0656bSEduardo Habkost mc->default_machine_opts = "modern-hotplug-events=off,suppress-vmdesc=on"; 52961c5f29bbSDavid Gibson } 5297fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_2, "2.2", false); 52981c5f29bbSDavid Gibson 52991c5f29bbSDavid Gibson /* 53001c5f29bbSDavid Gibson * pseries-2.1 53011c5f29bbSDavid Gibson */ 53021c5f29bbSDavid Gibson 53035013c547SDavid Gibson static void spapr_machine_2_1_class_options(MachineClass *mc) 5304b0e966d0SJason Wang { 5305fc9f38c3SDavid Gibson spapr_machine_2_2_class_options(mc); 5306c4fc5695SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_2_1, hw_compat_2_1_len); 53076026db45SAlexey Kardashevskiy } 5308fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_1, "2.1", false); 53096026db45SAlexey Kardashevskiy 531029ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void) 531129ee3247SAlexey Kardashevskiy { 531229ee3247SAlexey Kardashevskiy type_register_static(&spapr_machine_info); 531329ee3247SAlexey Kardashevskiy } 531429ee3247SAlexey Kardashevskiy 531529ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types) 5316