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 * 2653018216SPaolo Bonzini */ 270d75590dSPeter Maydell #include "qemu/osdep.h" 28da34e65cSMarkus Armbruster #include "qapi/error.h" 29fa98fbfcSSam Bobroff #include "qapi/visitor.h" 3053018216SPaolo Bonzini #include "sysemu/sysemu.h" 31e35704baSEduardo Habkost #include "sysemu/numa.h" 3253018216SPaolo Bonzini #include "hw/hw.h" 3303dd024fSPaolo Bonzini #include "qemu/log.h" 3471461b0fSAlexey Kardashevskiy #include "hw/fw-path-provider.h" 3553018216SPaolo Bonzini #include "elf.h" 3653018216SPaolo Bonzini #include "net/net.h" 37ad440b4aSAndrew Jones #include "sysemu/device_tree.h" 38fa1d36dfSMarkus Armbruster #include "sysemu/block-backend.h" 3953018216SPaolo Bonzini #include "sysemu/cpus.h" 40b3946626SVincent Palatin #include "sysemu/hw_accel.h" 4153018216SPaolo Bonzini #include "kvm_ppc.h" 42c4b63b7cSJuan Quintela #include "migration/misc.h" 4384a899deSJuan Quintela #include "migration/global_state.h" 44f2a8f0a6SJuan Quintela #include "migration/register.h" 454be21d56SDavid Gibson #include "mmu-hash64.h" 46b4db5413SSuraj Jitindar Singh #include "mmu-book3s-v3.h" 477abd43baSSuraj Jitindar Singh #include "cpu-models.h" 483794d548SAlexey Kardashevskiy #include "qom/cpu.h" 4953018216SPaolo Bonzini 5053018216SPaolo Bonzini #include "hw/boards.h" 510d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h" 5253018216SPaolo Bonzini #include "hw/loader.h" 5353018216SPaolo Bonzini 547804c353SCédric Le Goater #include "hw/ppc/fdt.h" 550d09e41aSPaolo Bonzini #include "hw/ppc/spapr.h" 560d09e41aSPaolo Bonzini #include "hw/ppc/spapr_vio.h" 570d09e41aSPaolo Bonzini #include "hw/pci-host/spapr.h" 580d09e41aSPaolo Bonzini #include "hw/ppc/xics.h" 5953018216SPaolo Bonzini #include "hw/pci/msi.h" 6053018216SPaolo Bonzini 6153018216SPaolo Bonzini #include "hw/pci/pci.h" 6271461b0fSAlexey Kardashevskiy #include "hw/scsi/scsi.h" 6371461b0fSAlexey Kardashevskiy #include "hw/virtio/virtio-scsi.h" 64c4e13492SFelipe Franciosi #include "hw/virtio/vhost-scsi-common.h" 6553018216SPaolo Bonzini 6653018216SPaolo Bonzini #include "exec/address-spaces.h" 6753018216SPaolo Bonzini #include "hw/usb.h" 6853018216SPaolo Bonzini #include "qemu/config-file.h" 69135a129aSAneesh Kumar K.V #include "qemu/error-report.h" 702a6593cbSAlexey Kardashevskiy #include "trace.h" 7134316482SAlexey Kardashevskiy #include "hw/nmi.h" 726449da45SCédric Le Goater #include "hw/intc/intc.h" 7353018216SPaolo Bonzini 7468a27b20SMichael S. Tsirkin #include "hw/compat.h" 75f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 7694a94e4cSBharata B Rao #include "hw/ppc/spapr_cpu_core.h" 7768a27b20SMichael S. Tsirkin 7853018216SPaolo Bonzini #include <libfdt.h> 7953018216SPaolo Bonzini 8053018216SPaolo Bonzini /* SLOF memory layout: 8153018216SPaolo Bonzini * 8253018216SPaolo Bonzini * SLOF raw image loaded at 0, copies its romfs right below the flat 8353018216SPaolo Bonzini * device-tree, then position SLOF itself 31M below that 8453018216SPaolo Bonzini * 8553018216SPaolo Bonzini * So we set FW_OVERHEAD to 40MB which should account for all of that 8653018216SPaolo Bonzini * and more 8753018216SPaolo Bonzini * 8853018216SPaolo Bonzini * We load our kernel at 4M, leaving space for SLOF initial image 8953018216SPaolo Bonzini */ 9038b02bd8SAlexey Kardashevskiy #define FDT_MAX_SIZE 0x100000 9153018216SPaolo Bonzini #define RTAS_MAX_SIZE 0x10000 92b7d1f77aSBenjamin Herrenschmidt #define RTAS_MAX_ADDR 0x80000000 /* RTAS must stay below that */ 9353018216SPaolo Bonzini #define FW_MAX_SIZE 0x400000 9453018216SPaolo Bonzini #define FW_FILE_NAME "slof.bin" 9553018216SPaolo Bonzini #define FW_OVERHEAD 0x2800000 9653018216SPaolo Bonzini #define KERNEL_LOAD_ADDR FW_MAX_SIZE 9753018216SPaolo Bonzini 9853018216SPaolo Bonzini #define MIN_RMA_SLOF 128UL 9953018216SPaolo Bonzini 10053018216SPaolo Bonzini #define PHANDLE_XICP 0x00001111 10153018216SPaolo Bonzini 1025d0fb150SGreg Kurz /* These two functions implement the VCPU id numbering: one to compute them 1035d0fb150SGreg Kurz * all and one to identify thread 0 of a VCORE. Any change to the first one 1045d0fb150SGreg Kurz * is likely to have an impact on the second one, so let's keep them close. 1055d0fb150SGreg Kurz */ 1065d0fb150SGreg Kurz static int spapr_vcpu_id(sPAPRMachineState *spapr, int cpu_index) 1075d0fb150SGreg Kurz { 1081a5008fcSGreg Kurz assert(spapr->vsmt); 1095d0fb150SGreg Kurz return 1105d0fb150SGreg Kurz (cpu_index / smp_threads) * spapr->vsmt + cpu_index % smp_threads; 1115d0fb150SGreg Kurz } 1125d0fb150SGreg Kurz static bool spapr_is_thread0_in_vcore(sPAPRMachineState *spapr, 1135d0fb150SGreg Kurz PowerPCCPU *cpu) 1145d0fb150SGreg Kurz { 1151a5008fcSGreg Kurz assert(spapr->vsmt); 1165d0fb150SGreg Kurz return spapr_get_vcpu_id(cpu) % spapr->vsmt == 0; 1175d0fb150SGreg Kurz } 1185d0fb150SGreg Kurz 11971cd4dacSCédric Le Goater static ICSState *spapr_ics_create(sPAPRMachineState *spapr, 12071cd4dacSCédric Le Goater const char *type_ics, 121817bb6a4SCédric Le Goater int nr_irqs, Error **errp) 122c04d6cfaSAnthony Liguori { 123175d2aa0SGreg Kurz Error *local_err = NULL; 12471cd4dacSCédric Le Goater Object *obj; 125c04d6cfaSAnthony Liguori 12671cd4dacSCédric Le Goater obj = object_new(type_ics); 127175d2aa0SGreg Kurz object_property_add_child(OBJECT(spapr), "ics", obj, &error_abort); 128ad265631SGreg Kurz object_property_add_const_link(obj, ICS_PROP_XICS, OBJECT(spapr), 129ad265631SGreg Kurz &error_abort); 130175d2aa0SGreg Kurz object_property_set_int(obj, nr_irqs, "nr-irqs", &local_err); 131175d2aa0SGreg Kurz if (local_err) { 132175d2aa0SGreg Kurz goto error; 133175d2aa0SGreg Kurz } 13471cd4dacSCédric Le Goater object_property_set_bool(obj, true, "realized", &local_err); 135175d2aa0SGreg Kurz if (local_err) { 136175d2aa0SGreg Kurz goto error; 137c04d6cfaSAnthony Liguori } 138c04d6cfaSAnthony Liguori 13971cd4dacSCédric Le Goater return ICS_SIMPLE(obj); 140175d2aa0SGreg Kurz 141175d2aa0SGreg Kurz error: 142175d2aa0SGreg Kurz error_propagate(errp, local_err); 143175d2aa0SGreg Kurz return NULL; 1445bc8d26dSCédric Le Goater } 1455bc8d26dSCédric Le Goater 14646f7afa3SGreg Kurz static bool pre_2_10_vmstate_dummy_icp_needed(void *opaque) 14746f7afa3SGreg Kurz { 14846f7afa3SGreg Kurz /* Dummy entries correspond to unused ICPState objects in older QEMUs, 14946f7afa3SGreg Kurz * and newer QEMUs don't even have them. In both cases, we don't want 15046f7afa3SGreg Kurz * to send anything on the wire. 15146f7afa3SGreg Kurz */ 15246f7afa3SGreg Kurz return false; 15346f7afa3SGreg Kurz } 15446f7afa3SGreg Kurz 15546f7afa3SGreg Kurz static const VMStateDescription pre_2_10_vmstate_dummy_icp = { 15646f7afa3SGreg Kurz .name = "icp/server", 15746f7afa3SGreg Kurz .version_id = 1, 15846f7afa3SGreg Kurz .minimum_version_id = 1, 15946f7afa3SGreg Kurz .needed = pre_2_10_vmstate_dummy_icp_needed, 16046f7afa3SGreg Kurz .fields = (VMStateField[]) { 16146f7afa3SGreg Kurz VMSTATE_UNUSED(4), /* uint32_t xirr */ 16246f7afa3SGreg Kurz VMSTATE_UNUSED(1), /* uint8_t pending_priority */ 16346f7afa3SGreg Kurz VMSTATE_UNUSED(1), /* uint8_t mfrr */ 16446f7afa3SGreg Kurz VMSTATE_END_OF_LIST() 16546f7afa3SGreg Kurz }, 16646f7afa3SGreg Kurz }; 16746f7afa3SGreg Kurz 16846f7afa3SGreg Kurz static void pre_2_10_vmstate_register_dummy_icp(int i) 16946f7afa3SGreg Kurz { 17046f7afa3SGreg Kurz vmstate_register(NULL, i, &pre_2_10_vmstate_dummy_icp, 17146f7afa3SGreg Kurz (void *)(uintptr_t) i); 17246f7afa3SGreg Kurz } 17346f7afa3SGreg Kurz 17446f7afa3SGreg Kurz static void pre_2_10_vmstate_unregister_dummy_icp(int i) 17546f7afa3SGreg Kurz { 17646f7afa3SGreg Kurz vmstate_unregister(NULL, &pre_2_10_vmstate_dummy_icp, 17746f7afa3SGreg Kurz (void *)(uintptr_t) i); 17846f7afa3SGreg Kurz } 17946f7afa3SGreg Kurz 18072194664SGreg Kurz static int xics_max_server_number(sPAPRMachineState *spapr) 18146f7afa3SGreg Kurz { 1821a5008fcSGreg Kurz assert(spapr->vsmt); 18372194664SGreg Kurz return DIV_ROUND_UP(max_cpus * spapr->vsmt, smp_threads); 18446f7afa3SGreg Kurz } 18546f7afa3SGreg Kurz 18671cd4dacSCédric Le Goater static void xics_system_init(MachineState *machine, int nr_irqs, Error **errp) 187c04d6cfaSAnthony Liguori { 18871cd4dacSCédric Le Goater sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 189c04d6cfaSAnthony Liguori 19011ad93f6SDavid Gibson if (kvm_enabled()) { 1912192a930SCédric Le Goater if (machine_kernel_irqchip_allowed(machine) && 19271cd4dacSCédric Le Goater !xics_kvm_init(spapr, errp)) { 19371cd4dacSCédric Le Goater spapr->icp_type = TYPE_KVM_ICP; 1943d85885aSGreg Kurz spapr->ics = spapr_ics_create(spapr, TYPE_ICS_KVM, nr_irqs, errp); 19511ad93f6SDavid Gibson } 19671cd4dacSCédric Le Goater if (machine_kernel_irqchip_required(machine) && !spapr->ics) { 1973d85885aSGreg Kurz error_prepend(errp, "kernel_irqchip requested but unavailable: "); 1983d85885aSGreg Kurz return; 19911ad93f6SDavid Gibson } 200b83baa60SMarkus Armbruster } 20111ad93f6SDavid Gibson 20271cd4dacSCédric Le Goater if (!spapr->ics) { 203f63ebfe0SGreg Kurz xics_spapr_init(spapr); 20471cd4dacSCédric Le Goater spapr->icp_type = TYPE_ICP; 20571cd4dacSCédric Le Goater spapr->ics = spapr_ics_create(spapr, TYPE_ICS_SIMPLE, nr_irqs, errp); 2063d85885aSGreg Kurz if (!spapr->ics) { 2073d85885aSGreg Kurz return; 2083d85885aSGreg Kurz } 209c04d6cfaSAnthony Liguori } 210c04d6cfaSAnthony Liguori } 211c04d6cfaSAnthony Liguori 212833d4668SAlexey Kardashevskiy static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, 213833d4668SAlexey Kardashevskiy int smt_threads) 214833d4668SAlexey Kardashevskiy { 215833d4668SAlexey Kardashevskiy int i, ret = 0; 216833d4668SAlexey Kardashevskiy uint32_t servers_prop[smt_threads]; 217833d4668SAlexey Kardashevskiy uint32_t gservers_prop[smt_threads * 2]; 21814bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 219833d4668SAlexey Kardashevskiy 220d6e166c0SDavid Gibson if (cpu->compat_pvr) { 221d6e166c0SDavid Gibson ret = fdt_setprop_cell(fdt, offset, "cpu-version", cpu->compat_pvr); 2226d9412eaSAlexey Kardashevskiy if (ret < 0) { 2236d9412eaSAlexey Kardashevskiy return ret; 2246d9412eaSAlexey Kardashevskiy } 2256d9412eaSAlexey Kardashevskiy } 2266d9412eaSAlexey Kardashevskiy 227833d4668SAlexey Kardashevskiy /* Build interrupt servers and gservers properties */ 228833d4668SAlexey Kardashevskiy for (i = 0; i < smt_threads; i++) { 229833d4668SAlexey Kardashevskiy servers_prop[i] = cpu_to_be32(index + i); 230833d4668SAlexey Kardashevskiy /* Hack, direct the group queues back to cpu 0 */ 231833d4668SAlexey Kardashevskiy gservers_prop[i*2] = cpu_to_be32(index + i); 232833d4668SAlexey Kardashevskiy gservers_prop[i*2 + 1] = 0; 233833d4668SAlexey Kardashevskiy } 234833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 235833d4668SAlexey Kardashevskiy servers_prop, sizeof(servers_prop)); 236833d4668SAlexey Kardashevskiy if (ret < 0) { 237833d4668SAlexey Kardashevskiy return ret; 238833d4668SAlexey Kardashevskiy } 239833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-gserver#s", 240833d4668SAlexey Kardashevskiy gservers_prop, sizeof(gservers_prop)); 241833d4668SAlexey Kardashevskiy 242833d4668SAlexey Kardashevskiy return ret; 243833d4668SAlexey Kardashevskiy } 244833d4668SAlexey Kardashevskiy 24599861ecbSIgor Mammedov static int spapr_fixup_cpu_numa_dt(void *fdt, int offset, PowerPCCPU *cpu) 2460da6f3feSBharata B Rao { 24714bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 2480da6f3feSBharata B Rao uint32_t associativity[] = {cpu_to_be32(0x5), 2490da6f3feSBharata B Rao cpu_to_be32(0x0), 2500da6f3feSBharata B Rao cpu_to_be32(0x0), 2510da6f3feSBharata B Rao cpu_to_be32(0x0), 25215f8b142SIgor Mammedov cpu_to_be32(cpu->node_id), 2530da6f3feSBharata B Rao cpu_to_be32(index)}; 2540da6f3feSBharata B Rao 2550da6f3feSBharata B Rao /* Advertise NUMA via ibm,associativity */ 25699861ecbSIgor Mammedov return fdt_setprop(fdt, offset, "ibm,associativity", associativity, 2570da6f3feSBharata B Rao sizeof(associativity)); 2580da6f3feSBharata B Rao } 2590da6f3feSBharata B Rao 26086d5771aSSam Bobroff /* Populate the "ibm,pa-features" property */ 261ee76a09fSDavid Gibson static void spapr_populate_pa_features(sPAPRMachineState *spapr, 262ee76a09fSDavid Gibson PowerPCCPU *cpu, 263ee76a09fSDavid Gibson void *fdt, int offset, 264e957f6a9SSam Bobroff bool legacy_guest) 26586d5771aSSam Bobroff { 2667abd43baSSuraj Jitindar Singh CPUPPCState *env = &cpu->env; 26786d5771aSSam Bobroff uint8_t pa_features_206[] = { 6, 0, 26886d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 }; 26986d5771aSSam Bobroff uint8_t pa_features_207[] = { 24, 0, 27086d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, 27186d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 27286d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 27386d5771aSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 }; 2749fb4541fSSam Bobroff uint8_t pa_features_300[] = { 66, 0, 2759fb4541fSSam Bobroff /* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */ 2769fb4541fSSam Bobroff /* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, SSO, 5: LE|CFAR|EB|LSQ */ 27786d5771aSSam Bobroff 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, /* 0 - 5 */ 2789fb4541fSSam Bobroff /* 6: DS207 */ 27986d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */ 2809fb4541fSSam Bobroff /* 16: Vector */ 28186d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */ 2829fb4541fSSam Bobroff /* 18: Vec. Scalar, 20: Vec. XOR, 22: HTM */ 2839bf502feSDavid Gibson 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */ 2849fb4541fSSam Bobroff /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */ 2859fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */ 2869fb4541fSSam Bobroff /* 30: MMR, 32: LE atomic, 34: EBB + ext EBB */ 2879fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */ 2889fb4541fSSam Bobroff /* 36: SPR SO, 38: Copy/Paste, 40: Radix MMU */ 2899fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 36 - 41 */ 2909fb4541fSSam Bobroff /* 42: PM, 44: PC RA, 46: SC vec'd */ 2919fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */ 2929fb4541fSSam Bobroff /* 48: SIMD, 50: QP BFP, 52: String */ 2939fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */ 2949fb4541fSSam Bobroff /* 54: DecFP, 56: DecI, 58: SHA */ 2959fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */ 2969fb4541fSSam Bobroff /* 60: NM atomic, 62: RNG */ 2979fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */ 2989fb4541fSSam Bobroff }; 2997abd43baSSuraj Jitindar Singh uint8_t *pa_features = NULL; 30086d5771aSSam Bobroff size_t pa_size; 30186d5771aSSam Bobroff 3027abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06, 0, cpu->compat_pvr)) { 30386d5771aSSam Bobroff pa_features = pa_features_206; 30486d5771aSSam Bobroff pa_size = sizeof(pa_features_206); 3057abd43baSSuraj Jitindar Singh } 3067abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07, 0, cpu->compat_pvr)) { 30786d5771aSSam Bobroff pa_features = pa_features_207; 30886d5771aSSam Bobroff pa_size = sizeof(pa_features_207); 3097abd43baSSuraj Jitindar Singh } 3107abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0, cpu->compat_pvr)) { 31186d5771aSSam Bobroff pa_features = pa_features_300; 31286d5771aSSam Bobroff pa_size = sizeof(pa_features_300); 3137abd43baSSuraj Jitindar Singh } 3147abd43baSSuraj Jitindar Singh if (!pa_features) { 31586d5771aSSam Bobroff return; 31686d5771aSSam Bobroff } 31786d5771aSSam Bobroff 31886d5771aSSam Bobroff if (env->ci_large_pages) { 31986d5771aSSam Bobroff /* 32086d5771aSSam Bobroff * Note: we keep CI large pages off by default because a 64K capable 32186d5771aSSam Bobroff * guest provisioned with large pages might otherwise try to map a qemu 32286d5771aSSam Bobroff * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages 32386d5771aSSam Bobroff * even if that qemu runs on a 4k host. 32486d5771aSSam Bobroff * We dd this bit back here if we are confident this is not an issue 32586d5771aSSam Bobroff */ 32686d5771aSSam Bobroff pa_features[3] |= 0x20; 32786d5771aSSam Bobroff } 3284e5fe368SSuraj Jitindar Singh if ((spapr_get_cap(spapr, SPAPR_CAP_HTM) != 0) && pa_size > 24) { 32986d5771aSSam Bobroff pa_features[24] |= 0x80; /* Transactional memory support */ 33086d5771aSSam Bobroff } 331e957f6a9SSam Bobroff if (legacy_guest && pa_size > 40) { 332e957f6a9SSam Bobroff /* Workaround for broken kernels that attempt (guest) radix 333e957f6a9SSam Bobroff * mode when they can't handle it, if they see the radix bit set 334e957f6a9SSam Bobroff * in pa-features. So hide it from them. */ 335e957f6a9SSam Bobroff pa_features[40 + 2] &= ~0x80; /* Radix MMU */ 336e957f6a9SSam Bobroff } 33786d5771aSSam Bobroff 33886d5771aSSam Bobroff _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size))); 33986d5771aSSam Bobroff } 34086d5771aSSam Bobroff 34128e02042SDavid Gibson static int spapr_fixup_cpu_dt(void *fdt, sPAPRMachineState *spapr) 34253018216SPaolo Bonzini { 34382677ed2SAlexey Kardashevskiy int ret = 0, offset, cpus_offset; 34482677ed2SAlexey Kardashevskiy CPUState *cs; 34553018216SPaolo Bonzini char cpu_model[32]; 34653018216SPaolo Bonzini uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 34753018216SPaolo Bonzini 34882677ed2SAlexey Kardashevskiy CPU_FOREACH(cs) { 34982677ed2SAlexey Kardashevskiy PowerPCCPU *cpu = POWERPC_CPU(cs); 35082677ed2SAlexey Kardashevskiy DeviceClass *dc = DEVICE_GET_CLASS(cs); 35114bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 352abbc1247SDavid Gibson int compat_smt = MIN(smp_threads, ppc_compat_max_vthreads(cpu)); 35353018216SPaolo Bonzini 3545d0fb150SGreg Kurz if (!spapr_is_thread0_in_vcore(spapr, cpu)) { 35553018216SPaolo Bonzini continue; 35653018216SPaolo Bonzini } 35753018216SPaolo Bonzini 35882677ed2SAlexey Kardashevskiy snprintf(cpu_model, 32, "%s@%x", dc->fw_name, index); 35953018216SPaolo Bonzini 36082677ed2SAlexey Kardashevskiy cpus_offset = fdt_path_offset(fdt, "/cpus"); 36182677ed2SAlexey Kardashevskiy if (cpus_offset < 0) { 362a4f3885cSGreg Kurz cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 36382677ed2SAlexey Kardashevskiy if (cpus_offset < 0) { 36482677ed2SAlexey Kardashevskiy return cpus_offset; 36582677ed2SAlexey Kardashevskiy } 36682677ed2SAlexey Kardashevskiy } 36782677ed2SAlexey Kardashevskiy offset = fdt_subnode_offset(fdt, cpus_offset, cpu_model); 36882677ed2SAlexey Kardashevskiy if (offset < 0) { 36982677ed2SAlexey Kardashevskiy offset = fdt_add_subnode(fdt, cpus_offset, cpu_model); 37053018216SPaolo Bonzini if (offset < 0) { 37153018216SPaolo Bonzini return offset; 37253018216SPaolo Bonzini } 37382677ed2SAlexey Kardashevskiy } 37453018216SPaolo Bonzini 3750da6f3feSBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,pft-size", 3760da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)); 37753018216SPaolo Bonzini if (ret < 0) { 37853018216SPaolo Bonzini return ret; 37953018216SPaolo Bonzini } 38053018216SPaolo Bonzini 38199861ecbSIgor Mammedov if (nb_numa_nodes > 1) { 38299861ecbSIgor Mammedov ret = spapr_fixup_cpu_numa_dt(fdt, offset, cpu); 38353018216SPaolo Bonzini if (ret < 0) { 38453018216SPaolo Bonzini return ret; 38553018216SPaolo Bonzini } 38699861ecbSIgor Mammedov } 387833d4668SAlexey Kardashevskiy 38812dbeb16SDavid Gibson ret = spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt); 389833d4668SAlexey Kardashevskiy if (ret < 0) { 390833d4668SAlexey Kardashevskiy return ret; 391833d4668SAlexey Kardashevskiy } 392e957f6a9SSam Bobroff 393ee76a09fSDavid Gibson spapr_populate_pa_features(spapr, cpu, fdt, offset, 394e957f6a9SSam Bobroff spapr->cas_legacy_guest_workaround); 39553018216SPaolo Bonzini } 39653018216SPaolo Bonzini return ret; 39753018216SPaolo Bonzini } 39853018216SPaolo Bonzini 399c86c1affSDaniel Henrique Barboza static hwaddr spapr_node0_size(MachineState *machine) 400b082d65aSAlexey Kardashevskiy { 401b082d65aSAlexey Kardashevskiy if (nb_numa_nodes) { 402b082d65aSAlexey Kardashevskiy int i; 403b082d65aSAlexey Kardashevskiy for (i = 0; i < nb_numa_nodes; ++i) { 404b082d65aSAlexey Kardashevskiy if (numa_info[i].node_mem) { 405fb164994SDavid Gibson return MIN(pow2floor(numa_info[i].node_mem), 406fb164994SDavid Gibson machine->ram_size); 407b082d65aSAlexey Kardashevskiy } 408b082d65aSAlexey Kardashevskiy } 409b082d65aSAlexey Kardashevskiy } 410fb164994SDavid Gibson return machine->ram_size; 411b082d65aSAlexey Kardashevskiy } 412b082d65aSAlexey Kardashevskiy 413a1d59c0fSAlexey Kardashevskiy static void add_str(GString *s, const gchar *s1) 414a1d59c0fSAlexey Kardashevskiy { 415a1d59c0fSAlexey Kardashevskiy g_string_append_len(s, s1, strlen(s1) + 1); 416a1d59c0fSAlexey Kardashevskiy } 41753018216SPaolo Bonzini 41803d196b7SBharata B Rao static int spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start, 41926a8c353SAlexey Kardashevskiy hwaddr size) 42026a8c353SAlexey Kardashevskiy { 42126a8c353SAlexey Kardashevskiy uint32_t associativity[] = { 42226a8c353SAlexey Kardashevskiy cpu_to_be32(0x4), /* length */ 42326a8c353SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(0x0), 424c3b4f589SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(nodeid) 42526a8c353SAlexey Kardashevskiy }; 42626a8c353SAlexey Kardashevskiy char mem_name[32]; 42726a8c353SAlexey Kardashevskiy uint64_t mem_reg_property[2]; 42826a8c353SAlexey Kardashevskiy int off; 42926a8c353SAlexey Kardashevskiy 43026a8c353SAlexey Kardashevskiy mem_reg_property[0] = cpu_to_be64(start); 43126a8c353SAlexey Kardashevskiy mem_reg_property[1] = cpu_to_be64(size); 43226a8c353SAlexey Kardashevskiy 43326a8c353SAlexey Kardashevskiy sprintf(mem_name, "memory@" TARGET_FMT_lx, start); 43426a8c353SAlexey Kardashevskiy off = fdt_add_subnode(fdt, 0, mem_name); 43526a8c353SAlexey Kardashevskiy _FDT(off); 43626a8c353SAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 43726a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 43826a8c353SAlexey Kardashevskiy sizeof(mem_reg_property)))); 43926a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity, 44026a8c353SAlexey Kardashevskiy sizeof(associativity)))); 44103d196b7SBharata B Rao return off; 44226a8c353SAlexey Kardashevskiy } 44326a8c353SAlexey Kardashevskiy 44428e02042SDavid Gibson static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt) 44553018216SPaolo Bonzini { 446fb164994SDavid Gibson MachineState *machine = MACHINE(spapr); 4477db8a127SAlexey Kardashevskiy hwaddr mem_start, node_size; 4487db8a127SAlexey Kardashevskiy int i, nb_nodes = nb_numa_nodes; 4497db8a127SAlexey Kardashevskiy NodeInfo *nodes = numa_info; 4507db8a127SAlexey Kardashevskiy NodeInfo ramnode; 45153018216SPaolo Bonzini 4527db8a127SAlexey Kardashevskiy /* No NUMA nodes, assume there is just one node with whole RAM */ 4537db8a127SAlexey Kardashevskiy if (!nb_numa_nodes) { 4547db8a127SAlexey Kardashevskiy nb_nodes = 1; 455fb164994SDavid Gibson ramnode.node_mem = machine->ram_size; 4567db8a127SAlexey Kardashevskiy nodes = &ramnode; 4575fe269b1SPaul Mackerras } 45853018216SPaolo Bonzini 4597db8a127SAlexey Kardashevskiy for (i = 0, mem_start = 0; i < nb_nodes; ++i) { 4607db8a127SAlexey Kardashevskiy if (!nodes[i].node_mem) { 4617db8a127SAlexey Kardashevskiy continue; 46253018216SPaolo Bonzini } 463fb164994SDavid Gibson if (mem_start >= machine->ram_size) { 4645fe269b1SPaul Mackerras node_size = 0; 4655fe269b1SPaul Mackerras } else { 4667db8a127SAlexey Kardashevskiy node_size = nodes[i].node_mem; 467fb164994SDavid Gibson if (node_size > machine->ram_size - mem_start) { 468fb164994SDavid Gibson node_size = machine->ram_size - mem_start; 4695fe269b1SPaul Mackerras } 4705fe269b1SPaul Mackerras } 4717db8a127SAlexey Kardashevskiy if (!mem_start) { 472b472b1a7SDaniel Henrique Barboza /* spapr_machine_init() checks for rma_size <= node0_size 473b472b1a7SDaniel Henrique Barboza * already */ 474e8f986fcSBharata B Rao spapr_populate_memory_node(fdt, i, 0, spapr->rma_size); 4757db8a127SAlexey Kardashevskiy mem_start += spapr->rma_size; 4767db8a127SAlexey Kardashevskiy node_size -= spapr->rma_size; 4777db8a127SAlexey Kardashevskiy } 4786010818cSAlexey Kardashevskiy for ( ; node_size; ) { 4796010818cSAlexey Kardashevskiy hwaddr sizetmp = pow2floor(node_size); 4806010818cSAlexey Kardashevskiy 4816010818cSAlexey Kardashevskiy /* mem_start != 0 here */ 4826010818cSAlexey Kardashevskiy if (ctzl(mem_start) < ctzl(sizetmp)) { 4836010818cSAlexey Kardashevskiy sizetmp = 1ULL << ctzl(mem_start); 4846010818cSAlexey Kardashevskiy } 4856010818cSAlexey Kardashevskiy 4866010818cSAlexey Kardashevskiy spapr_populate_memory_node(fdt, i, mem_start, sizetmp); 4876010818cSAlexey Kardashevskiy node_size -= sizetmp; 4886010818cSAlexey Kardashevskiy mem_start += sizetmp; 4896010818cSAlexey Kardashevskiy } 49053018216SPaolo Bonzini } 49153018216SPaolo Bonzini 49253018216SPaolo Bonzini return 0; 49353018216SPaolo Bonzini } 49453018216SPaolo Bonzini 4950da6f3feSBharata B Rao static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, 4960da6f3feSBharata B Rao sPAPRMachineState *spapr) 4970da6f3feSBharata B Rao { 4980da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 4990da6f3feSBharata B Rao CPUPPCState *env = &cpu->env; 5000da6f3feSBharata B Rao PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 50114bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 5020da6f3feSBharata B Rao uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 5030da6f3feSBharata B Rao 0xffffffff, 0xffffffff}; 504afd10a0fSBharata B Rao uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() 505afd10a0fSBharata B Rao : SPAPR_TIMEBASE_FREQ; 5060da6f3feSBharata B Rao uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; 5070da6f3feSBharata B Rao uint32_t page_sizes_prop[64]; 5080da6f3feSBharata B Rao size_t page_sizes_prop_size; 50922419c2aSDavid Gibson uint32_t vcpus_per_socket = smp_threads * smp_cores; 5100da6f3feSBharata B Rao uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 511abbc1247SDavid Gibson int compat_smt = MIN(smp_threads, ppc_compat_max_vthreads(cpu)); 512af81cf32SBharata B Rao sPAPRDRConnector *drc; 513af81cf32SBharata B Rao int drc_index; 514c64abd1fSSam Bobroff uint32_t radix_AP_encodings[PPC_PAGE_SIZES_MAX_SZ]; 515c64abd1fSSam Bobroff int i; 516af81cf32SBharata B Rao 517fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index); 518af81cf32SBharata B Rao if (drc) { 5190b55aa91SDavid Gibson drc_index = spapr_drc_index(drc); 520af81cf32SBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index))); 521af81cf32SBharata B Rao } 5220da6f3feSBharata B Rao 5230da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); 5240da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 5250da6f3feSBharata B Rao 5260da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 5270da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 5280da6f3feSBharata B Rao env->dcache_line_size))); 5290da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 5300da6f3feSBharata B Rao env->dcache_line_size))); 5310da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 5320da6f3feSBharata B Rao env->icache_line_size))); 5330da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 5340da6f3feSBharata B Rao env->icache_line_size))); 5350da6f3feSBharata B Rao 5360da6f3feSBharata B Rao if (pcc->l1_dcache_size) { 5370da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 5380da6f3feSBharata B Rao pcc->l1_dcache_size))); 5390da6f3feSBharata B Rao } else { 5403dc6f869SAlistair Francis warn_report("Unknown L1 dcache size for cpu"); 5410da6f3feSBharata B Rao } 5420da6f3feSBharata B Rao if (pcc->l1_icache_size) { 5430da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 5440da6f3feSBharata B Rao pcc->l1_icache_size))); 5450da6f3feSBharata B Rao } else { 5463dc6f869SAlistair Francis warn_report("Unknown L1 icache size for cpu"); 5470da6f3feSBharata B Rao } 5480da6f3feSBharata B Rao 5490da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 5500da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 551fd5da5c4SThomas Huth _FDT((fdt_setprop_cell(fdt, offset, "slb-size", env->slb_nr))); 5520da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", env->slb_nr))); 5530da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 5540da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 5550da6f3feSBharata B Rao 5560da6f3feSBharata B Rao if (env->spr_cb[SPR_PURR].oea_read) { 5570da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 5580da6f3feSBharata B Rao } 5590da6f3feSBharata B Rao 5600da6f3feSBharata B Rao if (env->mmu_model & POWERPC_MMU_1TSEG) { 5610da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 5620da6f3feSBharata B Rao segs, sizeof(segs)))); 5630da6f3feSBharata B Rao } 5640da6f3feSBharata B Rao 56529386642SDavid Gibson /* Advertise VSX (vector extensions) if available 5660da6f3feSBharata B Rao * 1 == VMX / Altivec available 56729386642SDavid Gibson * 2 == VSX available 56829386642SDavid Gibson * 56929386642SDavid Gibson * Only CPUs for which we create core types in spapr_cpu_core.c 57029386642SDavid Gibson * are possible, and all of those have VMX */ 5714e5fe368SSuraj Jitindar Singh if (spapr_get_cap(spapr, SPAPR_CAP_VSX) != 0) { 57229386642SDavid Gibson _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2))); 57329386642SDavid Gibson } else { 57429386642SDavid Gibson _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1))); 5750da6f3feSBharata B Rao } 5760da6f3feSBharata B Rao 5770da6f3feSBharata B Rao /* Advertise DFP (Decimal Floating Point) if available 5780da6f3feSBharata B Rao * 0 / no property == no DFP 5790da6f3feSBharata B Rao * 1 == DFP available */ 5804e5fe368SSuraj Jitindar Singh if (spapr_get_cap(spapr, SPAPR_CAP_DFP) != 0) { 5810da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 5820da6f3feSBharata B Rao } 5830da6f3feSBharata B Rao 5843654fa95SCédric Le Goater page_sizes_prop_size = ppc_create_page_sizes_prop(env, page_sizes_prop, 5850da6f3feSBharata B Rao sizeof(page_sizes_prop)); 5860da6f3feSBharata B Rao if (page_sizes_prop_size) { 5870da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 5880da6f3feSBharata B Rao page_sizes_prop, page_sizes_prop_size))); 5890da6f3feSBharata B Rao } 5900da6f3feSBharata B Rao 591ee76a09fSDavid Gibson spapr_populate_pa_features(spapr, cpu, fdt, offset, false); 59290da0d5aSBenjamin Herrenschmidt 5930da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", 59422419c2aSDavid Gibson cs->cpu_index / vcpus_per_socket))); 5950da6f3feSBharata B Rao 5960da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", 5970da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)))); 5980da6f3feSBharata B Rao 59999861ecbSIgor Mammedov if (nb_numa_nodes > 1) { 60099861ecbSIgor Mammedov _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cpu)); 60199861ecbSIgor Mammedov } 6020da6f3feSBharata B Rao 60312dbeb16SDavid Gibson _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt)); 604c64abd1fSSam Bobroff 605c64abd1fSSam Bobroff if (pcc->radix_page_info) { 606c64abd1fSSam Bobroff for (i = 0; i < pcc->radix_page_info->count; i++) { 607c64abd1fSSam Bobroff radix_AP_encodings[i] = 608c64abd1fSSam Bobroff cpu_to_be32(pcc->radix_page_info->entries[i]); 609c64abd1fSSam Bobroff } 610c64abd1fSSam Bobroff _FDT((fdt_setprop(fdt, offset, "ibm,processor-radix-AP-encodings", 611c64abd1fSSam Bobroff radix_AP_encodings, 612c64abd1fSSam Bobroff pcc->radix_page_info->count * 613c64abd1fSSam Bobroff sizeof(radix_AP_encodings[0])))); 614c64abd1fSSam Bobroff } 6150da6f3feSBharata B Rao } 6160da6f3feSBharata B Rao 6170da6f3feSBharata B Rao static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr) 6180da6f3feSBharata B Rao { 6190da6f3feSBharata B Rao CPUState *cs; 6200da6f3feSBharata B Rao int cpus_offset; 6210da6f3feSBharata B Rao char *nodename; 6220da6f3feSBharata B Rao 6230da6f3feSBharata B Rao cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 6240da6f3feSBharata B Rao _FDT(cpus_offset); 6250da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 6260da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 6270da6f3feSBharata B Rao 6280da6f3feSBharata B Rao /* 6290da6f3feSBharata B Rao * We walk the CPUs in reverse order to ensure that CPU DT nodes 6300da6f3feSBharata B Rao * created by fdt_add_subnode() end up in the right order in FDT 6310da6f3feSBharata B Rao * for the guest kernel the enumerate the CPUs correctly. 6320da6f3feSBharata B Rao */ 6330da6f3feSBharata B Rao CPU_FOREACH_REVERSE(cs) { 6340da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 63514bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu); 6360da6f3feSBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 6370da6f3feSBharata B Rao int offset; 6380da6f3feSBharata B Rao 6395d0fb150SGreg Kurz if (!spapr_is_thread0_in_vcore(spapr, cpu)) { 6400da6f3feSBharata B Rao continue; 6410da6f3feSBharata B Rao } 6420da6f3feSBharata B Rao 6430da6f3feSBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, index); 6440da6f3feSBharata B Rao offset = fdt_add_subnode(fdt, cpus_offset, nodename); 6450da6f3feSBharata B Rao g_free(nodename); 6460da6f3feSBharata B Rao _FDT(offset); 6470da6f3feSBharata B Rao spapr_populate_cpu_dt(cs, fdt, offset, spapr); 6480da6f3feSBharata B Rao } 6490da6f3feSBharata B Rao 6500da6f3feSBharata B Rao } 6510da6f3feSBharata B Rao 652f47bd1c8SIgor Mammedov static uint32_t spapr_pc_dimm_node(MemoryDeviceInfoList *list, ram_addr_t addr) 653f47bd1c8SIgor Mammedov { 654f47bd1c8SIgor Mammedov MemoryDeviceInfoList *info; 655f47bd1c8SIgor Mammedov 656f47bd1c8SIgor Mammedov for (info = list; info; info = info->next) { 657f47bd1c8SIgor Mammedov MemoryDeviceInfo *value = info->value; 658f47bd1c8SIgor Mammedov 659f47bd1c8SIgor Mammedov if (value && value->type == MEMORY_DEVICE_INFO_KIND_DIMM) { 660f47bd1c8SIgor Mammedov PCDIMMDeviceInfo *pcdimm_info = value->u.dimm.data; 661f47bd1c8SIgor Mammedov 662f47bd1c8SIgor Mammedov if (pcdimm_info->addr >= addr && 663f47bd1c8SIgor Mammedov addr < (pcdimm_info->addr + pcdimm_info->size)) { 664f47bd1c8SIgor Mammedov return pcdimm_info->node; 665f47bd1c8SIgor Mammedov } 666f47bd1c8SIgor Mammedov } 667f47bd1c8SIgor Mammedov } 668f47bd1c8SIgor Mammedov 669f47bd1c8SIgor Mammedov return -1; 670f47bd1c8SIgor Mammedov } 671f47bd1c8SIgor Mammedov 67203d196b7SBharata B Rao /* 67303d196b7SBharata B Rao * Adds ibm,dynamic-reconfiguration-memory node. 67403d196b7SBharata B Rao * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation 67503d196b7SBharata B Rao * of this device tree node. 67603d196b7SBharata B Rao */ 67703d196b7SBharata B Rao static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) 67803d196b7SBharata B Rao { 67903d196b7SBharata B Rao MachineState *machine = MACHINE(spapr); 68003d196b7SBharata B Rao int ret, i, offset; 68103d196b7SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 68203d196b7SBharata B Rao uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; 683d0e5a8f2SBharata B Rao uint32_t hotplug_lmb_start = spapr->hotplug_memory.base / lmb_size; 684d0e5a8f2SBharata B Rao uint32_t nr_lmbs = (spapr->hotplug_memory.base + 685d0e5a8f2SBharata B Rao memory_region_size(&spapr->hotplug_memory.mr)) / 686d0e5a8f2SBharata B Rao lmb_size; 68703d196b7SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 6886663864eSBharata B Rao int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; 689f47bd1c8SIgor Mammedov MemoryDeviceInfoList *dimms = NULL; 69003d196b7SBharata B Rao 691ef001f06SThomas Huth /* 692d0e5a8f2SBharata B Rao * Don't create the node if there is no hotpluggable memory 69316c25aefSBharata B Rao */ 694d0e5a8f2SBharata B Rao if (machine->ram_size == machine->maxram_size) { 69516c25aefSBharata B Rao return 0; 69616c25aefSBharata B Rao } 69716c25aefSBharata B Rao 69816c25aefSBharata B Rao /* 699ef001f06SThomas Huth * Allocate enough buffer size to fit in ibm,dynamic-memory 700ef001f06SThomas Huth * or ibm,associativity-lookup-arrays 701ef001f06SThomas Huth */ 702ef001f06SThomas Huth buf_len = MAX(nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1, nr_nodes * 4 + 2) 703ef001f06SThomas Huth * sizeof(uint32_t); 70403d196b7SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 70503d196b7SBharata B Rao 70603d196b7SBharata B Rao offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory"); 70703d196b7SBharata B Rao 70803d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size, 70903d196b7SBharata B Rao sizeof(prop_lmb_size)); 71003d196b7SBharata B Rao if (ret < 0) { 71103d196b7SBharata B Rao goto out; 71203d196b7SBharata B Rao } 71303d196b7SBharata B Rao 71403d196b7SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff); 71503d196b7SBharata B Rao if (ret < 0) { 71603d196b7SBharata B Rao goto out; 71703d196b7SBharata B Rao } 71803d196b7SBharata B Rao 71903d196b7SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0); 72003d196b7SBharata B Rao if (ret < 0) { 72103d196b7SBharata B Rao goto out; 72203d196b7SBharata B Rao } 72303d196b7SBharata B Rao 724f47bd1c8SIgor Mammedov if (hotplug_lmb_start) { 72552c95caeSHaozhong Zhang dimms = qmp_pc_dimm_device_list(); 726f47bd1c8SIgor Mammedov } 727f47bd1c8SIgor Mammedov 72803d196b7SBharata B Rao /* ibm,dynamic-memory */ 72903d196b7SBharata B Rao int_buf[0] = cpu_to_be32(nr_lmbs); 73003d196b7SBharata B Rao cur_index++; 73103d196b7SBharata B Rao for (i = 0; i < nr_lmbs; i++) { 732d0e5a8f2SBharata B Rao uint64_t addr = i * lmb_size; 73303d196b7SBharata B Rao uint32_t *dynamic_memory = cur_index; 73403d196b7SBharata B Rao 735d0e5a8f2SBharata B Rao if (i >= hotplug_lmb_start) { 736d0e5a8f2SBharata B Rao sPAPRDRConnector *drc; 737d0e5a8f2SBharata B Rao 738fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, i); 73903d196b7SBharata B Rao g_assert(drc); 74003d196b7SBharata B Rao 74103d196b7SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 74203d196b7SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 7430b55aa91SDavid Gibson dynamic_memory[2] = cpu_to_be32(spapr_drc_index(drc)); 74403d196b7SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 745f47bd1c8SIgor Mammedov dynamic_memory[4] = cpu_to_be32(spapr_pc_dimm_node(dimms, addr)); 746d0e5a8f2SBharata B Rao if (memory_region_present(get_system_memory(), addr)) { 74703d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); 74803d196b7SBharata B Rao } else { 74903d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(0); 75003d196b7SBharata B Rao } 751d0e5a8f2SBharata B Rao } else { 752d0e5a8f2SBharata B Rao /* 753d0e5a8f2SBharata B Rao * LMB information for RMA, boot time RAM and gap b/n RAM and 754d0e5a8f2SBharata B Rao * hotplug memory region -- all these are marked as reserved 755d0e5a8f2SBharata B Rao * and as having no valid DRC. 756d0e5a8f2SBharata B Rao */ 757d0e5a8f2SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 758d0e5a8f2SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 759d0e5a8f2SBharata B Rao dynamic_memory[2] = cpu_to_be32(0); 760d0e5a8f2SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 761d0e5a8f2SBharata B Rao dynamic_memory[4] = cpu_to_be32(-1); 762d0e5a8f2SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED | 763d0e5a8f2SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 764d0e5a8f2SBharata B Rao } 76503d196b7SBharata B Rao 76603d196b7SBharata B Rao cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; 76703d196b7SBharata B Rao } 768f47bd1c8SIgor Mammedov qapi_free_MemoryDeviceInfoList(dimms); 76903d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len); 77003d196b7SBharata B Rao if (ret < 0) { 77103d196b7SBharata B Rao goto out; 77203d196b7SBharata B Rao } 77303d196b7SBharata B Rao 77403d196b7SBharata B Rao /* ibm,associativity-lookup-arrays */ 77503d196b7SBharata B Rao cur_index = int_buf; 7766663864eSBharata B Rao int_buf[0] = cpu_to_be32(nr_nodes); 77703d196b7SBharata B Rao int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */ 77803d196b7SBharata B Rao cur_index += 2; 7796663864eSBharata B Rao for (i = 0; i < nr_nodes; i++) { 78003d196b7SBharata B Rao uint32_t associativity[] = { 78103d196b7SBharata B Rao cpu_to_be32(0x0), 78203d196b7SBharata B Rao cpu_to_be32(0x0), 78303d196b7SBharata B Rao cpu_to_be32(0x0), 78403d196b7SBharata B Rao cpu_to_be32(i) 78503d196b7SBharata B Rao }; 78603d196b7SBharata B Rao memcpy(cur_index, associativity, sizeof(associativity)); 78703d196b7SBharata B Rao cur_index += 4; 78803d196b7SBharata B Rao } 78903d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf, 79003d196b7SBharata B Rao (cur_index - int_buf) * sizeof(uint32_t)); 79103d196b7SBharata B Rao out: 79203d196b7SBharata B Rao g_free(int_buf); 79303d196b7SBharata B Rao return ret; 79403d196b7SBharata B Rao } 79503d196b7SBharata B Rao 7966787d27bSMichael Roth static int spapr_dt_cas_updates(sPAPRMachineState *spapr, void *fdt, 7976787d27bSMichael Roth sPAPROptionVector *ov5_updates) 7986787d27bSMichael Roth { 7996787d27bSMichael Roth sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 800417ece33SMichael Roth int ret = 0, offset; 8016787d27bSMichael Roth 8026787d27bSMichael Roth /* Generate ibm,dynamic-reconfiguration-memory node if required */ 8036787d27bSMichael Roth if (spapr_ovec_test(ov5_updates, OV5_DRCONF_MEMORY)) { 8046787d27bSMichael Roth g_assert(smc->dr_lmb_enabled); 8056787d27bSMichael Roth ret = spapr_populate_drconf_memory(spapr, fdt); 806417ece33SMichael Roth if (ret) { 807417ece33SMichael Roth goto out; 808417ece33SMichael Roth } 8096787d27bSMichael Roth } 8106787d27bSMichael Roth 811417ece33SMichael Roth offset = fdt_path_offset(fdt, "/chosen"); 812417ece33SMichael Roth if (offset < 0) { 813417ece33SMichael Roth offset = fdt_add_subnode(fdt, 0, "chosen"); 814417ece33SMichael Roth if (offset < 0) { 815417ece33SMichael Roth return offset; 816417ece33SMichael Roth } 817417ece33SMichael Roth } 818417ece33SMichael Roth ret = spapr_ovec_populate_dt(fdt, offset, spapr->ov5_cas, 819417ece33SMichael Roth "ibm,architecture-vec-5"); 820417ece33SMichael Roth 821417ece33SMichael Roth out: 8226787d27bSMichael Roth return ret; 8236787d27bSMichael Roth } 8246787d27bSMichael Roth 82510f12e64SDaniel Henrique Barboza static bool spapr_hotplugged_dev_before_cas(void) 82610f12e64SDaniel Henrique Barboza { 82710f12e64SDaniel Henrique Barboza Object *drc_container, *obj; 82810f12e64SDaniel Henrique Barboza ObjectProperty *prop; 82910f12e64SDaniel Henrique Barboza ObjectPropertyIterator iter; 83010f12e64SDaniel Henrique Barboza 83110f12e64SDaniel Henrique Barboza drc_container = container_get(object_get_root(), "/dr-connector"); 83210f12e64SDaniel Henrique Barboza object_property_iter_init(&iter, drc_container); 83310f12e64SDaniel Henrique Barboza while ((prop = object_property_iter_next(&iter))) { 83410f12e64SDaniel Henrique Barboza if (!strstart(prop->type, "link<", NULL)) { 83510f12e64SDaniel Henrique Barboza continue; 83610f12e64SDaniel Henrique Barboza } 83710f12e64SDaniel Henrique Barboza obj = object_property_get_link(drc_container, prop->name, NULL); 83810f12e64SDaniel Henrique Barboza if (spapr_drc_needed(obj)) { 83910f12e64SDaniel Henrique Barboza return true; 84010f12e64SDaniel Henrique Barboza } 84110f12e64SDaniel Henrique Barboza } 84210f12e64SDaniel Henrique Barboza return false; 84310f12e64SDaniel Henrique Barboza } 84410f12e64SDaniel Henrique Barboza 84503d196b7SBharata B Rao int spapr_h_cas_compose_response(sPAPRMachineState *spapr, 84603d196b7SBharata B Rao target_ulong addr, target_ulong size, 8476787d27bSMichael Roth sPAPROptionVector *ov5_updates) 84803d196b7SBharata B Rao { 84903d196b7SBharata B Rao void *fdt, *fdt_skel; 85003d196b7SBharata B Rao sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 }; 85103d196b7SBharata B Rao 85210f12e64SDaniel Henrique Barboza if (spapr_hotplugged_dev_before_cas()) { 85310f12e64SDaniel Henrique Barboza return 1; 85410f12e64SDaniel Henrique Barboza } 85510f12e64SDaniel Henrique Barboza 856827b17c4SGreg Kurz if (size < sizeof(hdr) || size > FW_MAX_SIZE) { 857827b17c4SGreg Kurz error_report("SLOF provided an unexpected CAS buffer size " 858827b17c4SGreg Kurz TARGET_FMT_lu " (min: %zu, max: %u)", 859827b17c4SGreg Kurz size, sizeof(hdr), FW_MAX_SIZE); 860827b17c4SGreg Kurz exit(EXIT_FAILURE); 861827b17c4SGreg Kurz } 862827b17c4SGreg Kurz 86303d196b7SBharata B Rao size -= sizeof(hdr); 86403d196b7SBharata B Rao 86510f12e64SDaniel Henrique Barboza /* Create skeleton */ 86603d196b7SBharata B Rao fdt_skel = g_malloc0(size); 86703d196b7SBharata B Rao _FDT((fdt_create(fdt_skel, size))); 868127f03e4SAlexey Kardashevskiy _FDT((fdt_finish_reservemap(fdt_skel))); 86903d196b7SBharata B Rao _FDT((fdt_begin_node(fdt_skel, ""))); 87003d196b7SBharata B Rao _FDT((fdt_end_node(fdt_skel))); 87103d196b7SBharata B Rao _FDT((fdt_finish(fdt_skel))); 87203d196b7SBharata B Rao fdt = g_malloc0(size); 87303d196b7SBharata B Rao _FDT((fdt_open_into(fdt_skel, fdt, size))); 87403d196b7SBharata B Rao g_free(fdt_skel); 87503d196b7SBharata B Rao 87603d196b7SBharata B Rao /* Fixup cpu nodes */ 87703d196b7SBharata B Rao _FDT((spapr_fixup_cpu_dt(fdt, spapr))); 87803d196b7SBharata B Rao 8796787d27bSMichael Roth if (spapr_dt_cas_updates(spapr, fdt, ov5_updates)) { 8806787d27bSMichael Roth return -1; 88103d196b7SBharata B Rao } 88203d196b7SBharata B Rao 88303d196b7SBharata B Rao /* Pack resulting tree */ 88403d196b7SBharata B Rao _FDT((fdt_pack(fdt))); 88503d196b7SBharata B Rao 88603d196b7SBharata B Rao if (fdt_totalsize(fdt) + sizeof(hdr) > size) { 88703d196b7SBharata B Rao trace_spapr_cas_failed(size); 88803d196b7SBharata B Rao return -1; 88903d196b7SBharata B Rao } 89003d196b7SBharata B Rao 89103d196b7SBharata B Rao cpu_physical_memory_write(addr, &hdr, sizeof(hdr)); 89203d196b7SBharata B Rao cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt)); 89303d196b7SBharata B Rao trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr)); 89403d196b7SBharata B Rao g_free(fdt); 89503d196b7SBharata B Rao 89603d196b7SBharata B Rao return 0; 89703d196b7SBharata B Rao } 89803d196b7SBharata B Rao 8993f5dabceSDavid Gibson static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt) 9003f5dabceSDavid Gibson { 9013f5dabceSDavid Gibson int rtas; 9023f5dabceSDavid Gibson GString *hypertas = g_string_sized_new(256); 9033f5dabceSDavid Gibson GString *qemu_hypertas = g_string_sized_new(256); 9043f5dabceSDavid Gibson uint32_t refpoints[] = { cpu_to_be32(0x4), cpu_to_be32(0x4) }; 9053f5dabceSDavid Gibson uint64_t max_hotplug_addr = spapr->hotplug_memory.base + 9063f5dabceSDavid Gibson memory_region_size(&spapr->hotplug_memory.mr); 9073f5dabceSDavid Gibson uint32_t lrdr_capacity[] = { 9083f5dabceSDavid Gibson cpu_to_be32(max_hotplug_addr >> 32), 9093f5dabceSDavid Gibson cpu_to_be32(max_hotplug_addr & 0xffffffff), 9103f5dabceSDavid Gibson 0, cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE), 9113f5dabceSDavid Gibson cpu_to_be32(max_cpus / smp_threads), 9123f5dabceSDavid Gibson }; 9133f5dabceSDavid Gibson 9143f5dabceSDavid Gibson _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas")); 9153f5dabceSDavid Gibson 9163f5dabceSDavid Gibson /* hypertas */ 9173f5dabceSDavid Gibson add_str(hypertas, "hcall-pft"); 9183f5dabceSDavid Gibson add_str(hypertas, "hcall-term"); 9193f5dabceSDavid Gibson add_str(hypertas, "hcall-dabr"); 9203f5dabceSDavid Gibson add_str(hypertas, "hcall-interrupt"); 9213f5dabceSDavid Gibson add_str(hypertas, "hcall-tce"); 9223f5dabceSDavid Gibson add_str(hypertas, "hcall-vio"); 9233f5dabceSDavid Gibson add_str(hypertas, "hcall-splpar"); 9243f5dabceSDavid Gibson add_str(hypertas, "hcall-bulk"); 9253f5dabceSDavid Gibson add_str(hypertas, "hcall-set-mode"); 9263f5dabceSDavid Gibson add_str(hypertas, "hcall-sprg0"); 9273f5dabceSDavid Gibson add_str(hypertas, "hcall-copy"); 9283f5dabceSDavid Gibson add_str(hypertas, "hcall-debug"); 9293f5dabceSDavid Gibson add_str(qemu_hypertas, "hcall-memop1"); 9303f5dabceSDavid Gibson 9313f5dabceSDavid Gibson if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { 9323f5dabceSDavid Gibson add_str(hypertas, "hcall-multi-tce"); 9333f5dabceSDavid Gibson } 93430f4b05bSDavid Gibson 93530f4b05bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { 93630f4b05bSDavid Gibson add_str(hypertas, "hcall-hpt-resize"); 93730f4b05bSDavid Gibson } 93830f4b05bSDavid Gibson 9393f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions", 9403f5dabceSDavid Gibson hypertas->str, hypertas->len)); 9413f5dabceSDavid Gibson g_string_free(hypertas, TRUE); 9423f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "qemu,hypertas-functions", 9433f5dabceSDavid Gibson qemu_hypertas->str, qemu_hypertas->len)); 9443f5dabceSDavid Gibson g_string_free(qemu_hypertas, TRUE); 9453f5dabceSDavid Gibson 9463f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,associativity-reference-points", 9473f5dabceSDavid Gibson refpoints, sizeof(refpoints))); 9483f5dabceSDavid Gibson 9493f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-error-log-max", 9503f5dabceSDavid Gibson RTAS_ERROR_LOG_MAX)); 9513f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-event-scan-rate", 9523f5dabceSDavid Gibson RTAS_EVENT_SCAN_RATE)); 9533f5dabceSDavid Gibson 9544f441474SDavid Gibson g_assert(msi_nonbroken); 9553f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,change-msix-capable", NULL, 0)); 9563f5dabceSDavid Gibson 9573f5dabceSDavid Gibson /* 9583f5dabceSDavid Gibson * According to PAPR, rtas ibm,os-term does not guarantee a return 9593f5dabceSDavid Gibson * back to the guest cpu. 9603f5dabceSDavid Gibson * 9613f5dabceSDavid Gibson * While an additional ibm,extended-os-term property indicates 9623f5dabceSDavid Gibson * that rtas call return will always occur. Set this property. 9633f5dabceSDavid Gibson */ 9643f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,extended-os-term", NULL, 0)); 9653f5dabceSDavid Gibson 9663f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,lrdr-capacity", 9673f5dabceSDavid Gibson lrdr_capacity, sizeof(lrdr_capacity))); 9683f5dabceSDavid Gibson 9693f5dabceSDavid Gibson spapr_dt_rtas_tokens(fdt, rtas); 9703f5dabceSDavid Gibson } 9713f5dabceSDavid Gibson 9729fb4541fSSam Bobroff /* Prepare ibm,arch-vec-5-platform-support, which indicates the MMU features 9739fb4541fSSam Bobroff * that the guest may request and thus the valid values for bytes 24..26 of 9749fb4541fSSam Bobroff * option vector 5: */ 9759fb4541fSSam Bobroff static void spapr_dt_ov5_platform_support(void *fdt, int chosen) 9769fb4541fSSam Bobroff { 977545d6e2bSSuraj Jitindar Singh PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); 978545d6e2bSSuraj Jitindar Singh 979f2b14e3aSCédric Le Goater char val[2 * 4] = { 98021f3f8dbSCédric Le Goater 23, 0x00, /* Xive mode, filled in below. */ 9819fb4541fSSam Bobroff 24, 0x00, /* Hash/Radix, filled in below. */ 9829fb4541fSSam Bobroff 25, 0x00, /* Hash options: Segment Tables == no, GTSE == no. */ 9839fb4541fSSam Bobroff 26, 0x40, /* Radix options: GTSE == yes. */ 9849fb4541fSSam Bobroff }; 9859fb4541fSSam Bobroff 9867abd43baSSuraj Jitindar Singh if (!ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0, 9877abd43baSSuraj Jitindar Singh first_ppc_cpu->compat_pvr)) { 9887abd43baSSuraj Jitindar Singh /* If we're in a pre POWER9 compat mode then the guest should do hash */ 9897abd43baSSuraj Jitindar Singh val[3] = 0x00; /* Hash */ 9907abd43baSSuraj Jitindar Singh } else if (kvm_enabled()) { 9919fb4541fSSam Bobroff if (kvmppc_has_cap_mmu_radix() && kvmppc_has_cap_mmu_hash_v3()) { 992f2b14e3aSCédric Le Goater val[3] = 0x80; /* OV5_MMU_BOTH */ 9939fb4541fSSam Bobroff } else if (kvmppc_has_cap_mmu_radix()) { 994f2b14e3aSCédric Le Goater val[3] = 0x40; /* OV5_MMU_RADIX_300 */ 9959fb4541fSSam Bobroff } else { 996f2b14e3aSCédric Le Goater val[3] = 0x00; /* Hash */ 9979fb4541fSSam Bobroff } 9989fb4541fSSam Bobroff } else { 9997abd43baSSuraj Jitindar Singh /* V3 MMU supports both hash and radix in tcg (with dynamic switching) */ 1000f2b14e3aSCédric Le Goater val[3] = 0xC0; 1001545d6e2bSSuraj Jitindar Singh } 10029fb4541fSSam Bobroff _FDT(fdt_setprop(fdt, chosen, "ibm,arch-vec-5-platform-support", 10039fb4541fSSam Bobroff val, sizeof(val))); 10049fb4541fSSam Bobroff } 10059fb4541fSSam Bobroff 10067c866c6aSDavid Gibson static void spapr_dt_chosen(sPAPRMachineState *spapr, void *fdt) 10077c866c6aSDavid Gibson { 10087c866c6aSDavid Gibson MachineState *machine = MACHINE(spapr); 10097c866c6aSDavid Gibson int chosen; 10107c866c6aSDavid Gibson const char *boot_device = machine->boot_order; 10117c866c6aSDavid Gibson char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus); 10127c866c6aSDavid Gibson size_t cb = 0; 10137c866c6aSDavid Gibson char *bootlist = get_boot_devices_list(&cb, true); 10147c866c6aSDavid Gibson 10157c866c6aSDavid Gibson _FDT(chosen = fdt_add_subnode(fdt, 0, "chosen")); 10167c866c6aSDavid Gibson 10177c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "bootargs", machine->kernel_cmdline)); 10187c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-start", 10197c866c6aSDavid Gibson spapr->initrd_base)); 10207c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-end", 10217c866c6aSDavid Gibson spapr->initrd_base + spapr->initrd_size)); 10227c866c6aSDavid Gibson 10237c866c6aSDavid Gibson if (spapr->kernel_size) { 10247c866c6aSDavid Gibson uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR), 10257c866c6aSDavid Gibson cpu_to_be64(spapr->kernel_size) }; 10267c866c6aSDavid Gibson 10277c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel", 10287c866c6aSDavid Gibson &kprop, sizeof(kprop))); 10297c866c6aSDavid Gibson if (spapr->kernel_le) { 10307c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel-le", NULL, 0)); 10317c866c6aSDavid Gibson } 10327c866c6aSDavid Gibson } 10337c866c6aSDavid Gibson if (boot_menu) { 10347c866c6aSDavid Gibson _FDT((fdt_setprop_cell(fdt, chosen, "qemu,boot-menu", boot_menu))); 10357c866c6aSDavid Gibson } 10367c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-width", graphic_width)); 10377c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-height", graphic_height)); 10387c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-depth", graphic_depth)); 10397c866c6aSDavid Gibson 10407c866c6aSDavid Gibson if (cb && bootlist) { 10417c866c6aSDavid Gibson int i; 10427c866c6aSDavid Gibson 10437c866c6aSDavid Gibson for (i = 0; i < cb; i++) { 10447c866c6aSDavid Gibson if (bootlist[i] == '\n') { 10457c866c6aSDavid Gibson bootlist[i] = ' '; 10467c866c6aSDavid Gibson } 10477c866c6aSDavid Gibson } 10487c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-list", bootlist)); 10497c866c6aSDavid Gibson } 10507c866c6aSDavid Gibson 10517c866c6aSDavid Gibson if (boot_device && strlen(boot_device)) { 10527c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-device", boot_device)); 10537c866c6aSDavid Gibson } 10547c866c6aSDavid Gibson 10557c866c6aSDavid Gibson if (!spapr->has_graphics && stdout_path) { 105690ee4e01SNikunj A Dadhania /* 105790ee4e01SNikunj A Dadhania * "linux,stdout-path" and "stdout" properties are deprecated by linux 105890ee4e01SNikunj A Dadhania * kernel. New platforms should only use the "stdout-path" property. Set 105990ee4e01SNikunj A Dadhania * the new property and continue using older property to remain 106090ee4e01SNikunj A Dadhania * compatible with the existing firmware. 106190ee4e01SNikunj A Dadhania */ 10627c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "linux,stdout-path", stdout_path)); 106390ee4e01SNikunj A Dadhania _FDT(fdt_setprop_string(fdt, chosen, "stdout-path", stdout_path)); 10647c866c6aSDavid Gibson } 10657c866c6aSDavid Gibson 10669fb4541fSSam Bobroff spapr_dt_ov5_platform_support(fdt, chosen); 10679fb4541fSSam Bobroff 10687c866c6aSDavid Gibson g_free(stdout_path); 10697c866c6aSDavid Gibson g_free(bootlist); 10707c866c6aSDavid Gibson } 10717c866c6aSDavid Gibson 1072fca5f2dcSDavid Gibson static void spapr_dt_hypervisor(sPAPRMachineState *spapr, void *fdt) 1073fca5f2dcSDavid Gibson { 1074fca5f2dcSDavid Gibson /* The /hypervisor node isn't in PAPR - this is a hack to allow PR 1075fca5f2dcSDavid Gibson * KVM to work under pHyp with some guest co-operation */ 1076fca5f2dcSDavid Gibson int hypervisor; 1077fca5f2dcSDavid Gibson uint8_t hypercall[16]; 1078fca5f2dcSDavid Gibson 1079fca5f2dcSDavid Gibson _FDT(hypervisor = fdt_add_subnode(fdt, 0, "hypervisor")); 1080fca5f2dcSDavid Gibson /* indicate KVM hypercall interface */ 1081fca5f2dcSDavid Gibson _FDT(fdt_setprop_string(fdt, hypervisor, "compatible", "linux,kvm")); 1082fca5f2dcSDavid Gibson if (kvmppc_has_cap_fixup_hcalls()) { 1083fca5f2dcSDavid Gibson /* 1084fca5f2dcSDavid Gibson * Older KVM versions with older guest kernels were broken 1085fca5f2dcSDavid Gibson * with the magic page, don't allow the guest to map it. 1086fca5f2dcSDavid Gibson */ 1087fca5f2dcSDavid Gibson if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall, 1088fca5f2dcSDavid Gibson sizeof(hypercall))) { 1089fca5f2dcSDavid Gibson _FDT(fdt_setprop(fdt, hypervisor, "hcall-instructions", 1090fca5f2dcSDavid Gibson hypercall, sizeof(hypercall))); 1091fca5f2dcSDavid Gibson } 1092fca5f2dcSDavid Gibson } 1093fca5f2dcSDavid Gibson } 1094fca5f2dcSDavid Gibson 1095997b6cfcSDavid Gibson static void *spapr_build_fdt(sPAPRMachineState *spapr, 109653018216SPaolo Bonzini hwaddr rtas_addr, 109753018216SPaolo Bonzini hwaddr rtas_size) 109853018216SPaolo Bonzini { 1099c86c1affSDaniel Henrique Barboza MachineState *machine = MACHINE(spapr); 11003c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 1101c20d332aSBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 11027c866c6aSDavid Gibson int ret; 110353018216SPaolo Bonzini void *fdt; 110453018216SPaolo Bonzini sPAPRPHBState *phb; 1105398a0bd5SDavid Gibson char *buf; 110653018216SPaolo Bonzini 1107398a0bd5SDavid Gibson fdt = g_malloc0(FDT_MAX_SIZE); 1108398a0bd5SDavid Gibson _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 110953018216SPaolo Bonzini 1110398a0bd5SDavid Gibson /* Root node */ 1111398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "device_type", "chrp")); 1112398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "model", "IBM pSeries (emulated by qemu)")); 1113398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "compatible", "qemu,pseries")); 1114398a0bd5SDavid Gibson 1115398a0bd5SDavid Gibson /* 1116398a0bd5SDavid Gibson * Add info to guest to indentify which host is it being run on 1117398a0bd5SDavid Gibson * and what is the uuid of the guest 1118398a0bd5SDavid Gibson */ 1119398a0bd5SDavid Gibson if (kvmppc_get_host_model(&buf)) { 1120398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-model", buf)); 1121398a0bd5SDavid Gibson g_free(buf); 1122398a0bd5SDavid Gibson } 1123398a0bd5SDavid Gibson if (kvmppc_get_host_serial(&buf)) { 1124398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf)); 1125398a0bd5SDavid Gibson g_free(buf); 1126398a0bd5SDavid Gibson } 1127398a0bd5SDavid Gibson 1128398a0bd5SDavid Gibson buf = qemu_uuid_unparse_strdup(&qemu_uuid); 1129398a0bd5SDavid Gibson 1130398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "vm,uuid", buf)); 1131398a0bd5SDavid Gibson if (qemu_uuid_set) { 1132398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "system-id", buf)); 1133398a0bd5SDavid Gibson } 1134398a0bd5SDavid Gibson g_free(buf); 1135398a0bd5SDavid Gibson 1136398a0bd5SDavid Gibson if (qemu_get_vm_name()) { 1137398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "ibm,partition-name", 1138398a0bd5SDavid Gibson qemu_get_vm_name())); 1139398a0bd5SDavid Gibson } 1140398a0bd5SDavid Gibson 1141398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#address-cells", 2)); 1142398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2)); 114353018216SPaolo Bonzini 1144fc7e0765SDavid Gibson /* /interrupt controller */ 114572194664SGreg Kurz spapr_dt_xics(xics_max_server_number(spapr), fdt, PHANDLE_XICP); 1146fc7e0765SDavid Gibson 1147e8f986fcSBharata B Rao ret = spapr_populate_memory(spapr, fdt); 1148e8f986fcSBharata B Rao if (ret < 0) { 1149ce9863b7SCédric Le Goater error_report("couldn't setup memory nodes in fdt"); 1150e8f986fcSBharata B Rao exit(1); 115153018216SPaolo Bonzini } 115253018216SPaolo Bonzini 1153bf5a6696SDavid Gibson /* /vdevice */ 1154bf5a6696SDavid Gibson spapr_dt_vdevice(spapr->vio_bus, fdt); 115553018216SPaolo Bonzini 11564d9392beSThomas Huth if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) { 11574d9392beSThomas Huth ret = spapr_rng_populate_dt(fdt); 11584d9392beSThomas Huth if (ret < 0) { 1159ce9863b7SCédric Le Goater error_report("could not set up rng device in the fdt"); 11604d9392beSThomas Huth exit(1); 11614d9392beSThomas Huth } 11624d9392beSThomas Huth } 11634d9392beSThomas Huth 116453018216SPaolo Bonzini QLIST_FOREACH(phb, &spapr->phbs, list) { 116553018216SPaolo Bonzini ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt); 116653018216SPaolo Bonzini if (ret < 0) { 1167da34fed7SThomas Huth error_report("couldn't setup PCI devices in fdt"); 116853018216SPaolo Bonzini exit(1); 116953018216SPaolo Bonzini } 1170da34fed7SThomas Huth } 117153018216SPaolo Bonzini 11720da6f3feSBharata B Rao /* cpus */ 11730da6f3feSBharata B Rao spapr_populate_cpus_dt_node(fdt, spapr); 117453018216SPaolo Bonzini 1175c20d332aSBharata B Rao if (smc->dr_lmb_enabled) { 1176c20d332aSBharata B Rao _FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB)); 1177c20d332aSBharata B Rao } 1178c20d332aSBharata B Rao 1179c5514d0eSIgor Mammedov if (mc->has_hotpluggable_cpus) { 1180af81cf32SBharata B Rao int offset = fdt_path_offset(fdt, "/cpus"); 1181af81cf32SBharata B Rao ret = spapr_drc_populate_dt(fdt, offset, NULL, 1182af81cf32SBharata B Rao SPAPR_DR_CONNECTOR_TYPE_CPU); 1183af81cf32SBharata B Rao if (ret < 0) { 1184af81cf32SBharata B Rao error_report("Couldn't set up CPU DR device tree properties"); 1185af81cf32SBharata B Rao exit(1); 1186af81cf32SBharata B Rao } 1187af81cf32SBharata B Rao } 1188af81cf32SBharata B Rao 1189ffb1e275SDavid Gibson /* /event-sources */ 1190ffbb1705SMichael Roth spapr_dt_events(spapr, fdt); 1191ffb1e275SDavid Gibson 11923f5dabceSDavid Gibson /* /rtas */ 11933f5dabceSDavid Gibson spapr_dt_rtas(spapr, fdt); 11943f5dabceSDavid Gibson 11957c866c6aSDavid Gibson /* /chosen */ 11967c866c6aSDavid Gibson spapr_dt_chosen(spapr, fdt); 1197cf6e5223SDavid Gibson 1198fca5f2dcSDavid Gibson /* /hypervisor */ 1199fca5f2dcSDavid Gibson if (kvm_enabled()) { 1200fca5f2dcSDavid Gibson spapr_dt_hypervisor(spapr, fdt); 1201fca5f2dcSDavid Gibson } 1202fca5f2dcSDavid Gibson 1203cf6e5223SDavid Gibson /* Build memory reserve map */ 1204cf6e5223SDavid Gibson if (spapr->kernel_size) { 1205cf6e5223SDavid Gibson _FDT((fdt_add_mem_rsv(fdt, KERNEL_LOAD_ADDR, spapr->kernel_size))); 1206cf6e5223SDavid Gibson } 1207cf6e5223SDavid Gibson if (spapr->initrd_size) { 1208cf6e5223SDavid Gibson _FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base, spapr->initrd_size))); 1209cf6e5223SDavid Gibson } 1210cf6e5223SDavid Gibson 12116787d27bSMichael Roth /* ibm,client-architecture-support updates */ 12126787d27bSMichael Roth ret = spapr_dt_cas_updates(spapr, fdt, spapr->ov5_cas); 12136787d27bSMichael Roth if (ret < 0) { 12146787d27bSMichael Roth error_report("couldn't setup CAS properties fdt"); 12156787d27bSMichael Roth exit(1); 12166787d27bSMichael Roth } 12176787d27bSMichael Roth 1218997b6cfcSDavid Gibson return fdt; 121953018216SPaolo Bonzini } 122053018216SPaolo Bonzini 122153018216SPaolo Bonzini static uint64_t translate_kernel_address(void *opaque, uint64_t addr) 122253018216SPaolo Bonzini { 122353018216SPaolo Bonzini return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR; 122453018216SPaolo Bonzini } 122553018216SPaolo Bonzini 12261d1be34dSDavid Gibson static void emulate_spapr_hypercall(PPCVirtualHypervisor *vhyp, 12271d1be34dSDavid Gibson PowerPCCPU *cpu) 122853018216SPaolo Bonzini { 122953018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 123053018216SPaolo Bonzini 12318d04fb55SJan Kiszka /* The TCG path should also be holding the BQL at this point */ 12328d04fb55SJan Kiszka g_assert(qemu_mutex_iothread_locked()); 12338d04fb55SJan Kiszka 123453018216SPaolo Bonzini if (msr_pr) { 123553018216SPaolo Bonzini hcall_dprintf("Hypercall made with MSR[PR]=1\n"); 123653018216SPaolo Bonzini env->gpr[3] = H_PRIVILEGE; 123753018216SPaolo Bonzini } else { 123853018216SPaolo Bonzini env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]); 123953018216SPaolo Bonzini } 124053018216SPaolo Bonzini } 124153018216SPaolo Bonzini 12429861bb3eSSuraj Jitindar Singh static uint64_t spapr_get_patbe(PPCVirtualHypervisor *vhyp) 12439861bb3eSSuraj Jitindar Singh { 12449861bb3eSSuraj Jitindar Singh sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); 12459861bb3eSSuraj Jitindar Singh 12469861bb3eSSuraj Jitindar Singh return spapr->patb_entry; 12479861bb3eSSuraj Jitindar Singh } 12489861bb3eSSuraj Jitindar Singh 1249e6b8fd24SSamuel Mendoza-Jonas #define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2)) 1250e6b8fd24SSamuel Mendoza-Jonas #define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID) 1251e6b8fd24SSamuel Mendoza-Jonas #define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY) 1252e6b8fd24SSamuel Mendoza-Jonas #define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY)) 1253e6b8fd24SSamuel Mendoza-Jonas #define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY)) 1254e6b8fd24SSamuel Mendoza-Jonas 1255715c5407SDavid Gibson /* 1256715c5407SDavid Gibson * Get the fd to access the kernel htab, re-opening it if necessary 1257715c5407SDavid Gibson */ 1258715c5407SDavid Gibson static int get_htab_fd(sPAPRMachineState *spapr) 1259715c5407SDavid Gibson { 126014b0d748SGreg Kurz Error *local_err = NULL; 126114b0d748SGreg Kurz 1262715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1263715c5407SDavid Gibson return spapr->htab_fd; 1264715c5407SDavid Gibson } 1265715c5407SDavid Gibson 126614b0d748SGreg Kurz spapr->htab_fd = kvmppc_get_htab_fd(false, 0, &local_err); 1267715c5407SDavid Gibson if (spapr->htab_fd < 0) { 126814b0d748SGreg Kurz error_report_err(local_err); 1269715c5407SDavid Gibson } 1270715c5407SDavid Gibson 1271715c5407SDavid Gibson return spapr->htab_fd; 1272715c5407SDavid Gibson } 1273715c5407SDavid Gibson 1274b4db5413SSuraj Jitindar Singh void close_htab_fd(sPAPRMachineState *spapr) 1275715c5407SDavid Gibson { 1276715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1277715c5407SDavid Gibson close(spapr->htab_fd); 1278715c5407SDavid Gibson } 1279715c5407SDavid Gibson spapr->htab_fd = -1; 1280715c5407SDavid Gibson } 1281715c5407SDavid Gibson 1282e57ca75cSDavid Gibson static hwaddr spapr_hpt_mask(PPCVirtualHypervisor *vhyp) 1283e57ca75cSDavid Gibson { 1284e57ca75cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); 1285e57ca75cSDavid Gibson 1286e57ca75cSDavid Gibson return HTAB_SIZE(spapr) / HASH_PTEG_SIZE_64 - 1; 1287e57ca75cSDavid Gibson } 1288e57ca75cSDavid Gibson 12891ec26c75SGreg Kurz static target_ulong spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp) 12901ec26c75SGreg Kurz { 12911ec26c75SGreg Kurz sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); 12921ec26c75SGreg Kurz 12931ec26c75SGreg Kurz assert(kvm_enabled()); 12941ec26c75SGreg Kurz 12951ec26c75SGreg Kurz if (!spapr->htab) { 12961ec26c75SGreg Kurz return 0; 12971ec26c75SGreg Kurz } 12981ec26c75SGreg Kurz 12991ec26c75SGreg Kurz return (target_ulong)(uintptr_t)spapr->htab | (spapr->htab_shift - 18); 13001ec26c75SGreg Kurz } 13011ec26c75SGreg Kurz 1302e57ca75cSDavid Gibson static const ppc_hash_pte64_t *spapr_map_hptes(PPCVirtualHypervisor *vhyp, 1303e57ca75cSDavid Gibson hwaddr ptex, int n) 1304e57ca75cSDavid Gibson { 1305e57ca75cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); 1306e57ca75cSDavid Gibson hwaddr pte_offset = ptex * HASH_PTE_SIZE_64; 1307e57ca75cSDavid Gibson 1308e57ca75cSDavid Gibson if (!spapr->htab) { 1309e57ca75cSDavid Gibson /* 1310e57ca75cSDavid Gibson * HTAB is controlled by KVM. Fetch into temporary buffer 1311e57ca75cSDavid Gibson */ 1312e57ca75cSDavid Gibson ppc_hash_pte64_t *hptes = g_malloc(n * HASH_PTE_SIZE_64); 1313e57ca75cSDavid Gibson kvmppc_read_hptes(hptes, ptex, n); 1314e57ca75cSDavid Gibson return hptes; 1315e57ca75cSDavid Gibson } 1316e57ca75cSDavid Gibson 1317e57ca75cSDavid Gibson /* 1318e57ca75cSDavid Gibson * HTAB is controlled by QEMU. Just point to the internally 1319e57ca75cSDavid Gibson * accessible PTEG. 1320e57ca75cSDavid Gibson */ 1321e57ca75cSDavid Gibson return (const ppc_hash_pte64_t *)(spapr->htab + pte_offset); 1322e57ca75cSDavid Gibson } 1323e57ca75cSDavid Gibson 1324e57ca75cSDavid Gibson static void spapr_unmap_hptes(PPCVirtualHypervisor *vhyp, 1325e57ca75cSDavid Gibson const ppc_hash_pte64_t *hptes, 1326e57ca75cSDavid Gibson hwaddr ptex, int n) 1327e57ca75cSDavid Gibson { 1328e57ca75cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); 1329e57ca75cSDavid Gibson 1330e57ca75cSDavid Gibson if (!spapr->htab) { 1331e57ca75cSDavid Gibson g_free((void *)hptes); 1332e57ca75cSDavid Gibson } 1333e57ca75cSDavid Gibson 1334e57ca75cSDavid Gibson /* Nothing to do for qemu managed HPT */ 1335e57ca75cSDavid Gibson } 1336e57ca75cSDavid Gibson 1337e57ca75cSDavid Gibson static void spapr_store_hpte(PPCVirtualHypervisor *vhyp, hwaddr ptex, 1338e57ca75cSDavid Gibson uint64_t pte0, uint64_t pte1) 1339e57ca75cSDavid Gibson { 1340e57ca75cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); 1341e57ca75cSDavid Gibson hwaddr offset = ptex * HASH_PTE_SIZE_64; 1342e57ca75cSDavid Gibson 1343e57ca75cSDavid Gibson if (!spapr->htab) { 1344e57ca75cSDavid Gibson kvmppc_write_hpte(ptex, pte0, pte1); 1345e57ca75cSDavid Gibson } else { 1346e57ca75cSDavid Gibson stq_p(spapr->htab + offset, pte0); 1347e57ca75cSDavid Gibson stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); 1348e57ca75cSDavid Gibson } 1349e57ca75cSDavid Gibson } 1350e57ca75cSDavid Gibson 13510b0b8310SDavid Gibson int spapr_hpt_shift_for_ramsize(uint64_t ramsize) 13528dfe8e7fSDavid Gibson { 13538dfe8e7fSDavid Gibson int shift; 13548dfe8e7fSDavid Gibson 13558dfe8e7fSDavid Gibson /* We aim for a hash table of size 1/128 the size of RAM (rounded 13568dfe8e7fSDavid Gibson * up). The PAPR recommendation is actually 1/64 of RAM size, but 13578dfe8e7fSDavid Gibson * that's much more than is needed for Linux guests */ 13588dfe8e7fSDavid Gibson shift = ctz64(pow2ceil(ramsize)) - 7; 13598dfe8e7fSDavid Gibson shift = MAX(shift, 18); /* Minimum architected size */ 13608dfe8e7fSDavid Gibson shift = MIN(shift, 46); /* Maximum architected size */ 13618dfe8e7fSDavid Gibson return shift; 13628dfe8e7fSDavid Gibson } 13638dfe8e7fSDavid Gibson 136406ec79e8SBharata B Rao void spapr_free_hpt(sPAPRMachineState *spapr) 136506ec79e8SBharata B Rao { 136606ec79e8SBharata B Rao g_free(spapr->htab); 136706ec79e8SBharata B Rao spapr->htab = NULL; 136806ec79e8SBharata B Rao spapr->htab_shift = 0; 136906ec79e8SBharata B Rao close_htab_fd(spapr); 137006ec79e8SBharata B Rao } 137106ec79e8SBharata B Rao 13722772cf6bSDavid Gibson void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift, 1373c5f54f3eSDavid Gibson Error **errp) 137453018216SPaolo Bonzini { 1375c5f54f3eSDavid Gibson long rc; 137653018216SPaolo Bonzini 1377c5f54f3eSDavid Gibson /* Clean up any HPT info from a previous boot */ 137806ec79e8SBharata B Rao spapr_free_hpt(spapr); 137953018216SPaolo Bonzini 1380c5f54f3eSDavid Gibson rc = kvmppc_reset_htab(shift); 1381c5f54f3eSDavid Gibson if (rc < 0) { 1382c5f54f3eSDavid Gibson /* kernel-side HPT needed, but couldn't allocate one */ 1383c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1384c5f54f3eSDavid Gibson "Failed to allocate KVM HPT of order %d (try smaller maxmem?)", 1385c5f54f3eSDavid Gibson shift); 1386c5f54f3eSDavid Gibson /* This is almost certainly fatal, but if the caller really 1387c5f54f3eSDavid Gibson * wants to carry on with shift == 0, it's welcome to try */ 1388c5f54f3eSDavid Gibson } else if (rc > 0) { 1389c5f54f3eSDavid Gibson /* kernel-side HPT allocated */ 1390c5f54f3eSDavid Gibson if (rc != shift) { 1391c5f54f3eSDavid Gibson error_setg(errp, 1392c5f54f3eSDavid Gibson "Requested order %d HPT, but kernel allocated order %ld (try smaller maxmem?)", 1393c5f54f3eSDavid Gibson shift, rc); 13947735fedaSBharata B Rao } 13957735fedaSBharata B Rao 139653018216SPaolo Bonzini spapr->htab_shift = shift; 1397c18ad9a5SDavid Gibson spapr->htab = NULL; 1398b817772aSBharata B Rao } else { 1399c5f54f3eSDavid Gibson /* kernel-side HPT not needed, allocate in userspace instead */ 1400c5f54f3eSDavid Gibson size_t size = 1ULL << shift; 1401c5f54f3eSDavid Gibson int i; 140201a57972SSamuel Mendoza-Jonas 1403c5f54f3eSDavid Gibson spapr->htab = qemu_memalign(size, size); 1404c5f54f3eSDavid Gibson if (!spapr->htab) { 1405c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1406c5f54f3eSDavid Gibson "Could not allocate HPT of order %d", shift); 1407c5f54f3eSDavid Gibson return; 1408b817772aSBharata B Rao } 1409b817772aSBharata B Rao 1410c5f54f3eSDavid Gibson memset(spapr->htab, 0, size); 1411c5f54f3eSDavid Gibson spapr->htab_shift = shift; 1412b817772aSBharata B Rao 1413c5f54f3eSDavid Gibson for (i = 0; i < size / HASH_PTE_SIZE_64; i++) { 1414c5f54f3eSDavid Gibson DIRTY_HPTE(HPTE(spapr->htab, i)); 14157735fedaSBharata B Rao } 141653018216SPaolo Bonzini } 1417ee4d9eccSSuraj Jitindar Singh /* We're setting up a hash table, so that means we're not radix */ 1418ee4d9eccSSuraj Jitindar Singh spapr->patb_entry = 0; 141953018216SPaolo Bonzini } 142053018216SPaolo Bonzini 1421b4db5413SSuraj Jitindar Singh void spapr_setup_hpt_and_vrma(sPAPRMachineState *spapr) 1422b4db5413SSuraj Jitindar Singh { 14232772cf6bSDavid Gibson int hpt_shift; 14242772cf6bSDavid Gibson 14252772cf6bSDavid Gibson if ((spapr->resize_hpt == SPAPR_RESIZE_HPT_DISABLED) 14262772cf6bSDavid Gibson || (spapr->cas_reboot 14272772cf6bSDavid Gibson && !spapr_ovec_test(spapr->ov5_cas, OV5_HPT_RESIZE))) { 14282772cf6bSDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(MACHINE(spapr)->maxram_size); 14292772cf6bSDavid Gibson } else { 1430768a20f3SDavid Gibson uint64_t current_ram_size; 1431768a20f3SDavid Gibson 1432768a20f3SDavid Gibson current_ram_size = MACHINE(spapr)->ram_size + get_plugged_memory_size(); 1433768a20f3SDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(current_ram_size); 14342772cf6bSDavid Gibson } 14352772cf6bSDavid Gibson spapr_reallocate_hpt(spapr, hpt_shift, &error_fatal); 14362772cf6bSDavid Gibson 1437b4db5413SSuraj Jitindar Singh if (spapr->vrma_adjust) { 1438c86c1affSDaniel Henrique Barboza spapr->rma_size = kvmppc_rma_size(spapr_node0_size(MACHINE(spapr)), 1439b4db5413SSuraj Jitindar Singh spapr->htab_shift); 1440b4db5413SSuraj Jitindar Singh } 1441b4db5413SSuraj Jitindar Singh } 1442b4db5413SSuraj Jitindar Singh 14434f01a637SDavid Gibson static void find_unknown_sysbus_device(SysBusDevice *sbdev, void *opaque) 14449e3f9733SAlexander Graf { 14459e3f9733SAlexander Graf bool matched = false; 14469e3f9733SAlexander Graf 14479e3f9733SAlexander Graf if (object_dynamic_cast(OBJECT(sbdev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 14489e3f9733SAlexander Graf matched = true; 14499e3f9733SAlexander Graf } 14509e3f9733SAlexander Graf 14519e3f9733SAlexander Graf if (!matched) { 14529e3f9733SAlexander Graf error_report("Device %s is not supported by this machine yet.", 14539e3f9733SAlexander Graf qdev_fw_name(DEVICE(sbdev))); 14549e3f9733SAlexander Graf exit(1); 14559e3f9733SAlexander Graf } 14569e3f9733SAlexander Graf } 14579e3f9733SAlexander Graf 145882512483SGreg Kurz static int spapr_reset_drcs(Object *child, void *opaque) 145982512483SGreg Kurz { 146082512483SGreg Kurz sPAPRDRConnector *drc = 146182512483SGreg Kurz (sPAPRDRConnector *) object_dynamic_cast(child, 146282512483SGreg Kurz TYPE_SPAPR_DR_CONNECTOR); 146382512483SGreg Kurz 146482512483SGreg Kurz if (drc) { 146582512483SGreg Kurz spapr_drc_reset(drc); 146682512483SGreg Kurz } 146782512483SGreg Kurz 146882512483SGreg Kurz return 0; 146982512483SGreg Kurz } 147082512483SGreg Kurz 1471bcb5ce08SDavid Gibson static void spapr_machine_reset(void) 147253018216SPaolo Bonzini { 1473c5f54f3eSDavid Gibson MachineState *machine = MACHINE(qdev_get_machine()); 1474c5f54f3eSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 1475182735efSAndreas Färber PowerPCCPU *first_ppc_cpu; 1476b7d1f77aSBenjamin Herrenschmidt uint32_t rtas_limit; 1477cae172abSDavid Gibson hwaddr rtas_addr, fdt_addr; 1478997b6cfcSDavid Gibson void *fdt; 1479997b6cfcSDavid Gibson int rc; 1480259186a7SAndreas Färber 14819e3f9733SAlexander Graf /* Check for unknown sysbus devices */ 14829e3f9733SAlexander Graf foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL); 14839e3f9733SAlexander Graf 148433face6bSDavid Gibson spapr_caps_reset(spapr); 148533face6bSDavid Gibson 14861481fe5fSLaurent Vivier first_ppc_cpu = POWERPC_CPU(first_cpu); 14871481fe5fSLaurent Vivier if (kvm_enabled() && kvmppc_has_cap_mmu_radix() && 14881481fe5fSLaurent Vivier ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0, 14891481fe5fSLaurent Vivier spapr->max_compat_pvr)) { 1490b4db5413SSuraj Jitindar Singh /* If using KVM with radix mode available, VCPUs can be started 1491b4db5413SSuraj Jitindar Singh * without a HPT because KVM will start them in radix mode. 1492b4db5413SSuraj Jitindar Singh * Set the GR bit in PATB so that we know there is no HPT. */ 1493b4db5413SSuraj Jitindar Singh spapr->patb_entry = PATBE1_GR; 1494b4db5413SSuraj Jitindar Singh } else { 1495b4db5413SSuraj Jitindar Singh spapr_setup_hpt_and_vrma(spapr); 1496c5f54f3eSDavid Gibson } 149753018216SPaolo Bonzini 14989012a53fSGreg Kurz /* if this reset wasn't generated by CAS, we should reset our 14999012a53fSGreg Kurz * negotiated options and start from scratch */ 15009012a53fSGreg Kurz if (!spapr->cas_reboot) { 15019012a53fSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas); 15029012a53fSGreg Kurz spapr->ov5_cas = spapr_ovec_new(); 15039012a53fSGreg Kurz 15049012a53fSGreg Kurz ppc_set_compat(first_ppc_cpu, spapr->max_compat_pvr, &error_fatal); 15059012a53fSGreg Kurz } 15069012a53fSGreg Kurz 150753018216SPaolo Bonzini qemu_devices_reset(); 150882512483SGreg Kurz 150982512483SGreg Kurz /* DRC reset may cause a device to be unplugged. This will cause troubles 151082512483SGreg Kurz * if this device is used by another device (eg, a running vhost backend 151182512483SGreg Kurz * will crash QEMU if the DIMM holding the vring goes away). To avoid such 151282512483SGreg Kurz * situations, we reset DRCs after all devices have been reset. 151382512483SGreg Kurz */ 151482512483SGreg Kurz object_child_foreach_recursive(object_get_root(), spapr_reset_drcs, NULL); 151582512483SGreg Kurz 151656258174SDaniel Henrique Barboza spapr_clear_pending_events(spapr); 151753018216SPaolo Bonzini 1518b7d1f77aSBenjamin Herrenschmidt /* 1519b7d1f77aSBenjamin Herrenschmidt * We place the device tree and RTAS just below either the top of the RMA, 1520b7d1f77aSBenjamin Herrenschmidt * or just below 2GB, whichever is lowere, so that it can be 1521b7d1f77aSBenjamin Herrenschmidt * processed with 32-bit real mode code if necessary 1522b7d1f77aSBenjamin Herrenschmidt */ 1523b7d1f77aSBenjamin Herrenschmidt rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR); 1524cae172abSDavid Gibson rtas_addr = rtas_limit - RTAS_MAX_SIZE; 1525cae172abSDavid Gibson fdt_addr = rtas_addr - FDT_MAX_SIZE; 1526b7d1f77aSBenjamin Herrenschmidt 1527cae172abSDavid Gibson fdt = spapr_build_fdt(spapr, rtas_addr, spapr->rtas_size); 152853018216SPaolo Bonzini 15292cac78c1SDavid Gibson spapr_load_rtas(spapr, fdt, rtas_addr); 1530b7d1f77aSBenjamin Herrenschmidt 1531997b6cfcSDavid Gibson rc = fdt_pack(fdt); 1532997b6cfcSDavid Gibson 1533997b6cfcSDavid Gibson /* Should only fail if we've built a corrupted tree */ 1534997b6cfcSDavid Gibson assert(rc == 0); 1535997b6cfcSDavid Gibson 1536997b6cfcSDavid Gibson if (fdt_totalsize(fdt) > FDT_MAX_SIZE) { 1537997b6cfcSDavid Gibson error_report("FDT too big ! 0x%x bytes (max is 0x%x)", 1538997b6cfcSDavid Gibson fdt_totalsize(fdt), FDT_MAX_SIZE); 1539997b6cfcSDavid Gibson exit(1); 1540997b6cfcSDavid Gibson } 1541997b6cfcSDavid Gibson 1542997b6cfcSDavid Gibson /* Load the fdt */ 1543997b6cfcSDavid Gibson qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 1544cae172abSDavid Gibson cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); 1545997b6cfcSDavid Gibson g_free(fdt); 1546997b6cfcSDavid Gibson 154753018216SPaolo Bonzini /* Set up the entry state */ 1548cae172abSDavid Gibson first_ppc_cpu->env.gpr[3] = fdt_addr; 1549182735efSAndreas Färber first_ppc_cpu->env.gpr[5] = 0; 1550182735efSAndreas Färber first_cpu->halted = 0; 15511b718907SDavid Gibson first_ppc_cpu->env.nip = SPAPR_ENTRY_POINT; 155253018216SPaolo Bonzini 15536787d27bSMichael Roth spapr->cas_reboot = false; 155453018216SPaolo Bonzini } 155553018216SPaolo Bonzini 155628e02042SDavid Gibson static void spapr_create_nvram(sPAPRMachineState *spapr) 155753018216SPaolo Bonzini { 15582ff3de68SMarkus Armbruster DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); 15593978b863SPaolo Bonzini DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); 156053018216SPaolo Bonzini 15613978b863SPaolo Bonzini if (dinfo) { 15626231a6daSMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo), 15636231a6daSMarkus Armbruster &error_fatal); 156453018216SPaolo Bonzini } 156553018216SPaolo Bonzini 156653018216SPaolo Bonzini qdev_init_nofail(dev); 156753018216SPaolo Bonzini 156853018216SPaolo Bonzini spapr->nvram = (struct sPAPRNVRAM *)dev; 156953018216SPaolo Bonzini } 157053018216SPaolo Bonzini 157128e02042SDavid Gibson static void spapr_rtc_create(sPAPRMachineState *spapr) 157228df36a1SDavid Gibson { 1573147ff807SCédric Le Goater object_initialize(&spapr->rtc, sizeof(spapr->rtc), TYPE_SPAPR_RTC); 1574147ff807SCédric Le Goater object_property_add_child(OBJECT(spapr), "rtc", OBJECT(&spapr->rtc), 1575147ff807SCédric Le Goater &error_fatal); 1576147ff807SCédric Le Goater object_property_set_bool(OBJECT(&spapr->rtc), true, "realized", 1577147ff807SCédric Le Goater &error_fatal); 1578147ff807SCédric Le Goater object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc), 1579147ff807SCédric Le Goater "date", &error_fatal); 158028df36a1SDavid Gibson } 158128df36a1SDavid Gibson 158253018216SPaolo Bonzini /* Returns whether we want to use VGA or not */ 158314c6a894SDavid Gibson static bool spapr_vga_init(PCIBus *pci_bus, Error **errp) 158453018216SPaolo Bonzini { 158553018216SPaolo Bonzini switch (vga_interface_type) { 158653018216SPaolo Bonzini case VGA_NONE: 15877effdaa3SMark Wu return false; 15887effdaa3SMark Wu case VGA_DEVICE: 15897effdaa3SMark Wu return true; 159053018216SPaolo Bonzini case VGA_STD: 1591b798c190SBenjamin Herrenschmidt case VGA_VIRTIO: 159253018216SPaolo Bonzini return pci_vga_init(pci_bus) != NULL; 159353018216SPaolo Bonzini default: 159414c6a894SDavid Gibson error_setg(errp, 159514c6a894SDavid Gibson "Unsupported VGA mode, only -vga std or -vga virtio is supported"); 159614c6a894SDavid Gibson return false; 159753018216SPaolo Bonzini } 159853018216SPaolo Bonzini } 159953018216SPaolo Bonzini 16004e5fe368SSuraj Jitindar Singh static int spapr_pre_load(void *opaque) 16014e5fe368SSuraj Jitindar Singh { 16024e5fe368SSuraj Jitindar Singh int rc; 16034e5fe368SSuraj Jitindar Singh 16044e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_load(opaque); 16054e5fe368SSuraj Jitindar Singh if (rc) { 16064e5fe368SSuraj Jitindar Singh return rc; 16074e5fe368SSuraj Jitindar Singh } 16084e5fe368SSuraj Jitindar Singh 16094e5fe368SSuraj Jitindar Singh return 0; 16104e5fe368SSuraj Jitindar Singh } 16114e5fe368SSuraj Jitindar Singh 1612880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id) 1613880ae7deSDavid Gibson { 161428e02042SDavid Gibson sPAPRMachineState *spapr = (sPAPRMachineState *)opaque; 1615880ae7deSDavid Gibson int err = 0; 1616880ae7deSDavid Gibson 1617be85537dSDavid Gibson err = spapr_caps_post_migration(spapr); 1618be85537dSDavid Gibson if (err) { 1619be85537dSDavid Gibson return err; 1620be85537dSDavid Gibson } 1621be85537dSDavid Gibson 1622a7ff1212SCédric Le Goater if (!object_dynamic_cast(OBJECT(spapr->ics), TYPE_ICS_KVM)) { 16235bc8d26dSCédric Le Goater CPUState *cs; 16245bc8d26dSCédric Le Goater CPU_FOREACH(cs) { 16255bc8d26dSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 16265bc8d26dSCédric Le Goater icp_resend(ICP(cpu->intc)); 1627a7ff1212SCédric Le Goater } 1628a7ff1212SCédric Le Goater } 1629a7ff1212SCédric Le Goater 1630631b22eaSStefan Weil /* In earlier versions, there was no separate qdev for the PAPR 1631880ae7deSDavid Gibson * RTC, so the RTC offset was stored directly in sPAPREnvironment. 1632880ae7deSDavid Gibson * So when migrating from those versions, poke the incoming offset 1633880ae7deSDavid Gibson * value into the RTC device */ 1634880ae7deSDavid Gibson if (version_id < 3) { 1635147ff807SCédric Le Goater err = spapr_rtc_import_offset(&spapr->rtc, spapr->rtc_offset); 1636880ae7deSDavid Gibson } 1637880ae7deSDavid Gibson 16380c86b2dfSLaurent Vivier if (kvm_enabled() && spapr->patb_entry) { 1639d39c90f5SBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(first_cpu); 1640d39c90f5SBharata B Rao bool radix = !!(spapr->patb_entry & PATBE1_GR); 1641d39c90f5SBharata B Rao bool gtse = !!(cpu->env.spr[SPR_LPCR] & LPCR_GTSE); 1642d39c90f5SBharata B Rao 1643d39c90f5SBharata B Rao err = kvmppc_configure_v3_mmu(cpu, radix, gtse, spapr->patb_entry); 1644d39c90f5SBharata B Rao if (err) { 1645d39c90f5SBharata B Rao error_report("Process table config unsupported by the host"); 1646d39c90f5SBharata B Rao return -EINVAL; 1647d39c90f5SBharata B Rao } 1648d39c90f5SBharata B Rao } 1649d39c90f5SBharata B Rao 1650880ae7deSDavid Gibson return err; 1651880ae7deSDavid Gibson } 1652880ae7deSDavid Gibson 16534e5fe368SSuraj Jitindar Singh static int spapr_pre_save(void *opaque) 16544e5fe368SSuraj Jitindar Singh { 16554e5fe368SSuraj Jitindar Singh int rc; 16564e5fe368SSuraj Jitindar Singh 16574e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_save(opaque); 16584e5fe368SSuraj Jitindar Singh if (rc) { 16594e5fe368SSuraj Jitindar Singh return rc; 16604e5fe368SSuraj Jitindar Singh } 16614e5fe368SSuraj Jitindar Singh 16624e5fe368SSuraj Jitindar Singh return 0; 16634e5fe368SSuraj Jitindar Singh } 16644e5fe368SSuraj Jitindar Singh 1665880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id) 1666880ae7deSDavid Gibson { 1667880ae7deSDavid Gibson return version_id < 3; 1668880ae7deSDavid Gibson } 1669880ae7deSDavid Gibson 1670fd38804bSDaniel Henrique Barboza static bool spapr_pending_events_needed(void *opaque) 1671fd38804bSDaniel Henrique Barboza { 1672fd38804bSDaniel Henrique Barboza sPAPRMachineState *spapr = (sPAPRMachineState *)opaque; 1673fd38804bSDaniel Henrique Barboza return !QTAILQ_EMPTY(&spapr->pending_events); 1674fd38804bSDaniel Henrique Barboza } 1675fd38804bSDaniel Henrique Barboza 1676fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_event_entry = { 1677fd38804bSDaniel Henrique Barboza .name = "spapr_event_log_entry", 1678fd38804bSDaniel Henrique Barboza .version_id = 1, 1679fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1680fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 16815341258eSDavid Gibson VMSTATE_UINT32(summary, sPAPREventLogEntry), 16825341258eSDavid Gibson VMSTATE_UINT32(extended_length, sPAPREventLogEntry), 1683fd38804bSDaniel Henrique Barboza VMSTATE_VBUFFER_ALLOC_UINT32(extended_log, sPAPREventLogEntry, 0, 16845341258eSDavid Gibson NULL, extended_length), 1685fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1686fd38804bSDaniel Henrique Barboza }, 1687fd38804bSDaniel Henrique Barboza }; 1688fd38804bSDaniel Henrique Barboza 1689fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_pending_events = { 1690fd38804bSDaniel Henrique Barboza .name = "spapr_pending_events", 1691fd38804bSDaniel Henrique Barboza .version_id = 1, 1692fd38804bSDaniel Henrique Barboza .minimum_version_id = 1, 1693fd38804bSDaniel Henrique Barboza .needed = spapr_pending_events_needed, 1694fd38804bSDaniel Henrique Barboza .fields = (VMStateField[]) { 1695fd38804bSDaniel Henrique Barboza VMSTATE_QTAILQ_V(pending_events, sPAPRMachineState, 1, 1696fd38804bSDaniel Henrique Barboza vmstate_spapr_event_entry, sPAPREventLogEntry, next), 1697fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST() 1698fd38804bSDaniel Henrique Barboza }, 1699fd38804bSDaniel Henrique Barboza }; 1700fd38804bSDaniel Henrique Barboza 170162ef3760SMichael Roth static bool spapr_ov5_cas_needed(void *opaque) 170262ef3760SMichael Roth { 170362ef3760SMichael Roth sPAPRMachineState *spapr = opaque; 170462ef3760SMichael Roth sPAPROptionVector *ov5_mask = spapr_ovec_new(); 170562ef3760SMichael Roth sPAPROptionVector *ov5_legacy = spapr_ovec_new(); 170662ef3760SMichael Roth sPAPROptionVector *ov5_removed = spapr_ovec_new(); 170762ef3760SMichael Roth bool cas_needed; 170862ef3760SMichael Roth 170962ef3760SMichael Roth /* Prior to the introduction of sPAPROptionVector, we had two option 171062ef3760SMichael Roth * vectors we dealt with: OV5_FORM1_AFFINITY, and OV5_DRCONF_MEMORY. 171162ef3760SMichael Roth * Both of these options encode machine topology into the device-tree 171262ef3760SMichael Roth * in such a way that the now-booted OS should still be able to interact 171362ef3760SMichael Roth * appropriately with QEMU regardless of what options were actually 171462ef3760SMichael Roth * negotiatied on the source side. 171562ef3760SMichael Roth * 171662ef3760SMichael Roth * As such, we can avoid migrating the CAS-negotiated options if these 171762ef3760SMichael Roth * are the only options available on the current machine/platform. 171862ef3760SMichael Roth * Since these are the only options available for pseries-2.7 and 171962ef3760SMichael Roth * earlier, this allows us to maintain old->new/new->old migration 172062ef3760SMichael Roth * compatibility. 172162ef3760SMichael Roth * 172262ef3760SMichael Roth * For QEMU 2.8+, there are additional CAS-negotiatable options available 172362ef3760SMichael Roth * via default pseries-2.8 machines and explicit command-line parameters. 172462ef3760SMichael Roth * Some of these options, like OV5_HP_EVT, *do* require QEMU to be aware 172562ef3760SMichael Roth * of the actual CAS-negotiated values to continue working properly. For 172662ef3760SMichael Roth * example, availability of memory unplug depends on knowing whether 172762ef3760SMichael Roth * OV5_HP_EVT was negotiated via CAS. 172862ef3760SMichael Roth * 172962ef3760SMichael Roth * Thus, for any cases where the set of available CAS-negotiatable 173062ef3760SMichael Roth * options extends beyond OV5_FORM1_AFFINITY and OV5_DRCONF_MEMORY, we 173162ef3760SMichael Roth * include the CAS-negotiated options in the migration stream. 173262ef3760SMichael Roth */ 173362ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_FORM1_AFFINITY); 173462ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_DRCONF_MEMORY); 173562ef3760SMichael Roth 173662ef3760SMichael Roth /* spapr_ovec_diff returns true if bits were removed. we avoid using 173762ef3760SMichael Roth * the mask itself since in the future it's possible "legacy" bits may be 173862ef3760SMichael Roth * removed via machine options, which could generate a false positive 173962ef3760SMichael Roth * that breaks migration. 174062ef3760SMichael Roth */ 174162ef3760SMichael Roth spapr_ovec_intersect(ov5_legacy, spapr->ov5, ov5_mask); 174262ef3760SMichael Roth cas_needed = spapr_ovec_diff(ov5_removed, spapr->ov5, ov5_legacy); 174362ef3760SMichael Roth 174462ef3760SMichael Roth spapr_ovec_cleanup(ov5_mask); 174562ef3760SMichael Roth spapr_ovec_cleanup(ov5_legacy); 174662ef3760SMichael Roth spapr_ovec_cleanup(ov5_removed); 174762ef3760SMichael Roth 174862ef3760SMichael Roth return cas_needed; 174962ef3760SMichael Roth } 175062ef3760SMichael Roth 175162ef3760SMichael Roth static const VMStateDescription vmstate_spapr_ov5_cas = { 175262ef3760SMichael Roth .name = "spapr_option_vector_ov5_cas", 175362ef3760SMichael Roth .version_id = 1, 175462ef3760SMichael Roth .minimum_version_id = 1, 175562ef3760SMichael Roth .needed = spapr_ov5_cas_needed, 175662ef3760SMichael Roth .fields = (VMStateField[]) { 175762ef3760SMichael Roth VMSTATE_STRUCT_POINTER_V(ov5_cas, sPAPRMachineState, 1, 175862ef3760SMichael Roth vmstate_spapr_ovec, sPAPROptionVector), 175962ef3760SMichael Roth VMSTATE_END_OF_LIST() 176062ef3760SMichael Roth }, 176162ef3760SMichael Roth }; 176262ef3760SMichael Roth 17639861bb3eSSuraj Jitindar Singh static bool spapr_patb_entry_needed(void *opaque) 17649861bb3eSSuraj Jitindar Singh { 17659861bb3eSSuraj Jitindar Singh sPAPRMachineState *spapr = opaque; 17669861bb3eSSuraj Jitindar Singh 17679861bb3eSSuraj Jitindar Singh return !!spapr->patb_entry; 17689861bb3eSSuraj Jitindar Singh } 17699861bb3eSSuraj Jitindar Singh 17709861bb3eSSuraj Jitindar Singh static const VMStateDescription vmstate_spapr_patb_entry = { 17719861bb3eSSuraj Jitindar Singh .name = "spapr_patb_entry", 17729861bb3eSSuraj Jitindar Singh .version_id = 1, 17739861bb3eSSuraj Jitindar Singh .minimum_version_id = 1, 17749861bb3eSSuraj Jitindar Singh .needed = spapr_patb_entry_needed, 17759861bb3eSSuraj Jitindar Singh .fields = (VMStateField[]) { 17769861bb3eSSuraj Jitindar Singh VMSTATE_UINT64(patb_entry, sPAPRMachineState), 17779861bb3eSSuraj Jitindar Singh VMSTATE_END_OF_LIST() 17789861bb3eSSuraj Jitindar Singh }, 17799861bb3eSSuraj Jitindar Singh }; 17809861bb3eSSuraj Jitindar Singh 17814be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = { 17824be21d56SDavid Gibson .name = "spapr", 1783880ae7deSDavid Gibson .version_id = 3, 17844be21d56SDavid Gibson .minimum_version_id = 1, 17854e5fe368SSuraj Jitindar Singh .pre_load = spapr_pre_load, 1786880ae7deSDavid Gibson .post_load = spapr_post_load, 17874e5fe368SSuraj Jitindar Singh .pre_save = spapr_pre_save, 17884be21d56SDavid Gibson .fields = (VMStateField[]) { 1789880ae7deSDavid Gibson /* used to be @next_irq */ 1790880ae7deSDavid Gibson VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4), 17914be21d56SDavid Gibson 17924be21d56SDavid Gibson /* RTC offset */ 179328e02042SDavid Gibson VMSTATE_UINT64_TEST(rtc_offset, sPAPRMachineState, version_before_3), 1794880ae7deSDavid Gibson 179528e02042SDavid Gibson VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2), 17964be21d56SDavid Gibson VMSTATE_END_OF_LIST() 17974be21d56SDavid Gibson }, 179862ef3760SMichael Roth .subsections = (const VMStateDescription*[]) { 179962ef3760SMichael Roth &vmstate_spapr_ov5_cas, 18009861bb3eSSuraj Jitindar Singh &vmstate_spapr_patb_entry, 1801fd38804bSDaniel Henrique Barboza &vmstate_spapr_pending_events, 18024e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_htm, 18034e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_vsx, 18044e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_dfp, 18058f38eaf8SSuraj Jitindar Singh &vmstate_spapr_cap_cfpc, 180609114fd8SSuraj Jitindar Singh &vmstate_spapr_cap_sbbc, 18074be8d4e7SSuraj Jitindar Singh &vmstate_spapr_cap_ibs, 180862ef3760SMichael Roth NULL 180962ef3760SMichael Roth } 18104be21d56SDavid Gibson }; 18114be21d56SDavid Gibson 18124be21d56SDavid Gibson static int htab_save_setup(QEMUFile *f, void *opaque) 18134be21d56SDavid Gibson { 181428e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 18154be21d56SDavid Gibson 18164be21d56SDavid Gibson /* "Iteration" header */ 18173a384297SBharata B Rao if (!spapr->htab_shift) { 18183a384297SBharata B Rao qemu_put_be32(f, -1); 18193a384297SBharata B Rao } else { 18204be21d56SDavid Gibson qemu_put_be32(f, spapr->htab_shift); 18213a384297SBharata B Rao } 18224be21d56SDavid Gibson 1823e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 1824e68cb8b4SAlexey Kardashevskiy spapr->htab_save_index = 0; 1825e68cb8b4SAlexey Kardashevskiy spapr->htab_first_pass = true; 1826e68cb8b4SAlexey Kardashevskiy } else { 18273a384297SBharata B Rao if (spapr->htab_shift) { 1828e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 18294be21d56SDavid Gibson } 18303a384297SBharata B Rao } 18314be21d56SDavid Gibson 1832e68cb8b4SAlexey Kardashevskiy 1833e68cb8b4SAlexey Kardashevskiy return 0; 1834e68cb8b4SAlexey Kardashevskiy } 18354be21d56SDavid Gibson 1836332f7721SGreg Kurz static void htab_save_chunk(QEMUFile *f, sPAPRMachineState *spapr, 1837332f7721SGreg Kurz int chunkstart, int n_valid, int n_invalid) 1838332f7721SGreg Kurz { 1839332f7721SGreg Kurz qemu_put_be32(f, chunkstart); 1840332f7721SGreg Kurz qemu_put_be16(f, n_valid); 1841332f7721SGreg Kurz qemu_put_be16(f, n_invalid); 1842332f7721SGreg Kurz qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 1843332f7721SGreg Kurz HASH_PTE_SIZE_64 * n_valid); 1844332f7721SGreg Kurz } 1845332f7721SGreg Kurz 1846332f7721SGreg Kurz static void htab_save_end_marker(QEMUFile *f) 1847332f7721SGreg Kurz { 1848332f7721SGreg Kurz qemu_put_be32(f, 0); 1849332f7721SGreg Kurz qemu_put_be16(f, 0); 1850332f7721SGreg Kurz qemu_put_be16(f, 0); 1851332f7721SGreg Kurz } 1852332f7721SGreg Kurz 185328e02042SDavid Gibson static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr, 18544be21d56SDavid Gibson int64_t max_ns) 18554be21d56SDavid Gibson { 1856378bc217SDavid Gibson bool has_timeout = max_ns != -1; 18574be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 18584be21d56SDavid Gibson int index = spapr->htab_save_index; 1859bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 18604be21d56SDavid Gibson 18614be21d56SDavid Gibson assert(spapr->htab_first_pass); 18624be21d56SDavid Gibson 18634be21d56SDavid Gibson do { 18644be21d56SDavid Gibson int chunkstart; 18654be21d56SDavid Gibson 18664be21d56SDavid Gibson /* Consume invalid HPTEs */ 18674be21d56SDavid Gibson while ((index < htabslots) 18684be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 18694be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 187024ec2863SMarc-André Lureau index++; 18714be21d56SDavid Gibson } 18724be21d56SDavid Gibson 18734be21d56SDavid Gibson /* Consume valid HPTEs */ 18744be21d56SDavid Gibson chunkstart = index; 1875338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 18764be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 18774be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 187824ec2863SMarc-André Lureau index++; 18794be21d56SDavid Gibson } 18804be21d56SDavid Gibson 18814be21d56SDavid Gibson if (index > chunkstart) { 18824be21d56SDavid Gibson int n_valid = index - chunkstart; 18834be21d56SDavid Gibson 1884332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, 0); 18854be21d56SDavid Gibson 1886378bc217SDavid Gibson if (has_timeout && 1887378bc217SDavid Gibson (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 18884be21d56SDavid Gibson break; 18894be21d56SDavid Gibson } 18904be21d56SDavid Gibson } 18914be21d56SDavid Gibson } while ((index < htabslots) && !qemu_file_rate_limit(f)); 18924be21d56SDavid Gibson 18934be21d56SDavid Gibson if (index >= htabslots) { 18944be21d56SDavid Gibson assert(index == htabslots); 18954be21d56SDavid Gibson index = 0; 18964be21d56SDavid Gibson spapr->htab_first_pass = false; 18974be21d56SDavid Gibson } 18984be21d56SDavid Gibson spapr->htab_save_index = index; 18994be21d56SDavid Gibson } 19004be21d56SDavid Gibson 190128e02042SDavid Gibson static int htab_save_later_pass(QEMUFile *f, sPAPRMachineState *spapr, 19024be21d56SDavid Gibson int64_t max_ns) 19034be21d56SDavid Gibson { 19044be21d56SDavid Gibson bool final = max_ns < 0; 19054be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 19064be21d56SDavid Gibson int examined = 0, sent = 0; 19074be21d56SDavid Gibson int index = spapr->htab_save_index; 1908bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 19094be21d56SDavid Gibson 19104be21d56SDavid Gibson assert(!spapr->htab_first_pass); 19114be21d56SDavid Gibson 19124be21d56SDavid Gibson do { 19134be21d56SDavid Gibson int chunkstart, invalidstart; 19144be21d56SDavid Gibson 19154be21d56SDavid Gibson /* Consume non-dirty HPTEs */ 19164be21d56SDavid Gibson while ((index < htabslots) 19174be21d56SDavid Gibson && !HPTE_DIRTY(HPTE(spapr->htab, index))) { 19184be21d56SDavid Gibson index++; 19194be21d56SDavid Gibson examined++; 19204be21d56SDavid Gibson } 19214be21d56SDavid Gibson 19224be21d56SDavid Gibson chunkstart = index; 19234be21d56SDavid Gibson /* Consume valid dirty HPTEs */ 1924338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 19254be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 19264be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 19274be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 19284be21d56SDavid Gibson index++; 19294be21d56SDavid Gibson examined++; 19304be21d56SDavid Gibson } 19314be21d56SDavid Gibson 19324be21d56SDavid Gibson invalidstart = index; 19334be21d56SDavid Gibson /* Consume invalid dirty HPTEs */ 1934338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - invalidstart < USHRT_MAX) 19354be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 19364be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 19374be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 19384be21d56SDavid Gibson index++; 19394be21d56SDavid Gibson examined++; 19404be21d56SDavid Gibson } 19414be21d56SDavid Gibson 19424be21d56SDavid Gibson if (index > chunkstart) { 19434be21d56SDavid Gibson int n_valid = invalidstart - chunkstart; 19444be21d56SDavid Gibson int n_invalid = index - invalidstart; 19454be21d56SDavid Gibson 1946332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, n_invalid); 19474be21d56SDavid Gibson sent += index - chunkstart; 19484be21d56SDavid Gibson 1949bc72ad67SAlex Bligh if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 19504be21d56SDavid Gibson break; 19514be21d56SDavid Gibson } 19524be21d56SDavid Gibson } 19534be21d56SDavid Gibson 19544be21d56SDavid Gibson if (examined >= htabslots) { 19554be21d56SDavid Gibson break; 19564be21d56SDavid Gibson } 19574be21d56SDavid Gibson 19584be21d56SDavid Gibson if (index >= htabslots) { 19594be21d56SDavid Gibson assert(index == htabslots); 19604be21d56SDavid Gibson index = 0; 19614be21d56SDavid Gibson } 19624be21d56SDavid Gibson } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final)); 19634be21d56SDavid Gibson 19644be21d56SDavid Gibson if (index >= htabslots) { 19654be21d56SDavid Gibson assert(index == htabslots); 19664be21d56SDavid Gibson index = 0; 19674be21d56SDavid Gibson } 19684be21d56SDavid Gibson 19694be21d56SDavid Gibson spapr->htab_save_index = index; 19704be21d56SDavid Gibson 1971e68cb8b4SAlexey Kardashevskiy return (examined >= htabslots) && (sent == 0) ? 1 : 0; 19724be21d56SDavid Gibson } 19734be21d56SDavid Gibson 1974e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS 5000000 /* 5 ms */ 1975e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE 2048 1976e68cb8b4SAlexey Kardashevskiy 19774be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque) 19784be21d56SDavid Gibson { 197928e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 1980715c5407SDavid Gibson int fd; 1981e68cb8b4SAlexey Kardashevskiy int rc = 0; 19824be21d56SDavid Gibson 19834be21d56SDavid Gibson /* Iteration header */ 19843a384297SBharata B Rao if (!spapr->htab_shift) { 19853a384297SBharata B Rao qemu_put_be32(f, -1); 1986e8cd4247SLaurent Vivier return 1; 19873a384297SBharata B Rao } else { 19884be21d56SDavid Gibson qemu_put_be32(f, 0); 19893a384297SBharata B Rao } 19904be21d56SDavid Gibson 1991e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1992e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1993e68cb8b4SAlexey Kardashevskiy 1994715c5407SDavid Gibson fd = get_htab_fd(spapr); 1995715c5407SDavid Gibson if (fd < 0) { 1996715c5407SDavid Gibson return fd; 199701a57972SSamuel Mendoza-Jonas } 199801a57972SSamuel Mendoza-Jonas 1999715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); 2000e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2001e68cb8b4SAlexey Kardashevskiy return rc; 2002e68cb8b4SAlexey Kardashevskiy } 2003e68cb8b4SAlexey Kardashevskiy } else if (spapr->htab_first_pass) { 20044be21d56SDavid Gibson htab_save_first_pass(f, spapr, MAX_ITERATION_NS); 20054be21d56SDavid Gibson } else { 2006e68cb8b4SAlexey Kardashevskiy rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS); 20074be21d56SDavid Gibson } 20084be21d56SDavid Gibson 2009332f7721SGreg Kurz htab_save_end_marker(f); 20104be21d56SDavid Gibson 2011e68cb8b4SAlexey Kardashevskiy return rc; 20124be21d56SDavid Gibson } 20134be21d56SDavid Gibson 20144be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque) 20154be21d56SDavid Gibson { 201628e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 2017715c5407SDavid Gibson int fd; 20184be21d56SDavid Gibson 20194be21d56SDavid Gibson /* Iteration header */ 20203a384297SBharata B Rao if (!spapr->htab_shift) { 20213a384297SBharata B Rao qemu_put_be32(f, -1); 20223a384297SBharata B Rao return 0; 20233a384297SBharata B Rao } else { 20244be21d56SDavid Gibson qemu_put_be32(f, 0); 20253a384297SBharata B Rao } 20264be21d56SDavid Gibson 2027e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2028e68cb8b4SAlexey Kardashevskiy int rc; 2029e68cb8b4SAlexey Kardashevskiy 2030e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2031e68cb8b4SAlexey Kardashevskiy 2032715c5407SDavid Gibson fd = get_htab_fd(spapr); 2033715c5407SDavid Gibson if (fd < 0) { 2034715c5407SDavid Gibson return fd; 203501a57972SSamuel Mendoza-Jonas } 203601a57972SSamuel Mendoza-Jonas 2037715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1); 2038e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2039e68cb8b4SAlexey Kardashevskiy return rc; 2040e68cb8b4SAlexey Kardashevskiy } 2041e68cb8b4SAlexey Kardashevskiy } else { 2042378bc217SDavid Gibson if (spapr->htab_first_pass) { 2043378bc217SDavid Gibson htab_save_first_pass(f, spapr, -1); 2044378bc217SDavid Gibson } 20454be21d56SDavid Gibson htab_save_later_pass(f, spapr, -1); 2046e68cb8b4SAlexey Kardashevskiy } 20474be21d56SDavid Gibson 20484be21d56SDavid Gibson /* End marker */ 2049332f7721SGreg Kurz htab_save_end_marker(f); 20504be21d56SDavid Gibson 20514be21d56SDavid Gibson return 0; 20524be21d56SDavid Gibson } 20534be21d56SDavid Gibson 20544be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id) 20554be21d56SDavid Gibson { 205628e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 20574be21d56SDavid Gibson uint32_t section_hdr; 2058e68cb8b4SAlexey Kardashevskiy int fd = -1; 205914b0d748SGreg Kurz Error *local_err = NULL; 20604be21d56SDavid Gibson 20614be21d56SDavid Gibson if (version_id < 1 || version_id > 1) { 206298a5d100SDavid Gibson error_report("htab_load() bad version"); 20634be21d56SDavid Gibson return -EINVAL; 20644be21d56SDavid Gibson } 20654be21d56SDavid Gibson 20664be21d56SDavid Gibson section_hdr = qemu_get_be32(f); 20674be21d56SDavid Gibson 20683a384297SBharata B Rao if (section_hdr == -1) { 20693a384297SBharata B Rao spapr_free_hpt(spapr); 20703a384297SBharata B Rao return 0; 20713a384297SBharata B Rao } 20723a384297SBharata B Rao 20734be21d56SDavid Gibson if (section_hdr) { 2074c5f54f3eSDavid Gibson /* First section gives the htab size */ 2075c5f54f3eSDavid Gibson spapr_reallocate_hpt(spapr, section_hdr, &local_err); 2076c5f54f3eSDavid Gibson if (local_err) { 2077c5f54f3eSDavid Gibson error_report_err(local_err); 20784be21d56SDavid Gibson return -EINVAL; 20794be21d56SDavid Gibson } 20804be21d56SDavid Gibson return 0; 20814be21d56SDavid Gibson } 20824be21d56SDavid Gibson 2083e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2084e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 2085e68cb8b4SAlexey Kardashevskiy 208614b0d748SGreg Kurz fd = kvmppc_get_htab_fd(true, 0, &local_err); 2087e68cb8b4SAlexey Kardashevskiy if (fd < 0) { 208814b0d748SGreg Kurz error_report_err(local_err); 208982be8e73SGreg Kurz return fd; 2090e68cb8b4SAlexey Kardashevskiy } 2091e68cb8b4SAlexey Kardashevskiy } 2092e68cb8b4SAlexey Kardashevskiy 20934be21d56SDavid Gibson while (true) { 20944be21d56SDavid Gibson uint32_t index; 20954be21d56SDavid Gibson uint16_t n_valid, n_invalid; 20964be21d56SDavid Gibson 20974be21d56SDavid Gibson index = qemu_get_be32(f); 20984be21d56SDavid Gibson n_valid = qemu_get_be16(f); 20994be21d56SDavid Gibson n_invalid = qemu_get_be16(f); 21004be21d56SDavid Gibson 21014be21d56SDavid Gibson if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) { 21024be21d56SDavid Gibson /* End of Stream */ 21034be21d56SDavid Gibson break; 21044be21d56SDavid Gibson } 21054be21d56SDavid Gibson 2106e68cb8b4SAlexey Kardashevskiy if ((index + n_valid + n_invalid) > 21074be21d56SDavid Gibson (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) { 21084be21d56SDavid Gibson /* Bad index in stream */ 210998a5d100SDavid Gibson error_report( 211098a5d100SDavid Gibson "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)", 211198a5d100SDavid Gibson index, n_valid, n_invalid, spapr->htab_shift); 21124be21d56SDavid Gibson return -EINVAL; 21134be21d56SDavid Gibson } 21144be21d56SDavid Gibson 2115e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 21164be21d56SDavid Gibson if (n_valid) { 21174be21d56SDavid Gibson qemu_get_buffer(f, HPTE(spapr->htab, index), 21184be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 21194be21d56SDavid Gibson } 21204be21d56SDavid Gibson if (n_invalid) { 21214be21d56SDavid Gibson memset(HPTE(spapr->htab, index + n_valid), 0, 21224be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_invalid); 21234be21d56SDavid Gibson } 2124e68cb8b4SAlexey Kardashevskiy } else { 2125e68cb8b4SAlexey Kardashevskiy int rc; 2126e68cb8b4SAlexey Kardashevskiy 2127e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2128e68cb8b4SAlexey Kardashevskiy 2129e68cb8b4SAlexey Kardashevskiy rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid); 2130e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2131e68cb8b4SAlexey Kardashevskiy return rc; 2132e68cb8b4SAlexey Kardashevskiy } 2133e68cb8b4SAlexey Kardashevskiy } 2134e68cb8b4SAlexey Kardashevskiy } 2135e68cb8b4SAlexey Kardashevskiy 2136e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 2137e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 2138e68cb8b4SAlexey Kardashevskiy close(fd); 21394be21d56SDavid Gibson } 21404be21d56SDavid Gibson 21414be21d56SDavid Gibson return 0; 21424be21d56SDavid Gibson } 21434be21d56SDavid Gibson 214470f794fcSJuan Quintela static void htab_save_cleanup(void *opaque) 2145c573fc03SThomas Huth { 2146c573fc03SThomas Huth sPAPRMachineState *spapr = opaque; 2147c573fc03SThomas Huth 2148c573fc03SThomas Huth close_htab_fd(spapr); 2149c573fc03SThomas Huth } 2150c573fc03SThomas Huth 21514be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = { 21529907e842SJuan Quintela .save_setup = htab_save_setup, 21534be21d56SDavid Gibson .save_live_iterate = htab_save_iterate, 2154a3e06c3dSDr. David Alan Gilbert .save_live_complete_precopy = htab_save_complete, 215570f794fcSJuan Quintela .save_cleanup = htab_save_cleanup, 21564be21d56SDavid Gibson .load_state = htab_load, 21574be21d56SDavid Gibson }; 21584be21d56SDavid Gibson 21595b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device, 21605b2128d2SAlexander Graf Error **errp) 21615b2128d2SAlexander Graf { 2162c86c1affSDaniel Henrique Barboza MachineState *machine = MACHINE(opaque); 21635b2128d2SAlexander Graf machine->boot_order = g_strdup(boot_device); 21645b2128d2SAlexander Graf } 21655b2128d2SAlexander Graf 2166224245bfSDavid Gibson static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr) 2167224245bfSDavid Gibson { 2168224245bfSDavid Gibson MachineState *machine = MACHINE(spapr); 2169224245bfSDavid Gibson uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 2170e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 2171224245bfSDavid Gibson int i; 2172224245bfSDavid Gibson 2173224245bfSDavid Gibson for (i = 0; i < nr_lmbs; i++) { 2174224245bfSDavid Gibson uint64_t addr; 2175224245bfSDavid Gibson 2176e8f986fcSBharata B Rao addr = i * lmb_size + spapr->hotplug_memory.base; 21776caf3ac6SDavid Gibson spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_LMB, 2178224245bfSDavid Gibson addr / lmb_size); 2179224245bfSDavid Gibson } 2180224245bfSDavid Gibson } 2181224245bfSDavid Gibson 2182224245bfSDavid Gibson /* 2183224245bfSDavid Gibson * If RAM size, maxmem size and individual node mem sizes aren't aligned 2184224245bfSDavid Gibson * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest 2185224245bfSDavid Gibson * since we can't support such unaligned sizes with DRCONF_MEMORY. 2186224245bfSDavid Gibson */ 21877c150d6fSDavid Gibson static void spapr_validate_node_memory(MachineState *machine, Error **errp) 2188224245bfSDavid Gibson { 2189224245bfSDavid Gibson int i; 2190224245bfSDavid Gibson 21917c150d6fSDavid Gibson if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) { 21927c150d6fSDavid Gibson error_setg(errp, "Memory size 0x" RAM_ADDR_FMT 21937c150d6fSDavid Gibson " is not aligned to %llu MiB", 21947c150d6fSDavid Gibson machine->ram_size, 2195224245bfSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 21967c150d6fSDavid Gibson return; 21977c150d6fSDavid Gibson } 21987c150d6fSDavid Gibson 21997c150d6fSDavid Gibson if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) { 22007c150d6fSDavid Gibson error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT 22017c150d6fSDavid Gibson " is not aligned to %llu MiB", 22027c150d6fSDavid Gibson machine->ram_size, 22037c150d6fSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 22047c150d6fSDavid Gibson return; 2205224245bfSDavid Gibson } 2206224245bfSDavid Gibson 2207224245bfSDavid Gibson for (i = 0; i < nb_numa_nodes; i++) { 2208224245bfSDavid Gibson if (numa_info[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) { 22097c150d6fSDavid Gibson error_setg(errp, 22107c150d6fSDavid Gibson "Node %d memory size 0x%" PRIx64 22117c150d6fSDavid Gibson " is not aligned to %llu MiB", 22127c150d6fSDavid Gibson i, numa_info[i].node_mem, 2213224245bfSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 22147c150d6fSDavid Gibson return; 2215224245bfSDavid Gibson } 2216224245bfSDavid Gibson } 2217224245bfSDavid Gibson } 2218224245bfSDavid Gibson 2219535455fdSIgor Mammedov /* find cpu slot in machine->possible_cpus by core_id */ 2220535455fdSIgor Mammedov static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx) 2221535455fdSIgor Mammedov { 2222535455fdSIgor Mammedov int index = id / smp_threads; 2223535455fdSIgor Mammedov 2224535455fdSIgor Mammedov if (index >= ms->possible_cpus->len) { 2225535455fdSIgor Mammedov return NULL; 2226535455fdSIgor Mammedov } 2227535455fdSIgor Mammedov if (idx) { 2228535455fdSIgor Mammedov *idx = index; 2229535455fdSIgor Mammedov } 2230535455fdSIgor Mammedov return &ms->possible_cpus->cpus[index]; 2231535455fdSIgor Mammedov } 2232535455fdSIgor Mammedov 2233fa98fbfcSSam Bobroff static void spapr_set_vsmt_mode(sPAPRMachineState *spapr, Error **errp) 2234fa98fbfcSSam Bobroff { 2235fa98fbfcSSam Bobroff Error *local_err = NULL; 2236fa98fbfcSSam Bobroff bool vsmt_user = !!spapr->vsmt; 2237fa98fbfcSSam Bobroff int kvm_smt = kvmppc_smt_threads(); 2238fa98fbfcSSam Bobroff int ret; 2239fa98fbfcSSam Bobroff 2240fa98fbfcSSam Bobroff if (!kvm_enabled() && (smp_threads > 1)) { 2241fa98fbfcSSam Bobroff error_setg(&local_err, "TCG cannot support more than 1 thread/core " 2242fa98fbfcSSam Bobroff "on a pseries machine"); 2243fa98fbfcSSam Bobroff goto out; 2244fa98fbfcSSam Bobroff } 2245fa98fbfcSSam Bobroff if (!is_power_of_2(smp_threads)) { 2246fa98fbfcSSam Bobroff error_setg(&local_err, "Cannot support %d threads/core on a pseries " 2247fa98fbfcSSam Bobroff "machine because it must be a power of 2", smp_threads); 2248fa98fbfcSSam Bobroff goto out; 2249fa98fbfcSSam Bobroff } 2250fa98fbfcSSam Bobroff 2251fa98fbfcSSam Bobroff /* Detemine the VSMT mode to use: */ 2252fa98fbfcSSam Bobroff if (vsmt_user) { 2253fa98fbfcSSam Bobroff if (spapr->vsmt < smp_threads) { 2254fa98fbfcSSam Bobroff error_setg(&local_err, "Cannot support VSMT mode %d" 2255fa98fbfcSSam Bobroff " because it must be >= threads/core (%d)", 2256fa98fbfcSSam Bobroff spapr->vsmt, smp_threads); 2257fa98fbfcSSam Bobroff goto out; 2258fa98fbfcSSam Bobroff } 2259fa98fbfcSSam Bobroff /* In this case, spapr->vsmt has been set by the command line */ 2260fa98fbfcSSam Bobroff } else { 22618904e5a7SDavid Gibson /* 22628904e5a7SDavid Gibson * Default VSMT value is tricky, because we need it to be as 22638904e5a7SDavid Gibson * consistent as possible (for migration), but this requires 22648904e5a7SDavid Gibson * changing it for at least some existing cases. We pick 8 as 22658904e5a7SDavid Gibson * the value that we'd get with KVM on POWER8, the 22668904e5a7SDavid Gibson * overwhelmingly common case in production systems. 22678904e5a7SDavid Gibson */ 22684ad64cbdSLaurent Vivier spapr->vsmt = MAX(8, smp_threads); 2269fa98fbfcSSam Bobroff } 2270fa98fbfcSSam Bobroff 2271fa98fbfcSSam Bobroff /* KVM: If necessary, set the SMT mode: */ 2272fa98fbfcSSam Bobroff if (kvm_enabled() && (spapr->vsmt != kvm_smt)) { 2273fa98fbfcSSam Bobroff ret = kvmppc_set_smt_threads(spapr->vsmt); 2274fa98fbfcSSam Bobroff if (ret) { 22751f20f2e0SDavid Gibson /* Looks like KVM isn't able to change VSMT mode */ 2276fa98fbfcSSam Bobroff error_setg(&local_err, 2277fa98fbfcSSam Bobroff "Failed to set KVM's VSMT mode to %d (errno %d)", 2278fa98fbfcSSam Bobroff spapr->vsmt, ret); 22791f20f2e0SDavid Gibson /* We can live with that if the default one is big enough 22801f20f2e0SDavid Gibson * for the number of threads, and a submultiple of the one 22811f20f2e0SDavid Gibson * we want. In this case we'll waste some vcpu ids, but 22821f20f2e0SDavid Gibson * behaviour will be correct */ 22831f20f2e0SDavid Gibson if ((kvm_smt >= smp_threads) && ((spapr->vsmt % kvm_smt) == 0)) { 22841f20f2e0SDavid Gibson warn_report_err(local_err); 22851f20f2e0SDavid Gibson local_err = NULL; 22861f20f2e0SDavid Gibson goto out; 22871f20f2e0SDavid Gibson } else { 2288fa98fbfcSSam Bobroff if (!vsmt_user) { 22891f20f2e0SDavid Gibson error_append_hint(&local_err, 22901f20f2e0SDavid Gibson "On PPC, a VM with %d threads/core" 22911f20f2e0SDavid Gibson " on a host with %d threads/core" 22921f20f2e0SDavid Gibson " requires the use of VSMT mode %d.\n", 2293fa98fbfcSSam Bobroff smp_threads, kvm_smt, spapr->vsmt); 2294fa98fbfcSSam Bobroff } 2295fa98fbfcSSam Bobroff kvmppc_hint_smt_possible(&local_err); 2296fa98fbfcSSam Bobroff goto out; 2297fa98fbfcSSam Bobroff } 2298fa98fbfcSSam Bobroff } 22991f20f2e0SDavid Gibson } 2300fa98fbfcSSam Bobroff /* else TCG: nothing to do currently */ 2301fa98fbfcSSam Bobroff out: 2302fa98fbfcSSam Bobroff error_propagate(errp, local_err); 2303fa98fbfcSSam Bobroff } 2304fa98fbfcSSam Bobroff 23051a5008fcSGreg Kurz static void spapr_init_cpus(sPAPRMachineState *spapr) 23061a5008fcSGreg Kurz { 23071a5008fcSGreg Kurz MachineState *machine = MACHINE(spapr); 23081a5008fcSGreg Kurz MachineClass *mc = MACHINE_GET_CLASS(machine); 23091a5008fcSGreg Kurz sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 23101a5008fcSGreg Kurz const char *type = spapr_get_cpu_core_type(machine->cpu_type); 23111a5008fcSGreg Kurz const CPUArchIdList *possible_cpus; 23121a5008fcSGreg Kurz int boot_cores_nr = smp_cpus / smp_threads; 23131a5008fcSGreg Kurz int i; 23141a5008fcSGreg Kurz 23151a5008fcSGreg Kurz possible_cpus = mc->possible_cpu_arch_ids(machine); 23161a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 23171a5008fcSGreg Kurz if (smp_cpus % smp_threads) { 23181a5008fcSGreg Kurz error_report("smp_cpus (%u) must be multiple of threads (%u)", 23191a5008fcSGreg Kurz smp_cpus, smp_threads); 23201a5008fcSGreg Kurz exit(1); 23211a5008fcSGreg Kurz } 23221a5008fcSGreg Kurz if (max_cpus % smp_threads) { 23231a5008fcSGreg Kurz error_report("max_cpus (%u) must be multiple of threads (%u)", 23241a5008fcSGreg Kurz max_cpus, smp_threads); 23251a5008fcSGreg Kurz exit(1); 23261a5008fcSGreg Kurz } 23271a5008fcSGreg Kurz } else { 23281a5008fcSGreg Kurz if (max_cpus != smp_cpus) { 23291a5008fcSGreg Kurz error_report("This machine version does not support CPU hotplug"); 23301a5008fcSGreg Kurz exit(1); 23311a5008fcSGreg Kurz } 23321a5008fcSGreg Kurz boot_cores_nr = possible_cpus->len; 23331a5008fcSGreg Kurz } 23341a5008fcSGreg Kurz 23351a5008fcSGreg Kurz /* VSMT must be set in order to be able to compute VCPU ids, ie to 23361a5008fcSGreg Kurz * call xics_max_server_number() or spapr_vcpu_id(). 23371a5008fcSGreg Kurz */ 23381a5008fcSGreg Kurz spapr_set_vsmt_mode(spapr, &error_fatal); 23391a5008fcSGreg Kurz 23401a5008fcSGreg Kurz if (smc->pre_2_10_has_unused_icps) { 23411a5008fcSGreg Kurz int i; 23421a5008fcSGreg Kurz 23431a5008fcSGreg Kurz for (i = 0; i < xics_max_server_number(spapr); i++) { 23441a5008fcSGreg Kurz /* Dummy entries get deregistered when real ICPState objects 23451a5008fcSGreg Kurz * are registered during CPU core hotplug. 23461a5008fcSGreg Kurz */ 23471a5008fcSGreg Kurz pre_2_10_vmstate_register_dummy_icp(i); 23481a5008fcSGreg Kurz } 23491a5008fcSGreg Kurz } 23501a5008fcSGreg Kurz 23511a5008fcSGreg Kurz for (i = 0; i < possible_cpus->len; i++) { 23521a5008fcSGreg Kurz int core_id = i * smp_threads; 23531a5008fcSGreg Kurz 23541a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) { 23551a5008fcSGreg Kurz spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU, 23561a5008fcSGreg Kurz spapr_vcpu_id(spapr, core_id)); 23571a5008fcSGreg Kurz } 23581a5008fcSGreg Kurz 23591a5008fcSGreg Kurz if (i < boot_cores_nr) { 23601a5008fcSGreg Kurz Object *core = object_new(type); 23611a5008fcSGreg Kurz int nr_threads = smp_threads; 23621a5008fcSGreg Kurz 23631a5008fcSGreg Kurz /* Handle the partially filled core for older machine types */ 23641a5008fcSGreg Kurz if ((i + 1) * smp_threads >= smp_cpus) { 23651a5008fcSGreg Kurz nr_threads = smp_cpus - i * smp_threads; 23661a5008fcSGreg Kurz } 23671a5008fcSGreg Kurz 23681a5008fcSGreg Kurz object_property_set_int(core, nr_threads, "nr-threads", 23691a5008fcSGreg Kurz &error_fatal); 23701a5008fcSGreg Kurz object_property_set_int(core, core_id, CPU_CORE_PROP_CORE_ID, 23711a5008fcSGreg Kurz &error_fatal); 23721a5008fcSGreg Kurz object_property_set_bool(core, true, "realized", &error_fatal); 23731a5008fcSGreg Kurz } 23741a5008fcSGreg Kurz } 23751a5008fcSGreg Kurz } 23761a5008fcSGreg Kurz 237753018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */ 2378bcb5ce08SDavid Gibson static void spapr_machine_init(MachineState *machine) 237953018216SPaolo Bonzini { 238028e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 2381224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 23823ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 23833ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 238453018216SPaolo Bonzini PCIHostState *phb; 238553018216SPaolo Bonzini int i; 238653018216SPaolo Bonzini MemoryRegion *sysmem = get_system_memory(); 238753018216SPaolo Bonzini MemoryRegion *ram = g_new(MemoryRegion, 1); 2388658fa66bSAlexey Kardashevskiy MemoryRegion *rma_region; 2389658fa66bSAlexey Kardashevskiy void *rma = NULL; 239053018216SPaolo Bonzini hwaddr rma_alloc_size; 2391c86c1affSDaniel Henrique Barboza hwaddr node0_size = spapr_node0_size(machine); 2392b7d1f77aSBenjamin Herrenschmidt long load_limit, fw_size; 239353018216SPaolo Bonzini char *filename; 239430f4b05bSDavid Gibson Error *resize_hpt_err = NULL; 239553018216SPaolo Bonzini 2396226419d6SMichael S. Tsirkin msi_nonbroken = true; 239753018216SPaolo Bonzini 239853018216SPaolo Bonzini QLIST_INIT(&spapr->phbs); 23990cffce56SDavid Gibson QTAILQ_INIT(&spapr->pending_dimm_unplugs); 240053018216SPaolo Bonzini 240130f4b05bSDavid Gibson /* Check HPT resizing availability */ 240230f4b05bSDavid Gibson kvmppc_check_papr_resize_hpt(&resize_hpt_err); 240330f4b05bSDavid Gibson if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) { 240430f4b05bSDavid Gibson /* 240530f4b05bSDavid Gibson * If the user explicitly requested a mode we should either 240630f4b05bSDavid Gibson * supply it, or fail completely (which we do below). But if 240730f4b05bSDavid Gibson * it's not set explicitly, we reset our mode to something 240830f4b05bSDavid Gibson * that works 240930f4b05bSDavid Gibson */ 241030f4b05bSDavid Gibson if (resize_hpt_err) { 241130f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 241230f4b05bSDavid Gibson error_free(resize_hpt_err); 241330f4b05bSDavid Gibson resize_hpt_err = NULL; 241430f4b05bSDavid Gibson } else { 241530f4b05bSDavid Gibson spapr->resize_hpt = smc->resize_hpt_default; 241630f4b05bSDavid Gibson } 241730f4b05bSDavid Gibson } 241830f4b05bSDavid Gibson 241930f4b05bSDavid Gibson assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT); 242030f4b05bSDavid Gibson 242130f4b05bSDavid Gibson if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && resize_hpt_err) { 242230f4b05bSDavid Gibson /* 242330f4b05bSDavid Gibson * User requested HPT resize, but this host can't supply it. Bail out 242430f4b05bSDavid Gibson */ 242530f4b05bSDavid Gibson error_report_err(resize_hpt_err); 242630f4b05bSDavid Gibson exit(1); 242730f4b05bSDavid Gibson } 242830f4b05bSDavid Gibson 242953018216SPaolo Bonzini /* Allocate RMA if necessary */ 2430658fa66bSAlexey Kardashevskiy rma_alloc_size = kvmppc_alloc_rma(&rma); 243153018216SPaolo Bonzini 243253018216SPaolo Bonzini if (rma_alloc_size == -1) { 2433730fce59SThomas Huth error_report("Unable to create RMA"); 243453018216SPaolo Bonzini exit(1); 243553018216SPaolo Bonzini } 243653018216SPaolo Bonzini 2437c4177479SAlexey Kardashevskiy if (rma_alloc_size && (rma_alloc_size < node0_size)) { 243853018216SPaolo Bonzini spapr->rma_size = rma_alloc_size; 243953018216SPaolo Bonzini } else { 2440c4177479SAlexey Kardashevskiy spapr->rma_size = node0_size; 244153018216SPaolo Bonzini 244253018216SPaolo Bonzini /* With KVM, we don't actually know whether KVM supports an 244353018216SPaolo Bonzini * unbounded RMA (PR KVM) or is limited by the hash table size 244453018216SPaolo Bonzini * (HV KVM using VRMA), so we always assume the latter 244553018216SPaolo Bonzini * 244653018216SPaolo Bonzini * In that case, we also limit the initial allocations for RTAS 244753018216SPaolo Bonzini * etc... to 256M since we have no way to know what the VRMA size 244853018216SPaolo Bonzini * is going to be as it depends on the size of the hash table 244953018216SPaolo Bonzini * isn't determined yet. 245053018216SPaolo Bonzini */ 245153018216SPaolo Bonzini if (kvm_enabled()) { 245253018216SPaolo Bonzini spapr->vrma_adjust = 1; 245353018216SPaolo Bonzini spapr->rma_size = MIN(spapr->rma_size, 0x10000000); 245453018216SPaolo Bonzini } 2455912acdf4SBenjamin Herrenschmidt 2456912acdf4SBenjamin Herrenschmidt /* Actually we don't support unbounded RMA anymore since we 2457912acdf4SBenjamin Herrenschmidt * added proper emulation of HV mode. The max we can get is 2458912acdf4SBenjamin Herrenschmidt * 16G which also happens to be what we configure for PAPR 2459912acdf4SBenjamin Herrenschmidt * mode so make sure we don't do anything bigger than that 2460912acdf4SBenjamin Herrenschmidt */ 2461912acdf4SBenjamin Herrenschmidt spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull); 246253018216SPaolo Bonzini } 246353018216SPaolo Bonzini 2464c4177479SAlexey Kardashevskiy if (spapr->rma_size > node0_size) { 2465d54e4d76SDavid Gibson error_report("Numa node 0 has to span the RMA (%#08"HWADDR_PRIx")", 2466c4177479SAlexey Kardashevskiy spapr->rma_size); 2467c4177479SAlexey Kardashevskiy exit(1); 2468c4177479SAlexey Kardashevskiy } 2469c4177479SAlexey Kardashevskiy 2470b7d1f77aSBenjamin Herrenschmidt /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */ 2471b7d1f77aSBenjamin Herrenschmidt load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; 247253018216SPaolo Bonzini 24737b565160SDavid Gibson /* Set up Interrupt Controller before we create the VCPUs */ 247471cd4dacSCédric Le Goater xics_system_init(machine, XICS_IRQS_SPAPR, &error_fatal); 24757b565160SDavid Gibson 2476dc1b5eeeSGreg Kurz /* Set up containers for ibm,client-architecture-support negotiated options 2477dc1b5eeeSGreg Kurz */ 2478facdb8b6SMichael Roth spapr->ov5 = spapr_ovec_new(); 2479facdb8b6SMichael Roth spapr->ov5_cas = spapr_ovec_new(); 2480facdb8b6SMichael Roth 2481224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2482facdb8b6SMichael Roth spapr_ovec_set(spapr->ov5, OV5_DRCONF_MEMORY); 24837c150d6fSDavid Gibson spapr_validate_node_memory(machine, &error_fatal); 2484224245bfSDavid Gibson } 2485224245bfSDavid Gibson 2486417ece33SMichael Roth spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY); 2487545d6e2bSSuraj Jitindar Singh if (!kvm_enabled() || kvmppc_has_cap_mmu_radix()) { 2488545d6e2bSSuraj Jitindar Singh /* KVM and TCG always allow GTSE with radix... */ 24899fb4541fSSam Bobroff spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE); 24909fb4541fSSam Bobroff } 24919fb4541fSSam Bobroff /* ... but not with hash (currently). */ 2492417ece33SMichael Roth 2493ffbb1705SMichael Roth /* advertise support for dedicated HP event source to guests */ 2494ffbb1705SMichael Roth if (spapr->use_hotplug_event_source) { 2495ffbb1705SMichael Roth spapr_ovec_set(spapr->ov5, OV5_HP_EVT); 2496ffbb1705SMichael Roth } 2497ffbb1705SMichael Roth 24982772cf6bSDavid Gibson /* advertise support for HPT resizing */ 24992772cf6bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { 25002772cf6bSDavid Gibson spapr_ovec_set(spapr->ov5, OV5_HPT_RESIZE); 25012772cf6bSDavid Gibson } 25022772cf6bSDavid Gibson 250353018216SPaolo Bonzini /* init CPUs */ 25040c86d0fdSDavid Gibson spapr_init_cpus(spapr); 250553018216SPaolo Bonzini 2506026bfd89SDavid Gibson if (kvm_enabled()) { 2507026bfd89SDavid Gibson /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ 2508026bfd89SDavid Gibson kvmppc_enable_logical_ci_hcalls(); 2509ef9971ddSAlexey Kardashevskiy kvmppc_enable_set_mode_hcall(); 25105145ad4fSNathan Whitehorn 25115145ad4fSNathan Whitehorn /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */ 25125145ad4fSNathan Whitehorn kvmppc_enable_clear_ref_mod_hcalls(); 2513026bfd89SDavid Gibson } 2514026bfd89SDavid Gibson 251553018216SPaolo Bonzini /* allocate RAM */ 2516f92f5da1SAlexey Kardashevskiy memory_region_allocate_system_memory(ram, NULL, "ppc_spapr.ram", 2517fb164994SDavid Gibson machine->ram_size); 2518f92f5da1SAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, ram); 251953018216SPaolo Bonzini 2520658fa66bSAlexey Kardashevskiy if (rma_alloc_size && rma) { 2521658fa66bSAlexey Kardashevskiy rma_region = g_new(MemoryRegion, 1); 2522658fa66bSAlexey Kardashevskiy memory_region_init_ram_ptr(rma_region, NULL, "ppc_spapr.rma", 2523658fa66bSAlexey Kardashevskiy rma_alloc_size, rma); 2524658fa66bSAlexey Kardashevskiy vmstate_register_ram_global(rma_region); 2525658fa66bSAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, rma_region); 2526658fa66bSAlexey Kardashevskiy } 2527658fa66bSAlexey Kardashevskiy 25284a1c9cf0SBharata B Rao /* initialize hotplug memory address space */ 25294a1c9cf0SBharata B Rao if (machine->ram_size < machine->maxram_size) { 25304a1c9cf0SBharata B Rao ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size; 253171c9a3ddSBharata B Rao /* 253271c9a3ddSBharata B Rao * Limit the number of hotpluggable memory slots to half the number 253371c9a3ddSBharata B Rao * slots that KVM supports, leaving the other half for PCI and other 253471c9a3ddSBharata B Rao * devices. However ensure that number of slots doesn't drop below 32. 253571c9a3ddSBharata B Rao */ 253671c9a3ddSBharata B Rao int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 : 253771c9a3ddSBharata B Rao SPAPR_MAX_RAM_SLOTS; 25384a1c9cf0SBharata B Rao 253971c9a3ddSBharata B Rao if (max_memslots < SPAPR_MAX_RAM_SLOTS) { 254071c9a3ddSBharata B Rao max_memslots = SPAPR_MAX_RAM_SLOTS; 254171c9a3ddSBharata B Rao } 254271c9a3ddSBharata B Rao if (machine->ram_slots > max_memslots) { 2543d54e4d76SDavid Gibson error_report("Specified number of memory slots %" 2544d54e4d76SDavid Gibson PRIu64" exceeds max supported %d", 254571c9a3ddSBharata B Rao machine->ram_slots, max_memslots); 2546d54e4d76SDavid Gibson exit(1); 25474a1c9cf0SBharata B Rao } 25484a1c9cf0SBharata B Rao 25494a1c9cf0SBharata B Rao spapr->hotplug_memory.base = ROUND_UP(machine->ram_size, 25504a1c9cf0SBharata B Rao SPAPR_HOTPLUG_MEM_ALIGN); 25514a1c9cf0SBharata B Rao memory_region_init(&spapr->hotplug_memory.mr, OBJECT(spapr), 25524a1c9cf0SBharata B Rao "hotplug-memory", hotplug_mem_size); 25534a1c9cf0SBharata B Rao memory_region_add_subregion(sysmem, spapr->hotplug_memory.base, 25544a1c9cf0SBharata B Rao &spapr->hotplug_memory.mr); 25554a1c9cf0SBharata B Rao } 25564a1c9cf0SBharata B Rao 2557224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2558224245bfSDavid Gibson spapr_create_lmb_dr_connectors(spapr); 2559224245bfSDavid Gibson } 2560224245bfSDavid Gibson 256153018216SPaolo Bonzini filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin"); 25624c56440dSStefan Weil if (!filename) { 2563730fce59SThomas Huth error_report("Could not find LPAR rtas '%s'", "spapr-rtas.bin"); 25644c56440dSStefan Weil exit(1); 25654c56440dSStefan Weil } 2566b7d1f77aSBenjamin Herrenschmidt spapr->rtas_size = get_image_size(filename); 25678afc22a2SZhou Jie if (spapr->rtas_size < 0) { 25688afc22a2SZhou Jie error_report("Could not get size of LPAR rtas '%s'", filename); 25698afc22a2SZhou Jie exit(1); 25708afc22a2SZhou Jie } 2571b7d1f77aSBenjamin Herrenschmidt spapr->rtas_blob = g_malloc(spapr->rtas_size); 2572b7d1f77aSBenjamin Herrenschmidt if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) { 2573730fce59SThomas Huth error_report("Could not load LPAR rtas '%s'", filename); 257453018216SPaolo Bonzini exit(1); 257553018216SPaolo Bonzini } 257653018216SPaolo Bonzini if (spapr->rtas_size > RTAS_MAX_SIZE) { 2577730fce59SThomas Huth error_report("RTAS too big ! 0x%zx bytes (max is 0x%x)", 25782f285bddSPeter Maydell (size_t)spapr->rtas_size, RTAS_MAX_SIZE); 257953018216SPaolo Bonzini exit(1); 258053018216SPaolo Bonzini } 258153018216SPaolo Bonzini g_free(filename); 258253018216SPaolo Bonzini 2583ffbb1705SMichael Roth /* Set up RTAS event infrastructure */ 258453018216SPaolo Bonzini spapr_events_init(spapr); 258553018216SPaolo Bonzini 258612f42174SDavid Gibson /* Set up the RTC RTAS interfaces */ 258728df36a1SDavid Gibson spapr_rtc_create(spapr); 258812f42174SDavid Gibson 258953018216SPaolo Bonzini /* Set up VIO bus */ 259053018216SPaolo Bonzini spapr->vio_bus = spapr_vio_bus_init(); 259153018216SPaolo Bonzini 2592b8846a4dSPeter Maydell for (i = 0; i < serial_max_hds(); i++) { 25939bca0edbSPeter Maydell if (serial_hd(i)) { 25949bca0edbSPeter Maydell spapr_vty_create(spapr->vio_bus, serial_hd(i)); 259553018216SPaolo Bonzini } 259653018216SPaolo Bonzini } 259753018216SPaolo Bonzini 259853018216SPaolo Bonzini /* We always have at least the nvram device on VIO */ 259953018216SPaolo Bonzini spapr_create_nvram(spapr); 260053018216SPaolo Bonzini 260153018216SPaolo Bonzini /* Set up PCI */ 260253018216SPaolo Bonzini spapr_pci_rtas_init(); 260353018216SPaolo Bonzini 260489dfd6e1SDavid Gibson phb = spapr_create_phb(spapr, 0); 260553018216SPaolo Bonzini 260653018216SPaolo Bonzini for (i = 0; i < nb_nics; i++) { 260753018216SPaolo Bonzini NICInfo *nd = &nd_table[i]; 260853018216SPaolo Bonzini 260953018216SPaolo Bonzini if (!nd->model) { 26103c3a4e7aSThomas Huth nd->model = g_strdup("spapr-vlan"); 261153018216SPaolo Bonzini } 261253018216SPaolo Bonzini 26133c3a4e7aSThomas Huth if (g_str_equal(nd->model, "spapr-vlan") || 26143c3a4e7aSThomas Huth g_str_equal(nd->model, "ibmveth")) { 261553018216SPaolo Bonzini spapr_vlan_create(spapr->vio_bus, nd); 261653018216SPaolo Bonzini } else { 261729b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL); 261853018216SPaolo Bonzini } 261953018216SPaolo Bonzini } 262053018216SPaolo Bonzini 262153018216SPaolo Bonzini for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { 262253018216SPaolo Bonzini spapr_vscsi_create(spapr->vio_bus); 262353018216SPaolo Bonzini } 262453018216SPaolo Bonzini 262553018216SPaolo Bonzini /* Graphics */ 262614c6a894SDavid Gibson if (spapr_vga_init(phb->bus, &error_fatal)) { 262753018216SPaolo Bonzini spapr->has_graphics = true; 2628c6e76503SPaolo Bonzini machine->usb |= defaults_enabled() && !machine->usb_disabled; 262953018216SPaolo Bonzini } 263053018216SPaolo Bonzini 26314ee9ced9SMarcel Apfelbaum if (machine->usb) { 263257040d45SThomas Huth if (smc->use_ohci_by_default) { 263353018216SPaolo Bonzini pci_create_simple(phb->bus, -1, "pci-ohci"); 263457040d45SThomas Huth } else { 263557040d45SThomas Huth pci_create_simple(phb->bus, -1, "nec-usb-xhci"); 263657040d45SThomas Huth } 2637c86580b8SMarkus Armbruster 263853018216SPaolo Bonzini if (spapr->has_graphics) { 2639c86580b8SMarkus Armbruster USBBus *usb_bus = usb_bus_find(-1); 2640c86580b8SMarkus Armbruster 2641c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-kbd"); 2642c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-mouse"); 264353018216SPaolo Bonzini } 264453018216SPaolo Bonzini } 264553018216SPaolo Bonzini 264653018216SPaolo Bonzini if (spapr->rma_size < (MIN_RMA_SLOF << 20)) { 2647d54e4d76SDavid Gibson error_report( 2648d54e4d76SDavid Gibson "pSeries SLOF firmware requires >= %ldM guest RMA (Real Mode Area memory)", 2649d54e4d76SDavid Gibson MIN_RMA_SLOF); 265053018216SPaolo Bonzini exit(1); 265153018216SPaolo Bonzini } 265253018216SPaolo Bonzini 265353018216SPaolo Bonzini if (kernel_filename) { 265453018216SPaolo Bonzini uint64_t lowaddr = 0; 265553018216SPaolo Bonzini 2656a19f7fb0SDavid Gibson spapr->kernel_size = load_elf(kernel_filename, translate_kernel_address, 2657a19f7fb0SDavid Gibson NULL, NULL, &lowaddr, NULL, 1, 2658a19f7fb0SDavid Gibson PPC_ELF_MACHINE, 0, 0); 2659a19f7fb0SDavid Gibson if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) { 2660a19f7fb0SDavid Gibson spapr->kernel_size = load_elf(kernel_filename, 2661a19f7fb0SDavid Gibson translate_kernel_address, NULL, NULL, 2662a19f7fb0SDavid Gibson &lowaddr, NULL, 0, PPC_ELF_MACHINE, 26637ef295eaSPeter Crosthwaite 0, 0); 2664a19f7fb0SDavid Gibson spapr->kernel_le = spapr->kernel_size > 0; 266516457e7fSBenjamin Herrenschmidt } 2666a19f7fb0SDavid Gibson if (spapr->kernel_size < 0) { 2667a19f7fb0SDavid Gibson error_report("error loading %s: %s", kernel_filename, 2668a19f7fb0SDavid Gibson load_elf_strerror(spapr->kernel_size)); 266953018216SPaolo Bonzini exit(1); 267053018216SPaolo Bonzini } 267153018216SPaolo Bonzini 267253018216SPaolo Bonzini /* load initrd */ 267353018216SPaolo Bonzini if (initrd_filename) { 267453018216SPaolo Bonzini /* Try to locate the initrd in the gap between the kernel 267553018216SPaolo Bonzini * and the firmware. Add a bit of space just in case 267653018216SPaolo Bonzini */ 2677a19f7fb0SDavid Gibson spapr->initrd_base = (KERNEL_LOAD_ADDR + spapr->kernel_size 2678a19f7fb0SDavid Gibson + 0x1ffff) & ~0xffff; 2679a19f7fb0SDavid Gibson spapr->initrd_size = load_image_targphys(initrd_filename, 2680a19f7fb0SDavid Gibson spapr->initrd_base, 2681a19f7fb0SDavid Gibson load_limit 2682a19f7fb0SDavid Gibson - spapr->initrd_base); 2683a19f7fb0SDavid Gibson if (spapr->initrd_size < 0) { 2684d54e4d76SDavid Gibson error_report("could not load initial ram disk '%s'", 268553018216SPaolo Bonzini initrd_filename); 268653018216SPaolo Bonzini exit(1); 268753018216SPaolo Bonzini } 268853018216SPaolo Bonzini } 268953018216SPaolo Bonzini } 269053018216SPaolo Bonzini 26918e7ea787SAndreas Färber if (bios_name == NULL) { 26928e7ea787SAndreas Färber bios_name = FW_FILE_NAME; 26938e7ea787SAndreas Färber } 26948e7ea787SAndreas Färber filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 26954c56440dSStefan Weil if (!filename) { 269668fea5a0SThomas Huth error_report("Could not find LPAR firmware '%s'", bios_name); 26974c56440dSStefan Weil exit(1); 26984c56440dSStefan Weil } 269953018216SPaolo Bonzini fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); 270068fea5a0SThomas Huth if (fw_size <= 0) { 270168fea5a0SThomas Huth error_report("Could not load LPAR firmware '%s'", filename); 270253018216SPaolo Bonzini exit(1); 270353018216SPaolo Bonzini } 270453018216SPaolo Bonzini g_free(filename); 270553018216SPaolo Bonzini 270628e02042SDavid Gibson /* FIXME: Should register things through the MachineState's qdev 270728e02042SDavid Gibson * interface, this is a legacy from the sPAPREnvironment structure 270828e02042SDavid Gibson * which predated MachineState but had a similar function */ 27094be21d56SDavid Gibson vmstate_register(NULL, 0, &vmstate_spapr, spapr); 27104be21d56SDavid Gibson register_savevm_live(NULL, "spapr/htab", -1, 1, 27114be21d56SDavid Gibson &savevm_htab_handlers, spapr); 27124be21d56SDavid Gibson 27135b2128d2SAlexander Graf qemu_register_boot_set(spapr_boot_set, spapr); 271442043e4fSLaurent Vivier 271542043e4fSLaurent Vivier if (kvm_enabled()) { 27163dc410aeSAlexey Kardashevskiy /* to stop and start vmclock */ 271742043e4fSLaurent Vivier qemu_add_vm_change_state_handler(cpu_ppc_clock_vm_state_change, 271842043e4fSLaurent Vivier &spapr->tb); 27193dc410aeSAlexey Kardashevskiy 27203dc410aeSAlexey Kardashevskiy kvmppc_spapr_enable_inkernel_multitce(); 272142043e4fSLaurent Vivier } 272253018216SPaolo Bonzini } 272353018216SPaolo Bonzini 2724135a129aSAneesh Kumar K.V static int spapr_kvm_type(const char *vm_type) 2725135a129aSAneesh Kumar K.V { 2726135a129aSAneesh Kumar K.V if (!vm_type) { 2727135a129aSAneesh Kumar K.V return 0; 2728135a129aSAneesh Kumar K.V } 2729135a129aSAneesh Kumar K.V 2730135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "HV")) { 2731135a129aSAneesh Kumar K.V return 1; 2732135a129aSAneesh Kumar K.V } 2733135a129aSAneesh Kumar K.V 2734135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "PR")) { 2735135a129aSAneesh Kumar K.V return 2; 2736135a129aSAneesh Kumar K.V } 2737135a129aSAneesh Kumar K.V 2738135a129aSAneesh Kumar K.V error_report("Unknown kvm-type specified '%s'", vm_type); 2739135a129aSAneesh Kumar K.V exit(1); 2740135a129aSAneesh Kumar K.V } 2741135a129aSAneesh Kumar K.V 274271461b0fSAlexey Kardashevskiy /* 2743627b84f4SGonglei * Implementation of an interface to adjust firmware path 274471461b0fSAlexey Kardashevskiy * for the bootindex property handling. 274571461b0fSAlexey Kardashevskiy */ 274671461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, 274771461b0fSAlexey Kardashevskiy DeviceState *dev) 274871461b0fSAlexey Kardashevskiy { 274971461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \ 275071461b0fSAlexey Kardashevskiy ((type *)object_dynamic_cast(OBJECT(obj), (name))) 275171461b0fSAlexey Kardashevskiy SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); 275271461b0fSAlexey Kardashevskiy sPAPRPHBState *phb = CAST(sPAPRPHBState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); 2753c4e13492SFelipe Franciosi VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON); 275471461b0fSAlexey Kardashevskiy 275571461b0fSAlexey Kardashevskiy if (d) { 275671461b0fSAlexey Kardashevskiy void *spapr = CAST(void, bus->parent, "spapr-vscsi"); 275771461b0fSAlexey Kardashevskiy VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); 275871461b0fSAlexey Kardashevskiy USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); 275971461b0fSAlexey Kardashevskiy 276071461b0fSAlexey Kardashevskiy if (spapr) { 276171461b0fSAlexey Kardashevskiy /* 276271461b0fSAlexey Kardashevskiy * Replace "channel@0/disk@0,0" with "disk@8000000000000000": 276371461b0fSAlexey Kardashevskiy * We use SRP luns of the form 8000 | (bus << 8) | (id << 5) | lun 276471461b0fSAlexey Kardashevskiy * in the top 16 bits of the 64-bit LUN 276571461b0fSAlexey Kardashevskiy */ 276671461b0fSAlexey Kardashevskiy unsigned id = 0x8000 | (d->id << 8) | d->lun; 276771461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 276871461b0fSAlexey Kardashevskiy (uint64_t)id << 48); 276971461b0fSAlexey Kardashevskiy } else if (virtio) { 277071461b0fSAlexey Kardashevskiy /* 277171461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (target << 8) | lun 277271461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 277371461b0fSAlexey Kardashevskiy * Note: the quote above is from SLOF and it is wrong, 277471461b0fSAlexey Kardashevskiy * the actual binding is: 277571461b0fSAlexey Kardashevskiy * swap 0100 or 10 << or 20 << ( target lun-id -- srplun ) 277671461b0fSAlexey Kardashevskiy */ 277771461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (d->id << 16) | d->lun; 2778bac658d1SThomas Huth if (d->lun >= 256) { 2779bac658d1SThomas Huth /* Use the LUN "flat space addressing method" */ 2780bac658d1SThomas Huth id |= 0x4000; 2781bac658d1SThomas Huth } 278271461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 278371461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 278471461b0fSAlexey Kardashevskiy } else if (usb) { 278571461b0fSAlexey Kardashevskiy /* 278671461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (usb-port << 16) | lun 278771461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 278871461b0fSAlexey Kardashevskiy */ 278971461b0fSAlexey Kardashevskiy unsigned usb_port = atoi(usb->port->path); 279071461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (usb_port << 16) | d->lun; 279171461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 279271461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 279371461b0fSAlexey Kardashevskiy } 279471461b0fSAlexey Kardashevskiy } 279571461b0fSAlexey Kardashevskiy 2796b99260ebSThomas Huth /* 2797b99260ebSThomas Huth * SLOF probes the USB devices, and if it recognizes that the device is a 2798b99260ebSThomas Huth * storage device, it changes its name to "storage" instead of "usb-host", 2799b99260ebSThomas Huth * and additionally adds a child node for the SCSI LUN, so the correct 2800b99260ebSThomas Huth * boot path in SLOF is something like .../storage@1/disk@xxx" instead. 2801b99260ebSThomas Huth */ 2802b99260ebSThomas Huth if (strcmp("usb-host", qdev_fw_name(dev)) == 0) { 2803b99260ebSThomas Huth USBDevice *usbdev = CAST(USBDevice, dev, TYPE_USB_DEVICE); 2804b99260ebSThomas Huth if (usb_host_dev_is_scsi_storage(usbdev)) { 2805b99260ebSThomas Huth return g_strdup_printf("storage@%s/disk", usbdev->port->path); 2806b99260ebSThomas Huth } 2807b99260ebSThomas Huth } 2808b99260ebSThomas Huth 280971461b0fSAlexey Kardashevskiy if (phb) { 281071461b0fSAlexey Kardashevskiy /* Replace "pci" with "pci@800000020000000" */ 281171461b0fSAlexey Kardashevskiy return g_strdup_printf("pci@%"PRIX64, phb->buid); 281271461b0fSAlexey Kardashevskiy } 281371461b0fSAlexey Kardashevskiy 2814c4e13492SFelipe Franciosi if (vsc) { 2815c4e13492SFelipe Franciosi /* Same logic as virtio above */ 2816c4e13492SFelipe Franciosi unsigned id = 0x1000000 | (vsc->target << 16) | vsc->lun; 2817c4e13492SFelipe Franciosi return g_strdup_printf("disk@%"PRIX64, (uint64_t)id << 32); 2818c4e13492SFelipe Franciosi } 2819c4e13492SFelipe Franciosi 28204871dd4cSThomas Huth if (g_str_equal("pci-bridge", qdev_fw_name(dev))) { 28214871dd4cSThomas Huth /* SLOF uses "pci" instead of "pci-bridge" for PCI bridges */ 28224871dd4cSThomas Huth PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); 28234871dd4cSThomas Huth return g_strdup_printf("pci@%x", PCI_SLOT(pcidev->devfn)); 28244871dd4cSThomas Huth } 28254871dd4cSThomas Huth 282671461b0fSAlexey Kardashevskiy return NULL; 282771461b0fSAlexey Kardashevskiy } 282871461b0fSAlexey Kardashevskiy 282923825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp) 283023825581SEduardo Habkost { 283128e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 283223825581SEduardo Habkost 283328e02042SDavid Gibson return g_strdup(spapr->kvm_type); 283423825581SEduardo Habkost } 283523825581SEduardo Habkost 283623825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp) 283723825581SEduardo Habkost { 283828e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 283923825581SEduardo Habkost 284028e02042SDavid Gibson g_free(spapr->kvm_type); 284128e02042SDavid Gibson spapr->kvm_type = g_strdup(value); 284223825581SEduardo Habkost } 284323825581SEduardo Habkost 2844f6229214SMichael Roth static bool spapr_get_modern_hotplug_events(Object *obj, Error **errp) 2845f6229214SMichael Roth { 2846f6229214SMichael Roth sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 2847f6229214SMichael Roth 2848f6229214SMichael Roth return spapr->use_hotplug_event_source; 2849f6229214SMichael Roth } 2850f6229214SMichael Roth 2851f6229214SMichael Roth static void spapr_set_modern_hotplug_events(Object *obj, bool value, 2852f6229214SMichael Roth Error **errp) 2853f6229214SMichael Roth { 2854f6229214SMichael Roth sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 2855f6229214SMichael Roth 2856f6229214SMichael Roth spapr->use_hotplug_event_source = value; 2857f6229214SMichael Roth } 2858f6229214SMichael Roth 2859fcad0d21SAlexey Kardashevskiy static bool spapr_get_msix_emulation(Object *obj, Error **errp) 2860fcad0d21SAlexey Kardashevskiy { 2861fcad0d21SAlexey Kardashevskiy return true; 2862fcad0d21SAlexey Kardashevskiy } 2863fcad0d21SAlexey Kardashevskiy 286430f4b05bSDavid Gibson static char *spapr_get_resize_hpt(Object *obj, Error **errp) 286530f4b05bSDavid Gibson { 286630f4b05bSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 286730f4b05bSDavid Gibson 286830f4b05bSDavid Gibson switch (spapr->resize_hpt) { 286930f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DEFAULT: 287030f4b05bSDavid Gibson return g_strdup("default"); 287130f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DISABLED: 287230f4b05bSDavid Gibson return g_strdup("disabled"); 287330f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_ENABLED: 287430f4b05bSDavid Gibson return g_strdup("enabled"); 287530f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_REQUIRED: 287630f4b05bSDavid Gibson return g_strdup("required"); 287730f4b05bSDavid Gibson } 287830f4b05bSDavid Gibson g_assert_not_reached(); 287930f4b05bSDavid Gibson } 288030f4b05bSDavid Gibson 288130f4b05bSDavid Gibson static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp) 288230f4b05bSDavid Gibson { 288330f4b05bSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 288430f4b05bSDavid Gibson 288530f4b05bSDavid Gibson if (strcmp(value, "default") == 0) { 288630f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DEFAULT; 288730f4b05bSDavid Gibson } else if (strcmp(value, "disabled") == 0) { 288830f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; 288930f4b05bSDavid Gibson } else if (strcmp(value, "enabled") == 0) { 289030f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_ENABLED; 289130f4b05bSDavid Gibson } else if (strcmp(value, "required") == 0) { 289230f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_REQUIRED; 289330f4b05bSDavid Gibson } else { 289430f4b05bSDavid Gibson error_setg(errp, "Bad value for \"resize-hpt\" property"); 289530f4b05bSDavid Gibson } 289630f4b05bSDavid Gibson } 289730f4b05bSDavid Gibson 2898fa98fbfcSSam Bobroff static void spapr_get_vsmt(Object *obj, Visitor *v, const char *name, 2899fa98fbfcSSam Bobroff void *opaque, Error **errp) 2900fa98fbfcSSam Bobroff { 2901fa98fbfcSSam Bobroff visit_type_uint32(v, name, (uint32_t *)opaque, errp); 2902fa98fbfcSSam Bobroff } 2903fa98fbfcSSam Bobroff 2904fa98fbfcSSam Bobroff static void spapr_set_vsmt(Object *obj, Visitor *v, const char *name, 2905fa98fbfcSSam Bobroff void *opaque, Error **errp) 2906fa98fbfcSSam Bobroff { 2907fa98fbfcSSam Bobroff visit_type_uint32(v, name, (uint32_t *)opaque, errp); 2908fa98fbfcSSam Bobroff } 2909fa98fbfcSSam Bobroff 2910bcb5ce08SDavid Gibson static void spapr_instance_init(Object *obj) 291123825581SEduardo Habkost { 2912715c5407SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 2913715c5407SDavid Gibson 2914715c5407SDavid Gibson spapr->htab_fd = -1; 2915f6229214SMichael Roth spapr->use_hotplug_event_source = true; 291623825581SEduardo Habkost object_property_add_str(obj, "kvm-type", 291723825581SEduardo Habkost spapr_get_kvm_type, spapr_set_kvm_type, NULL); 291849d2e648SMarcel Apfelbaum object_property_set_description(obj, "kvm-type", 291949d2e648SMarcel Apfelbaum "Specifies the KVM virtualization mode (HV, PR)", 292049d2e648SMarcel Apfelbaum NULL); 2921f6229214SMichael Roth object_property_add_bool(obj, "modern-hotplug-events", 2922f6229214SMichael Roth spapr_get_modern_hotplug_events, 2923f6229214SMichael Roth spapr_set_modern_hotplug_events, 2924f6229214SMichael Roth NULL); 2925f6229214SMichael Roth object_property_set_description(obj, "modern-hotplug-events", 2926f6229214SMichael Roth "Use dedicated hotplug event mechanism in" 2927f6229214SMichael Roth " place of standard EPOW events when possible" 2928f6229214SMichael Roth " (required for memory hot-unplug support)", 2929f6229214SMichael Roth NULL); 29307843c0d6SDavid Gibson 29317843c0d6SDavid Gibson ppc_compat_add_property(obj, "max-cpu-compat", &spapr->max_compat_pvr, 29327843c0d6SDavid Gibson "Maximum permitted CPU compatibility mode", 29337843c0d6SDavid Gibson &error_fatal); 293430f4b05bSDavid Gibson 293530f4b05bSDavid Gibson object_property_add_str(obj, "resize-hpt", 293630f4b05bSDavid Gibson spapr_get_resize_hpt, spapr_set_resize_hpt, NULL); 293730f4b05bSDavid Gibson object_property_set_description(obj, "resize-hpt", 293830f4b05bSDavid Gibson "Resizing of the Hash Page Table (enabled, disabled, required)", 293930f4b05bSDavid Gibson NULL); 2940fa98fbfcSSam Bobroff object_property_add(obj, "vsmt", "uint32", spapr_get_vsmt, 2941fa98fbfcSSam Bobroff spapr_set_vsmt, NULL, &spapr->vsmt, &error_abort); 2942fa98fbfcSSam Bobroff object_property_set_description(obj, "vsmt", 2943fa98fbfcSSam Bobroff "Virtual SMT: KVM behaves as if this were" 2944fa98fbfcSSam Bobroff " the host's SMT mode", &error_abort); 2945fcad0d21SAlexey Kardashevskiy object_property_add_bool(obj, "vfio-no-msix-emulation", 2946fcad0d21SAlexey Kardashevskiy spapr_get_msix_emulation, NULL, NULL); 294723825581SEduardo Habkost } 294823825581SEduardo Habkost 294987bbdd9cSDavid Gibson static void spapr_machine_finalizefn(Object *obj) 295087bbdd9cSDavid Gibson { 295187bbdd9cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 295287bbdd9cSDavid Gibson 295387bbdd9cSDavid Gibson g_free(spapr->kvm_type); 295487bbdd9cSDavid Gibson } 295587bbdd9cSDavid Gibson 29561c7ad77eSNicholas Piggin void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg) 295734316482SAlexey Kardashevskiy { 295834316482SAlexey Kardashevskiy cpu_synchronize_state(cs); 295934316482SAlexey Kardashevskiy ppc_cpu_do_system_reset(cs); 296034316482SAlexey Kardashevskiy } 296134316482SAlexey Kardashevskiy 296234316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) 296334316482SAlexey Kardashevskiy { 296434316482SAlexey Kardashevskiy CPUState *cs; 296534316482SAlexey Kardashevskiy 296634316482SAlexey Kardashevskiy CPU_FOREACH(cs) { 29671c7ad77eSNicholas Piggin async_run_on_cpu(cs, spapr_do_system_reset_on_cpu, RUN_ON_CPU_NULL); 296834316482SAlexey Kardashevskiy } 296934316482SAlexey Kardashevskiy } 297034316482SAlexey Kardashevskiy 297179b78a6bSMichael Roth static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, 297279b78a6bSMichael Roth uint32_t node, bool dedicated_hp_event_source, 297379b78a6bSMichael Roth Error **errp) 2974c20d332aSBharata B Rao { 2975c20d332aSBharata B Rao sPAPRDRConnector *drc; 2976c20d332aSBharata B Rao uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; 2977c20d332aSBharata B Rao int i, fdt_offset, fdt_size; 2978c20d332aSBharata B Rao void *fdt; 297979b78a6bSMichael Roth uint64_t addr = addr_start; 298094fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 2981160bb678SGreg Kurz Error *local_err = NULL; 2982c20d332aSBharata B Rao 2983c20d332aSBharata B Rao for (i = 0; i < nr_lmbs; i++) { 2984fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 2985c20d332aSBharata B Rao addr / SPAPR_MEMORY_BLOCK_SIZE); 2986c20d332aSBharata B Rao g_assert(drc); 2987c20d332aSBharata B Rao 2988c20d332aSBharata B Rao fdt = create_device_tree(&fdt_size); 2989c20d332aSBharata B Rao fdt_offset = spapr_populate_memory_node(fdt, node, addr, 2990c20d332aSBharata B Rao SPAPR_MEMORY_BLOCK_SIZE); 2991c20d332aSBharata B Rao 2992160bb678SGreg Kurz spapr_drc_attach(drc, dev, fdt, fdt_offset, &local_err); 2993160bb678SGreg Kurz if (local_err) { 2994160bb678SGreg Kurz while (addr > addr_start) { 2995160bb678SGreg Kurz addr -= SPAPR_MEMORY_BLOCK_SIZE; 2996160bb678SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 2997160bb678SGreg Kurz addr / SPAPR_MEMORY_BLOCK_SIZE); 2998a8dc47fdSDavid Gibson spapr_drc_detach(drc); 2999160bb678SGreg Kurz } 3000160bb678SGreg Kurz g_free(fdt); 3001160bb678SGreg Kurz error_propagate(errp, local_err); 3002160bb678SGreg Kurz return; 3003160bb678SGreg Kurz } 300494fd9cbaSLaurent Vivier if (!hotplugged) { 300594fd9cbaSLaurent Vivier spapr_drc_reset(drc); 300694fd9cbaSLaurent Vivier } 3007c20d332aSBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE; 3008c20d332aSBharata B Rao } 30095dd5238cSJianjun Duan /* send hotplug notification to the 30105dd5238cSJianjun Duan * guest only in case of hotplugged memory 30115dd5238cSJianjun Duan */ 301294fd9cbaSLaurent Vivier if (hotplugged) { 301379b78a6bSMichael Roth if (dedicated_hp_event_source) { 3014fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 301579b78a6bSMichael Roth addr_start / SPAPR_MEMORY_BLOCK_SIZE); 301679b78a6bSMichael Roth spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 301779b78a6bSMichael Roth nr_lmbs, 30180b55aa91SDavid Gibson spapr_drc_index(drc)); 301979b78a6bSMichael Roth } else { 302079b78a6bSMichael Roth spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, 302179b78a6bSMichael Roth nr_lmbs); 302279b78a6bSMichael Roth } 3023c20d332aSBharata B Rao } 30245dd5238cSJianjun Duan } 3025c20d332aSBharata B Rao 3026c20d332aSBharata B Rao static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3027c20d332aSBharata B Rao uint32_t node, Error **errp) 3028c20d332aSBharata B Rao { 3029c20d332aSBharata B Rao Error *local_err = NULL; 3030c20d332aSBharata B Rao sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev); 3031c20d332aSBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 3032c20d332aSBharata B Rao PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); 303304790978SThomas Huth MemoryRegion *mr; 303404790978SThomas Huth uint64_t align, size, addr; 303504790978SThomas Huth 303604790978SThomas Huth mr = ddc->get_memory_region(dimm, &local_err); 303704790978SThomas Huth if (local_err) { 303804790978SThomas Huth goto out; 303904790978SThomas Huth } 304004790978SThomas Huth align = memory_region_get_alignment(mr); 304104790978SThomas Huth size = memory_region_size(mr); 3042df587133SThomas Huth 3043d6a9b0b8SMichael S. Tsirkin pc_dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, &local_err); 3044c20d332aSBharata B Rao if (local_err) { 3045c20d332aSBharata B Rao goto out; 3046c20d332aSBharata B Rao } 3047c20d332aSBharata B Rao 30489ed442b8SMarc-André Lureau addr = object_property_get_uint(OBJECT(dimm), 30499ed442b8SMarc-André Lureau PC_DIMM_ADDR_PROP, &local_err); 3050c20d332aSBharata B Rao if (local_err) { 3051160bb678SGreg Kurz goto out_unplug; 3052c20d332aSBharata B Rao } 3053c20d332aSBharata B Rao 305479b78a6bSMichael Roth spapr_add_lmbs(dev, addr, size, node, 305579b78a6bSMichael Roth spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), 3056160bb678SGreg Kurz &local_err); 3057160bb678SGreg Kurz if (local_err) { 3058160bb678SGreg Kurz goto out_unplug; 3059160bb678SGreg Kurz } 3060c20d332aSBharata B Rao 3061160bb678SGreg Kurz return; 3062160bb678SGreg Kurz 3063160bb678SGreg Kurz out_unplug: 3064160bb678SGreg Kurz pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr); 3065c20d332aSBharata B Rao out: 3066c20d332aSBharata B Rao error_propagate(errp, local_err); 3067c20d332aSBharata B Rao } 3068c20d332aSBharata B Rao 3069c871bc70SLaurent Vivier static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3070c871bc70SLaurent Vivier Error **errp) 3071c871bc70SLaurent Vivier { 3072c871bc70SLaurent Vivier PCDIMMDevice *dimm = PC_DIMM(dev); 3073c871bc70SLaurent Vivier PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); 307404790978SThomas Huth MemoryRegion *mr; 307504790978SThomas Huth uint64_t size; 3076c871bc70SLaurent Vivier char *mem_dev; 3077c871bc70SLaurent Vivier 307804790978SThomas Huth mr = ddc->get_memory_region(dimm, errp); 307904790978SThomas Huth if (!mr) { 308004790978SThomas Huth return; 308104790978SThomas Huth } 308204790978SThomas Huth size = memory_region_size(mr); 308304790978SThomas Huth 3084c871bc70SLaurent Vivier if (size % SPAPR_MEMORY_BLOCK_SIZE) { 3085c871bc70SLaurent Vivier error_setg(errp, "Hotplugged memory size must be a multiple of " 3086c871bc70SLaurent Vivier "%lld MB", SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 3087c871bc70SLaurent Vivier return; 3088c871bc70SLaurent Vivier } 3089c871bc70SLaurent Vivier 3090c871bc70SLaurent Vivier mem_dev = object_property_get_str(OBJECT(dimm), PC_DIMM_MEMDEV_PROP, NULL); 3091c871bc70SLaurent Vivier if (mem_dev && !kvmppc_is_mem_backend_page_size_ok(mem_dev)) { 3092c871bc70SLaurent Vivier error_setg(errp, "Memory backend has bad page size. " 3093c871bc70SLaurent Vivier "Use 'memory-backend-file' with correct mem-path."); 30948a9e0e7bSGreg Kurz goto out; 3095c871bc70SLaurent Vivier } 30968a9e0e7bSGreg Kurz 30978a9e0e7bSGreg Kurz out: 30988a9e0e7bSGreg Kurz g_free(mem_dev); 3099c871bc70SLaurent Vivier } 3100c871bc70SLaurent Vivier 31010cffce56SDavid Gibson struct sPAPRDIMMState { 31020cffce56SDavid Gibson PCDIMMDevice *dimm; 3103cf632463SBharata B Rao uint32_t nr_lmbs; 31040cffce56SDavid Gibson QTAILQ_ENTRY(sPAPRDIMMState) next; 31050cffce56SDavid Gibson }; 31060cffce56SDavid Gibson 31070cffce56SDavid Gibson static sPAPRDIMMState *spapr_pending_dimm_unplugs_find(sPAPRMachineState *s, 31080cffce56SDavid Gibson PCDIMMDevice *dimm) 31090cffce56SDavid Gibson { 31100cffce56SDavid Gibson sPAPRDIMMState *dimm_state = NULL; 31110cffce56SDavid Gibson 31120cffce56SDavid Gibson QTAILQ_FOREACH(dimm_state, &s->pending_dimm_unplugs, next) { 31130cffce56SDavid Gibson if (dimm_state->dimm == dimm) { 31140cffce56SDavid Gibson break; 31150cffce56SDavid Gibson } 31160cffce56SDavid Gibson } 31170cffce56SDavid Gibson return dimm_state; 31180cffce56SDavid Gibson } 31190cffce56SDavid Gibson 31208d5981c4SBharata B Rao static sPAPRDIMMState *spapr_pending_dimm_unplugs_add(sPAPRMachineState *spapr, 31218d5981c4SBharata B Rao uint32_t nr_lmbs, 31228d5981c4SBharata B Rao PCDIMMDevice *dimm) 31230cffce56SDavid Gibson { 31248d5981c4SBharata B Rao sPAPRDIMMState *ds = NULL; 31258d5981c4SBharata B Rao 31268d5981c4SBharata B Rao /* 31278d5981c4SBharata B Rao * If this request is for a DIMM whose removal had failed earlier 31288d5981c4SBharata B Rao * (due to guest's refusal to remove the LMBs), we would have this 31298d5981c4SBharata B Rao * dimm already in the pending_dimm_unplugs list. In that 31308d5981c4SBharata B Rao * case don't add again. 31318d5981c4SBharata B Rao */ 31328d5981c4SBharata B Rao ds = spapr_pending_dimm_unplugs_find(spapr, dimm); 31338d5981c4SBharata B Rao if (!ds) { 31348d5981c4SBharata B Rao ds = g_malloc0(sizeof(sPAPRDIMMState)); 31358d5981c4SBharata B Rao ds->nr_lmbs = nr_lmbs; 31368d5981c4SBharata B Rao ds->dimm = dimm; 31378d5981c4SBharata B Rao QTAILQ_INSERT_HEAD(&spapr->pending_dimm_unplugs, ds, next); 31388d5981c4SBharata B Rao } 31398d5981c4SBharata B Rao return ds; 31400cffce56SDavid Gibson } 31410cffce56SDavid Gibson 31420cffce56SDavid Gibson static void spapr_pending_dimm_unplugs_remove(sPAPRMachineState *spapr, 31430cffce56SDavid Gibson sPAPRDIMMState *dimm_state) 31440cffce56SDavid Gibson { 31450cffce56SDavid Gibson QTAILQ_REMOVE(&spapr->pending_dimm_unplugs, dimm_state, next); 31460cffce56SDavid Gibson g_free(dimm_state); 31470cffce56SDavid Gibson } 3148cf632463SBharata B Rao 314916ee9980SDaniel Henrique Barboza static sPAPRDIMMState *spapr_recover_pending_dimm_state(sPAPRMachineState *ms, 315016ee9980SDaniel Henrique Barboza PCDIMMDevice *dimm) 315116ee9980SDaniel Henrique Barboza { 315216ee9980SDaniel Henrique Barboza sPAPRDRConnector *drc; 315316ee9980SDaniel Henrique Barboza PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); 315404790978SThomas Huth MemoryRegion *mr = ddc->get_memory_region(dimm, &error_abort); 315516ee9980SDaniel Henrique Barboza uint64_t size = memory_region_size(mr); 315616ee9980SDaniel Henrique Barboza uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 315716ee9980SDaniel Henrique Barboza uint32_t avail_lmbs = 0; 315816ee9980SDaniel Henrique Barboza uint64_t addr_start, addr; 315916ee9980SDaniel Henrique Barboza int i; 316016ee9980SDaniel Henrique Barboza 316116ee9980SDaniel Henrique Barboza addr_start = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, 316216ee9980SDaniel Henrique Barboza &error_abort); 316316ee9980SDaniel Henrique Barboza 316416ee9980SDaniel Henrique Barboza addr = addr_start; 316516ee9980SDaniel Henrique Barboza for (i = 0; i < nr_lmbs; i++) { 3166fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 316716ee9980SDaniel Henrique Barboza addr / SPAPR_MEMORY_BLOCK_SIZE); 316816ee9980SDaniel Henrique Barboza g_assert(drc); 3169454b580aSDavid Gibson if (drc->dev) { 317016ee9980SDaniel Henrique Barboza avail_lmbs++; 317116ee9980SDaniel Henrique Barboza } 317216ee9980SDaniel Henrique Barboza addr += SPAPR_MEMORY_BLOCK_SIZE; 317316ee9980SDaniel Henrique Barboza } 317416ee9980SDaniel Henrique Barboza 31758d5981c4SBharata B Rao return spapr_pending_dimm_unplugs_add(ms, avail_lmbs, dimm); 317616ee9980SDaniel Henrique Barboza } 317716ee9980SDaniel Henrique Barboza 317831834723SDaniel Henrique Barboza /* Callback to be called during DRC release. */ 317931834723SDaniel Henrique Barboza void spapr_lmb_release(DeviceState *dev) 3180cf632463SBharata B Rao { 3181765d1bddSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_hotplug_handler(dev)); 3182765d1bddSDavid Gibson PCDIMMDevice *dimm = PC_DIMM(dev); 3183765d1bddSDavid Gibson PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); 318404790978SThomas Huth MemoryRegion *mr = ddc->get_memory_region(dimm, &error_abort); 31850cffce56SDavid Gibson sPAPRDIMMState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); 3186cf632463SBharata B Rao 318716ee9980SDaniel Henrique Barboza /* This information will get lost if a migration occurs 318816ee9980SDaniel Henrique Barboza * during the unplug process. In this case recover it. */ 318916ee9980SDaniel Henrique Barboza if (ds == NULL) { 319016ee9980SDaniel Henrique Barboza ds = spapr_recover_pending_dimm_state(spapr, PC_DIMM(dev)); 31918d5981c4SBharata B Rao g_assert(ds); 3192454b580aSDavid Gibson /* The DRC being examined by the caller at least must be counted */ 3193454b580aSDavid Gibson g_assert(ds->nr_lmbs); 319416ee9980SDaniel Henrique Barboza } 3195454b580aSDavid Gibson 3196454b580aSDavid Gibson if (--ds->nr_lmbs) { 3197cf632463SBharata B Rao return; 3198cf632463SBharata B Rao } 3199cf632463SBharata B Rao 3200cf632463SBharata B Rao /* 3201cf632463SBharata B Rao * Now that all the LMBs have been removed by the guest, call the 3202cf632463SBharata B Rao * pc-dimm unplug handler to cleanup up the pc-dimm device. 3203cf632463SBharata B Rao */ 3204765d1bddSDavid Gibson pc_dimm_memory_unplug(dev, &spapr->hotplug_memory, mr); 3205cf632463SBharata B Rao object_unparent(OBJECT(dev)); 32062a129767SDaniel Henrique Barboza spapr_pending_dimm_unplugs_remove(spapr, ds); 3207cf632463SBharata B Rao } 3208cf632463SBharata B Rao 3209cf632463SBharata B Rao static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, 3210cf632463SBharata B Rao DeviceState *dev, Error **errp) 3211cf632463SBharata B Rao { 32120cffce56SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_dev); 3213cf632463SBharata B Rao Error *local_err = NULL; 3214cf632463SBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 3215cf632463SBharata B Rao PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); 321604790978SThomas Huth MemoryRegion *mr; 321704790978SThomas Huth uint32_t nr_lmbs; 321804790978SThomas Huth uint64_t size, addr_start, addr; 32190cffce56SDavid Gibson int i; 32200cffce56SDavid Gibson sPAPRDRConnector *drc; 322104790978SThomas Huth 322204790978SThomas Huth mr = ddc->get_memory_region(dimm, &local_err); 322304790978SThomas Huth if (local_err) { 322404790978SThomas Huth goto out; 322504790978SThomas Huth } 322604790978SThomas Huth size = memory_region_size(mr); 322704790978SThomas Huth nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 322804790978SThomas Huth 32299ed442b8SMarc-André Lureau addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, 32300cffce56SDavid Gibson &local_err); 3231cf632463SBharata B Rao if (local_err) { 3232cf632463SBharata B Rao goto out; 3233cf632463SBharata B Rao } 3234cf632463SBharata B Rao 32352a129767SDaniel Henrique Barboza /* 32362a129767SDaniel Henrique Barboza * An existing pending dimm state for this DIMM means that there is an 32372a129767SDaniel Henrique Barboza * unplug operation in progress, waiting for the spapr_lmb_release 32382a129767SDaniel Henrique Barboza * callback to complete the job (BQL can't cover that far). In this case, 32392a129767SDaniel Henrique Barboza * bail out to avoid detaching DRCs that were already released. 32402a129767SDaniel Henrique Barboza */ 32412a129767SDaniel Henrique Barboza if (spapr_pending_dimm_unplugs_find(spapr, dimm)) { 32422a129767SDaniel Henrique Barboza error_setg(&local_err, 32432a129767SDaniel Henrique Barboza "Memory unplug already in progress for device %s", 32442a129767SDaniel Henrique Barboza dev->id); 32452a129767SDaniel Henrique Barboza goto out; 32462a129767SDaniel Henrique Barboza } 32472a129767SDaniel Henrique Barboza 32488d5981c4SBharata B Rao spapr_pending_dimm_unplugs_add(spapr, nr_lmbs, dimm); 32490cffce56SDavid Gibson 32500cffce56SDavid Gibson addr = addr_start; 32510cffce56SDavid Gibson for (i = 0; i < nr_lmbs; i++) { 3252fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 32530cffce56SDavid Gibson addr / SPAPR_MEMORY_BLOCK_SIZE); 32540cffce56SDavid Gibson g_assert(drc); 32550cffce56SDavid Gibson 3256a8dc47fdSDavid Gibson spapr_drc_detach(drc); 32570cffce56SDavid Gibson addr += SPAPR_MEMORY_BLOCK_SIZE; 32580cffce56SDavid Gibson } 32590cffce56SDavid Gibson 3260fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, 32610cffce56SDavid Gibson addr_start / SPAPR_MEMORY_BLOCK_SIZE); 32620cffce56SDavid Gibson spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 32630b55aa91SDavid Gibson nr_lmbs, spapr_drc_index(drc)); 3264cf632463SBharata B Rao out: 3265cf632463SBharata B Rao error_propagate(errp, local_err); 3266cf632463SBharata B Rao } 3267cf632463SBharata B Rao 326804d0ffbdSGreg Kurz static void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset, 3269af81cf32SBharata B Rao sPAPRMachineState *spapr) 3270af81cf32SBharata B Rao { 3271af81cf32SBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 3272af81cf32SBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 327314bb4486SGreg Kurz int id = spapr_get_vcpu_id(cpu); 3274af81cf32SBharata B Rao void *fdt; 3275af81cf32SBharata B Rao int offset, fdt_size; 3276af81cf32SBharata B Rao char *nodename; 3277af81cf32SBharata B Rao 3278af81cf32SBharata B Rao fdt = create_device_tree(&fdt_size); 3279af81cf32SBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, id); 3280af81cf32SBharata B Rao offset = fdt_add_subnode(fdt, 0, nodename); 3281af81cf32SBharata B Rao 3282af81cf32SBharata B Rao spapr_populate_cpu_dt(cs, fdt, offset, spapr); 3283af81cf32SBharata B Rao g_free(nodename); 3284af81cf32SBharata B Rao 3285af81cf32SBharata B Rao *fdt_offset = offset; 3286af81cf32SBharata B Rao return fdt; 3287af81cf32SBharata B Rao } 3288af81cf32SBharata B Rao 3289765d1bddSDavid Gibson /* Callback to be called during DRC release. */ 3290765d1bddSDavid Gibson void spapr_core_release(DeviceState *dev) 3291ff9006ddSIgor Mammedov { 3292765d1bddSDavid Gibson MachineState *ms = MACHINE(qdev_get_hotplug_handler(dev)); 329346f7afa3SGreg Kurz sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms); 3294ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3295535455fdSIgor Mammedov CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL); 3296ff9006ddSIgor Mammedov 329746f7afa3SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 329846f7afa3SGreg Kurz sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); 329946f7afa3SGreg Kurz int i; 330046f7afa3SGreg Kurz 330146f7afa3SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 330294ad93bdSGreg Kurz CPUState *cs = CPU(sc->threads[i]); 330346f7afa3SGreg Kurz 330446f7afa3SGreg Kurz pre_2_10_vmstate_register_dummy_icp(cs->cpu_index); 330546f7afa3SGreg Kurz } 330646f7afa3SGreg Kurz } 330746f7afa3SGreg Kurz 330807572c06SGreg Kurz assert(core_slot); 3309535455fdSIgor Mammedov core_slot->cpu = NULL; 3310ff9006ddSIgor Mammedov object_unparent(OBJECT(dev)); 3311ff9006ddSIgor Mammedov } 3312ff9006ddSIgor Mammedov 3313115debf2SIgor Mammedov static 3314115debf2SIgor Mammedov void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, 3315ff9006ddSIgor Mammedov Error **errp) 3316ff9006ddSIgor Mammedov { 331772194664SGreg Kurz sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3318535455fdSIgor Mammedov int index; 3319535455fdSIgor Mammedov sPAPRDRConnector *drc; 3320535455fdSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 3321ff9006ddSIgor Mammedov 3322535455fdSIgor Mammedov if (!spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index)) { 3323535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 3324535455fdSIgor Mammedov cc->core_id); 3325535455fdSIgor Mammedov return; 3326535455fdSIgor Mammedov } 3327ff9006ddSIgor Mammedov if (index == 0) { 3328ff9006ddSIgor Mammedov error_setg(errp, "Boot CPU core may not be unplugged"); 3329ff9006ddSIgor Mammedov return; 3330ff9006ddSIgor Mammedov } 3331ff9006ddSIgor Mammedov 33325d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 33335d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 3334ff9006ddSIgor Mammedov g_assert(drc); 3335ff9006ddSIgor Mammedov 3336a8dc47fdSDavid Gibson spapr_drc_detach(drc); 3337ff9006ddSIgor Mammedov 3338ff9006ddSIgor Mammedov spapr_hotplug_req_remove_by_index(drc); 3339ff9006ddSIgor Mammedov } 3340ff9006ddSIgor Mammedov 3341ff9006ddSIgor Mammedov static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3342ff9006ddSIgor Mammedov Error **errp) 3343ff9006ddSIgor Mammedov { 3344ff9006ddSIgor Mammedov sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3345ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(spapr); 334646f7afa3SGreg Kurz sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 3347ff9006ddSIgor Mammedov sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev)); 3348ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 334994ad93bdSGreg Kurz CPUState *cs = CPU(core->threads[0]); 3350ff9006ddSIgor Mammedov sPAPRDRConnector *drc; 3351ff9006ddSIgor Mammedov Error *local_err = NULL; 3352535455fdSIgor Mammedov CPUArchId *core_slot; 3353535455fdSIgor Mammedov int index; 335494fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev); 3355ff9006ddSIgor Mammedov 3356535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 3357535455fdSIgor Mammedov if (!core_slot) { 3358535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 3359535455fdSIgor Mammedov cc->core_id); 3360535455fdSIgor Mammedov return; 3361535455fdSIgor Mammedov } 33625d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, 33635d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id)); 3364ff9006ddSIgor Mammedov 3365c5514d0eSIgor Mammedov g_assert(drc || !mc->has_hotpluggable_cpus); 3366ff9006ddSIgor Mammedov 3367e49c63d5SGreg Kurz if (drc) { 3368e49c63d5SGreg Kurz void *fdt; 3369e49c63d5SGreg Kurz int fdt_offset; 3370e49c63d5SGreg Kurz 3371ff9006ddSIgor Mammedov fdt = spapr_populate_hotplug_cpu_dt(cs, &fdt_offset, spapr); 3372ff9006ddSIgor Mammedov 33735c1da812SDavid Gibson spapr_drc_attach(drc, dev, fdt, fdt_offset, &local_err); 3374ff9006ddSIgor Mammedov if (local_err) { 3375ff9006ddSIgor Mammedov g_free(fdt); 3376ff9006ddSIgor Mammedov error_propagate(errp, local_err); 3377ff9006ddSIgor Mammedov return; 3378ff9006ddSIgor Mammedov } 3379ff9006ddSIgor Mammedov 338094fd9cbaSLaurent Vivier if (hotplugged) { 3381ff9006ddSIgor Mammedov /* 338294fd9cbaSLaurent Vivier * Send hotplug notification interrupt to the guest only 338394fd9cbaSLaurent Vivier * in case of hotplugged CPUs. 3384ff9006ddSIgor Mammedov */ 3385ff9006ddSIgor Mammedov spapr_hotplug_req_add_by_index(drc); 338694fd9cbaSLaurent Vivier } else { 338794fd9cbaSLaurent Vivier spapr_drc_reset(drc); 3388ff9006ddSIgor Mammedov } 338994fd9cbaSLaurent Vivier } 339094fd9cbaSLaurent Vivier 3391535455fdSIgor Mammedov core_slot->cpu = OBJECT(dev); 339246f7afa3SGreg Kurz 339346f7afa3SGreg Kurz if (smc->pre_2_10_has_unused_icps) { 339446f7afa3SGreg Kurz int i; 339546f7afa3SGreg Kurz 339646f7afa3SGreg Kurz for (i = 0; i < cc->nr_threads; i++) { 3397bc877283SGreg Kurz cs = CPU(core->threads[i]); 339846f7afa3SGreg Kurz pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index); 339946f7afa3SGreg Kurz } 340046f7afa3SGreg Kurz } 3401ff9006ddSIgor Mammedov } 3402ff9006ddSIgor Mammedov 3403ff9006ddSIgor Mammedov static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 3404ff9006ddSIgor Mammedov Error **errp) 3405ff9006ddSIgor Mammedov { 3406ff9006ddSIgor Mammedov MachineState *machine = MACHINE(OBJECT(hotplug_dev)); 3407ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); 3408ff9006ddSIgor Mammedov Error *local_err = NULL; 3409ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 34102e9c10ebSIgor Mammedov const char *base_core_type = spapr_get_cpu_core_type(machine->cpu_type); 3411ff9006ddSIgor Mammedov const char *type = object_get_typename(OBJECT(dev)); 3412535455fdSIgor Mammedov CPUArchId *core_slot; 3413535455fdSIgor Mammedov int index; 3414ff9006ddSIgor Mammedov 3415c5514d0eSIgor Mammedov if (dev->hotplugged && !mc->has_hotpluggable_cpus) { 3416ff9006ddSIgor Mammedov error_setg(&local_err, "CPU hotplug not supported for this machine"); 3417ff9006ddSIgor Mammedov goto out; 3418ff9006ddSIgor Mammedov } 3419ff9006ddSIgor Mammedov 3420ff9006ddSIgor Mammedov if (strcmp(base_core_type, type)) { 3421ff9006ddSIgor Mammedov error_setg(&local_err, "CPU core type should be %s", base_core_type); 3422ff9006ddSIgor Mammedov goto out; 3423ff9006ddSIgor Mammedov } 3424ff9006ddSIgor Mammedov 3425ff9006ddSIgor Mammedov if (cc->core_id % smp_threads) { 3426ff9006ddSIgor Mammedov error_setg(&local_err, "invalid core id %d", cc->core_id); 3427ff9006ddSIgor Mammedov goto out; 3428ff9006ddSIgor Mammedov } 3429ff9006ddSIgor Mammedov 3430459264efSDavid Gibson /* 3431459264efSDavid Gibson * In general we should have homogeneous threads-per-core, but old 3432459264efSDavid Gibson * (pre hotplug support) machine types allow the last core to have 3433459264efSDavid Gibson * reduced threads as a compatibility hack for when we allowed 3434459264efSDavid Gibson * total vcpus not a multiple of threads-per-core. 3435459264efSDavid Gibson */ 3436459264efSDavid Gibson if (mc->has_hotpluggable_cpus && (cc->nr_threads != smp_threads)) { 3437df8658deSGreg Kurz error_setg(&local_err, "invalid nr-threads %d, must be %d", 34388149e299SDavid Gibson cc->nr_threads, smp_threads); 3439df8658deSGreg Kurz goto out; 34408149e299SDavid Gibson } 34418149e299SDavid Gibson 3442535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 3443535455fdSIgor Mammedov if (!core_slot) { 3444ff9006ddSIgor Mammedov error_setg(&local_err, "core id %d out of range", cc->core_id); 3445ff9006ddSIgor Mammedov goto out; 3446ff9006ddSIgor Mammedov } 3447ff9006ddSIgor Mammedov 3448535455fdSIgor Mammedov if (core_slot->cpu) { 3449ff9006ddSIgor Mammedov error_setg(&local_err, "core %d already populated", cc->core_id); 3450ff9006ddSIgor Mammedov goto out; 3451ff9006ddSIgor Mammedov } 3452ff9006ddSIgor Mammedov 3453a0ceb640SIgor Mammedov numa_cpu_pre_plug(core_slot, dev, &local_err); 34540b8497f0SIgor Mammedov 3455ff9006ddSIgor Mammedov out: 3456ff9006ddSIgor Mammedov error_propagate(errp, local_err); 3457ff9006ddSIgor Mammedov } 3458ff9006ddSIgor Mammedov 3459c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, 3460c20d332aSBharata B Rao DeviceState *dev, Error **errp) 3461c20d332aSBharata B Rao { 3462c86c1affSDaniel Henrique Barboza MachineState *ms = MACHINE(hotplug_dev); 3463c86c1affSDaniel Henrique Barboza sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms); 3464c20d332aSBharata B Rao 3465c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 3466b556854bSBharata B Rao int node; 3467c20d332aSBharata B Rao 3468c20d332aSBharata B Rao if (!smc->dr_lmb_enabled) { 3469c20d332aSBharata B Rao error_setg(errp, "Memory hotplug not supported for this machine"); 3470c20d332aSBharata B Rao return; 3471c20d332aSBharata B Rao } 34729ed442b8SMarc-André Lureau node = object_property_get_uint(OBJECT(dev), PC_DIMM_NODE_PROP, errp); 3473c20d332aSBharata B Rao if (*errp) { 3474c20d332aSBharata B Rao return; 3475c20d332aSBharata B Rao } 34761a5512bbSGonglei if (node < 0 || node >= MAX_NODES) { 34771a5512bbSGonglei error_setg(errp, "Invaild node %d", node); 34781a5512bbSGonglei return; 34791a5512bbSGonglei } 3480c20d332aSBharata B Rao 3481b556854bSBharata B Rao /* 3482b556854bSBharata B Rao * Currently PowerPC kernel doesn't allow hot-adding memory to 3483b556854bSBharata B Rao * memory-less node, but instead will silently add the memory 3484b556854bSBharata B Rao * to the first node that has some memory. This causes two 3485b556854bSBharata B Rao * unexpected behaviours for the user. 3486b556854bSBharata B Rao * 3487b556854bSBharata B Rao * - Memory gets hotplugged to a different node than what the user 3488b556854bSBharata B Rao * specified. 3489b556854bSBharata B Rao * - Since pc-dimm subsystem in QEMU still thinks that memory belongs 3490b556854bSBharata B Rao * to memory-less node, a reboot will set things accordingly 3491b556854bSBharata B Rao * and the previously hotplugged memory now ends in the right node. 3492b556854bSBharata B Rao * This appears as if some memory moved from one node to another. 3493b556854bSBharata B Rao * 3494b556854bSBharata B Rao * So until kernel starts supporting memory hotplug to memory-less 3495b556854bSBharata B Rao * nodes, just prevent such attempts upfront in QEMU. 3496b556854bSBharata B Rao */ 3497b556854bSBharata B Rao if (nb_numa_nodes && !numa_info[node].node_mem) { 3498b556854bSBharata B Rao error_setg(errp, "Can't hotplug memory to memory-less node %d", 3499b556854bSBharata B Rao node); 3500b556854bSBharata B Rao return; 3501b556854bSBharata B Rao } 3502b556854bSBharata B Rao 3503c20d332aSBharata B Rao spapr_memory_plug(hotplug_dev, dev, node, errp); 3504af81cf32SBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 3505af81cf32SBharata B Rao spapr_core_plug(hotplug_dev, dev, errp); 3506c20d332aSBharata B Rao } 3507c20d332aSBharata B Rao } 3508c20d332aSBharata B Rao 3509cf632463SBharata B Rao static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev, 3510cf632463SBharata B Rao DeviceState *dev, Error **errp) 3511cf632463SBharata B Rao { 3512c86c1affSDaniel Henrique Barboza sPAPRMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev)); 3513c86c1affSDaniel Henrique Barboza MachineClass *mc = MACHINE_GET_CLASS(sms); 3514cf632463SBharata B Rao 3515cf632463SBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 3516cf632463SBharata B Rao if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) { 3517cf632463SBharata B Rao spapr_memory_unplug_request(hotplug_dev, dev, errp); 3518cf632463SBharata B Rao } else { 3519cf632463SBharata B Rao /* NOTE: this means there is a window after guest reset, prior to 3520cf632463SBharata B Rao * CAS negotiation, where unplug requests will fail due to the 3521cf632463SBharata B Rao * capability not being detected yet. This is a bit different than 3522cf632463SBharata B Rao * the case with PCI unplug, where the events will be queued and 3523cf632463SBharata B Rao * eventually handled by the guest after boot 3524cf632463SBharata B Rao */ 3525cf632463SBharata B Rao error_setg(errp, "Memory hot unplug not supported for this guest"); 3526cf632463SBharata B Rao } 35276f4b5c3eSBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 3528c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 35296f4b5c3eSBharata B Rao error_setg(errp, "CPU hot unplug not supported on this machine"); 35306f4b5c3eSBharata B Rao return; 35316f4b5c3eSBharata B Rao } 3532115debf2SIgor Mammedov spapr_core_unplug_request(hotplug_dev, dev, errp); 3533c20d332aSBharata B Rao } 3534c20d332aSBharata B Rao } 3535c20d332aSBharata B Rao 353694a94e4cSBharata B Rao static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, 353794a94e4cSBharata B Rao DeviceState *dev, Error **errp) 353894a94e4cSBharata B Rao { 3539c871bc70SLaurent Vivier if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 3540c871bc70SLaurent Vivier spapr_memory_pre_plug(hotplug_dev, dev, errp); 3541c871bc70SLaurent Vivier } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 354294a94e4cSBharata B Rao spapr_core_pre_plug(hotplug_dev, dev, errp); 354394a94e4cSBharata B Rao } 354494a94e4cSBharata B Rao } 354594a94e4cSBharata B Rao 35467ebaf795SBharata B Rao static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine, 3547c20d332aSBharata B Rao DeviceState *dev) 3548c20d332aSBharata B Rao { 354994a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || 355094a94e4cSBharata B Rao object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 3551c20d332aSBharata B Rao return HOTPLUG_HANDLER(machine); 3552c20d332aSBharata B Rao } 3553c20d332aSBharata B Rao return NULL; 3554c20d332aSBharata B Rao } 3555c20d332aSBharata B Rao 3556ea089eebSIgor Mammedov static CpuInstanceProperties 3557ea089eebSIgor Mammedov spapr_cpu_index_to_props(MachineState *machine, unsigned cpu_index) 355820bb648dSDavid Gibson { 3559ea089eebSIgor Mammedov CPUArchId *core_slot; 3560ea089eebSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 3561ea089eebSIgor Mammedov 3562ea089eebSIgor Mammedov /* make sure possible_cpu are intialized */ 3563ea089eebSIgor Mammedov mc->possible_cpu_arch_ids(machine); 3564ea089eebSIgor Mammedov /* get CPU core slot containing thread that matches cpu_index */ 3565ea089eebSIgor Mammedov core_slot = spapr_find_cpu_slot(machine, cpu_index, NULL); 3566ea089eebSIgor Mammedov assert(core_slot); 3567ea089eebSIgor Mammedov return core_slot->props; 356820bb648dSDavid Gibson } 356920bb648dSDavid Gibson 357079e07936SIgor Mammedov static int64_t spapr_get_default_cpu_node_id(const MachineState *ms, int idx) 357179e07936SIgor Mammedov { 357279e07936SIgor Mammedov return idx / smp_cores % nb_numa_nodes; 357379e07936SIgor Mammedov } 357479e07936SIgor Mammedov 3575535455fdSIgor Mammedov static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine) 3576535455fdSIgor Mammedov { 3577535455fdSIgor Mammedov int i; 3578d342eb76SIgor Mammedov const char *core_type; 3579535455fdSIgor Mammedov int spapr_max_cores = max_cpus / smp_threads; 3580535455fdSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 3581535455fdSIgor Mammedov 3582c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 3583535455fdSIgor Mammedov spapr_max_cores = QEMU_ALIGN_UP(smp_cpus, smp_threads) / smp_threads; 3584535455fdSIgor Mammedov } 3585535455fdSIgor Mammedov if (machine->possible_cpus) { 3586535455fdSIgor Mammedov assert(machine->possible_cpus->len == spapr_max_cores); 3587535455fdSIgor Mammedov return machine->possible_cpus; 3588535455fdSIgor Mammedov } 3589535455fdSIgor Mammedov 3590d342eb76SIgor Mammedov core_type = spapr_get_cpu_core_type(machine->cpu_type); 3591d342eb76SIgor Mammedov if (!core_type) { 3592d342eb76SIgor Mammedov error_report("Unable to find sPAPR CPU Core definition"); 3593d342eb76SIgor Mammedov exit(1); 3594d342eb76SIgor Mammedov } 3595d342eb76SIgor Mammedov 3596535455fdSIgor Mammedov machine->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + 3597535455fdSIgor Mammedov sizeof(CPUArchId) * spapr_max_cores); 3598535455fdSIgor Mammedov machine->possible_cpus->len = spapr_max_cores; 3599535455fdSIgor Mammedov for (i = 0; i < machine->possible_cpus->len; i++) { 3600535455fdSIgor Mammedov int core_id = i * smp_threads; 3601535455fdSIgor Mammedov 3602d342eb76SIgor Mammedov machine->possible_cpus->cpus[i].type = core_type; 3603f2d672c2SIgor Mammedov machine->possible_cpus->cpus[i].vcpus_count = smp_threads; 3604535455fdSIgor Mammedov machine->possible_cpus->cpus[i].arch_id = core_id; 3605535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.has_core_id = true; 3606535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.core_id = core_id; 3607535455fdSIgor Mammedov } 3608535455fdSIgor Mammedov return machine->possible_cpus; 3609535455fdSIgor Mammedov } 3610535455fdSIgor Mammedov 36116737d9adSDavid Gibson static void spapr_phb_placement(sPAPRMachineState *spapr, uint32_t index, 3612daa23699SDavid Gibson uint64_t *buid, hwaddr *pio, 3613daa23699SDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 36146737d9adSDavid Gibson unsigned n_dma, uint32_t *liobns, Error **errp) 36156737d9adSDavid Gibson { 3616357d1e3bSDavid Gibson /* 3617357d1e3bSDavid Gibson * New-style PHB window placement. 3618357d1e3bSDavid Gibson * 3619357d1e3bSDavid Gibson * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window 3620357d1e3bSDavid Gibson * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO 3621357d1e3bSDavid Gibson * windows. 3622357d1e3bSDavid Gibson * 3623357d1e3bSDavid Gibson * Some guest kernels can't work with MMIO windows above 1<<46 3624357d1e3bSDavid Gibson * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB 3625357d1e3bSDavid Gibson * 3626357d1e3bSDavid Gibson * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each 3627357d1e3bSDavid Gibson * PHB stacked together. (32TiB+2GiB)..(32TiB+64GiB) contains the 3628357d1e3bSDavid Gibson * 2GiB 32-bit MMIO windows for each PHB. Then 33..64TiB has the 3629357d1e3bSDavid Gibson * 1TiB 64-bit MMIO windows for each PHB. 3630357d1e3bSDavid Gibson */ 36316737d9adSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 363225e6a118SMichael S. Tsirkin #define SPAPR_MAX_PHBS ((SPAPR_PCI_LIMIT - SPAPR_PCI_BASE) / \ 363325e6a118SMichael S. Tsirkin SPAPR_PCI_MEM64_WIN_SIZE - 1) 36346737d9adSDavid Gibson int i; 36356737d9adSDavid Gibson 3636357d1e3bSDavid Gibson /* Sanity check natural alignments */ 3637357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 3638357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 3639357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0); 3640357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0); 3641357d1e3bSDavid Gibson /* Sanity check bounds */ 364225e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_IO_WIN_SIZE) > 364325e6a118SMichael S. Tsirkin SPAPR_PCI_MEM32_WIN_SIZE); 364425e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_MEM32_WIN_SIZE) > 364525e6a118SMichael S. Tsirkin SPAPR_PCI_MEM64_WIN_SIZE); 36462efff1c0SDavid Gibson 364725e6a118SMichael S. Tsirkin if (index >= SPAPR_MAX_PHBS) { 364825e6a118SMichael S. Tsirkin error_setg(errp, "\"index\" for PAPR PHB is too large (max %llu)", 364925e6a118SMichael S. Tsirkin SPAPR_MAX_PHBS - 1); 36506737d9adSDavid Gibson return; 36516737d9adSDavid Gibson } 36526737d9adSDavid Gibson 36536737d9adSDavid Gibson *buid = base_buid + index; 36546737d9adSDavid Gibson for (i = 0; i < n_dma; ++i) { 36556737d9adSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 36566737d9adSDavid Gibson } 36576737d9adSDavid Gibson 3658357d1e3bSDavid Gibson *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE; 3659357d1e3bSDavid Gibson *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE; 3660357d1e3bSDavid Gibson *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE; 36616737d9adSDavid Gibson } 36626737d9adSDavid Gibson 36637844e12bSCédric Le Goater static ICSState *spapr_ics_get(XICSFabric *dev, int irq) 36647844e12bSCédric Le Goater { 36657844e12bSCédric Le Goater sPAPRMachineState *spapr = SPAPR_MACHINE(dev); 36667844e12bSCédric Le Goater 36677844e12bSCédric Le Goater return ics_valid_irq(spapr->ics, irq) ? spapr->ics : NULL; 36687844e12bSCédric Le Goater } 36697844e12bSCédric Le Goater 36707844e12bSCédric Le Goater static void spapr_ics_resend(XICSFabric *dev) 36717844e12bSCédric Le Goater { 36727844e12bSCédric Le Goater sPAPRMachineState *spapr = SPAPR_MACHINE(dev); 36737844e12bSCédric Le Goater 36747844e12bSCédric Le Goater ics_resend(spapr->ics); 36757844e12bSCédric Le Goater } 36767844e12bSCédric Le Goater 367781210c20SSam Bobroff static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id) 3678b2fc59aaSCédric Le Goater { 36792e886fb3SSam Bobroff PowerPCCPU *cpu = spapr_find_cpu(vcpu_id); 3680b2fc59aaSCédric Le Goater 36815bc8d26dSCédric Le Goater return cpu ? ICP(cpu->intc) : NULL; 3682b2fc59aaSCédric Le Goater } 3683b2fc59aaSCédric Le Goater 368460c6823bSCédric Le Goater #define ICS_IRQ_FREE(ics, srcno) \ 368560c6823bSCédric Le Goater (!((ics)->irqs[(srcno)].flags & (XICS_FLAGS_IRQ_MASK))) 368660c6823bSCédric Le Goater 368760c6823bSCédric Le Goater static int ics_find_free_block(ICSState *ics, int num, int alignnum) 368860c6823bSCédric Le Goater { 368960c6823bSCédric Le Goater int first, i; 369060c6823bSCédric Le Goater 369160c6823bSCédric Le Goater for (first = 0; first < ics->nr_irqs; first += alignnum) { 369260c6823bSCédric Le Goater if (num > (ics->nr_irqs - first)) { 369360c6823bSCédric Le Goater return -1; 369460c6823bSCédric Le Goater } 369560c6823bSCédric Le Goater for (i = first; i < first + num; ++i) { 369660c6823bSCédric Le Goater if (!ICS_IRQ_FREE(ics, i)) { 369760c6823bSCédric Le Goater break; 369860c6823bSCédric Le Goater } 369960c6823bSCédric Le Goater } 370060c6823bSCédric Le Goater if (i == (first + num)) { 370160c6823bSCédric Le Goater return first; 370260c6823bSCédric Le Goater } 370360c6823bSCédric Le Goater } 370460c6823bSCédric Le Goater 370560c6823bSCédric Le Goater return -1; 370660c6823bSCédric Le Goater } 370760c6823bSCédric Le Goater 37089e7dc5fcSCédric Le Goater /* 37099e7dc5fcSCédric Le Goater * Allocate the IRQ number and set the IRQ type, LSI or MSI 37109e7dc5fcSCédric Le Goater */ 37119e7dc5fcSCédric Le Goater static void spapr_irq_set_lsi(sPAPRMachineState *spapr, int irq, bool lsi) 37129e7dc5fcSCédric Le Goater { 37139e7dc5fcSCédric Le Goater ics_set_irq_type(spapr->ics, irq - spapr->ics->offset, lsi); 37149e7dc5fcSCédric Le Goater } 37159e7dc5fcSCédric Le Goater 371660c6823bSCédric Le Goater int spapr_irq_alloc(sPAPRMachineState *spapr, int irq_hint, bool lsi, 371760c6823bSCédric Le Goater Error **errp) 371860c6823bSCédric Le Goater { 371960c6823bSCédric Le Goater ICSState *ics = spapr->ics; 372060c6823bSCédric Le Goater int irq; 372160c6823bSCédric Le Goater 3722*1d36c75aSGreg Kurz assert(ics); 3723*1d36c75aSGreg Kurz 372460c6823bSCédric Le Goater if (irq_hint) { 372560c6823bSCédric Le Goater if (!ICS_IRQ_FREE(ics, irq_hint - ics->offset)) { 372660c6823bSCédric Le Goater error_setg(errp, "can't allocate IRQ %d: already in use", irq_hint); 372760c6823bSCédric Le Goater return -1; 372860c6823bSCédric Le Goater } 372960c6823bSCédric Le Goater irq = irq_hint; 373060c6823bSCédric Le Goater } else { 373160c6823bSCédric Le Goater irq = ics_find_free_block(ics, 1, 1); 373260c6823bSCédric Le Goater if (irq < 0) { 373360c6823bSCédric Le Goater error_setg(errp, "can't allocate IRQ: no IRQ left"); 373460c6823bSCédric Le Goater return -1; 373560c6823bSCédric Le Goater } 373660c6823bSCédric Le Goater irq += ics->offset; 373760c6823bSCédric Le Goater } 373860c6823bSCédric Le Goater 37399e7dc5fcSCédric Le Goater spapr_irq_set_lsi(spapr, irq, lsi); 374060c6823bSCédric Le Goater trace_spapr_irq_alloc(irq); 374160c6823bSCédric Le Goater 374260c6823bSCédric Le Goater return irq; 374360c6823bSCédric Le Goater } 374460c6823bSCédric Le Goater 374560c6823bSCédric Le Goater /* 374660c6823bSCédric Le Goater * Allocate block of consecutive IRQs, and return the number of the first IRQ in 374760c6823bSCédric Le Goater * the block. If align==true, aligns the first IRQ number to num. 374860c6823bSCédric Le Goater */ 374960c6823bSCédric Le Goater int spapr_irq_alloc_block(sPAPRMachineState *spapr, int num, bool lsi, 375060c6823bSCédric Le Goater bool align, Error **errp) 375160c6823bSCédric Le Goater { 375260c6823bSCédric Le Goater ICSState *ics = spapr->ics; 375360c6823bSCédric Le Goater int i, first = -1; 375460c6823bSCédric Le Goater 3755*1d36c75aSGreg Kurz assert(ics); 375660c6823bSCédric Le Goater 375760c6823bSCédric Le Goater /* 375860c6823bSCédric Le Goater * MSIMesage::data is used for storing VIRQ so 375960c6823bSCédric Le Goater * it has to be aligned to num to support multiple 376060c6823bSCédric Le Goater * MSI vectors. MSI-X is not affected by this. 376160c6823bSCédric Le Goater * The hint is used for the first IRQ, the rest should 376260c6823bSCédric Le Goater * be allocated continuously. 376360c6823bSCédric Le Goater */ 376460c6823bSCédric Le Goater if (align) { 376560c6823bSCédric Le Goater assert((num == 1) || (num == 2) || (num == 4) || 376660c6823bSCédric Le Goater (num == 8) || (num == 16) || (num == 32)); 376760c6823bSCédric Le Goater first = ics_find_free_block(ics, num, num); 376860c6823bSCédric Le Goater } else { 376960c6823bSCédric Le Goater first = ics_find_free_block(ics, num, 1); 377060c6823bSCédric Le Goater } 377160c6823bSCédric Le Goater if (first < 0) { 377260c6823bSCédric Le Goater error_setg(errp, "can't find a free %d-IRQ block", num); 377360c6823bSCédric Le Goater return -1; 377460c6823bSCédric Le Goater } 377560c6823bSCédric Le Goater 377660c6823bSCédric Le Goater first += ics->offset; 37779e7dc5fcSCédric Le Goater for (i = first; i < first + num; ++i) { 37789e7dc5fcSCédric Le Goater spapr_irq_set_lsi(spapr, i, lsi); 37799e7dc5fcSCédric Le Goater } 378060c6823bSCédric Le Goater 378160c6823bSCédric Le Goater trace_spapr_irq_alloc_block(first, num, lsi, align); 378260c6823bSCédric Le Goater 378360c6823bSCédric Le Goater return first; 378460c6823bSCédric Le Goater } 378560c6823bSCédric Le Goater 378660c6823bSCédric Le Goater void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num) 378760c6823bSCédric Le Goater { 378860c6823bSCédric Le Goater ICSState *ics = spapr->ics; 378960c6823bSCédric Le Goater int srcno = irq - ics->offset; 379060c6823bSCédric Le Goater int i; 379160c6823bSCédric Le Goater 379260c6823bSCédric Le Goater if (ics_valid_irq(ics, irq)) { 379360c6823bSCédric Le Goater trace_spapr_irq_free(0, irq, num); 379460c6823bSCédric Le Goater for (i = srcno; i < srcno + num; ++i) { 379560c6823bSCédric Le Goater if (ICS_IRQ_FREE(ics, i)) { 379660c6823bSCédric Le Goater trace_spapr_irq_free_warn(0, i + ics->offset); 379760c6823bSCédric Le Goater } 379860c6823bSCédric Le Goater memset(&ics->irqs[i], 0, sizeof(ICSIRQState)); 379960c6823bSCédric Le Goater } 380060c6823bSCédric Le Goater } 380160c6823bSCédric Le Goater } 380260c6823bSCédric Le Goater 380377183755SCédric Le Goater qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq) 380477183755SCédric Le Goater { 380577183755SCédric Le Goater ICSState *ics = spapr->ics; 380677183755SCédric Le Goater 380777183755SCédric Le Goater if (ics_valid_irq(ics, irq)) { 380877183755SCédric Le Goater return ics->qirqs[irq - ics->offset]; 380977183755SCédric Le Goater } 381077183755SCédric Le Goater 381177183755SCédric Le Goater return NULL; 381277183755SCédric Le Goater } 381377183755SCédric Le Goater 38146449da45SCédric Le Goater static void spapr_pic_print_info(InterruptStatsProvider *obj, 38156449da45SCédric Le Goater Monitor *mon) 38166449da45SCédric Le Goater { 38176449da45SCédric Le Goater sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 38185bc8d26dSCédric Le Goater CPUState *cs; 38196449da45SCédric Le Goater 38205bc8d26dSCédric Le Goater CPU_FOREACH(cs) { 38215bc8d26dSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 38225bc8d26dSCédric Le Goater 38235bc8d26dSCédric Le Goater icp_pic_print_info(ICP(cpu->intc), mon); 38246449da45SCédric Le Goater } 38256449da45SCédric Le Goater 38266449da45SCédric Le Goater ics_pic_print_info(spapr->ics, mon); 38276449da45SCédric Le Goater } 38286449da45SCédric Le Goater 382914bb4486SGreg Kurz int spapr_get_vcpu_id(PowerPCCPU *cpu) 38302e886fb3SSam Bobroff { 3831b1a568c1SGreg Kurz return cpu->vcpu_id; 38322e886fb3SSam Bobroff } 38332e886fb3SSam Bobroff 3834648edb64SGreg Kurz void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp) 3835648edb64SGreg Kurz { 3836648edb64SGreg Kurz sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 3837648edb64SGreg Kurz int vcpu_id; 3838648edb64SGreg Kurz 38395d0fb150SGreg Kurz vcpu_id = spapr_vcpu_id(spapr, cpu_index); 3840648edb64SGreg Kurz 3841648edb64SGreg Kurz if (kvm_enabled() && !kvm_vcpu_id_is_valid(vcpu_id)) { 3842648edb64SGreg Kurz error_setg(errp, "Can't create CPU with id %d in KVM", vcpu_id); 3843648edb64SGreg Kurz error_append_hint(errp, "Adjust the number of cpus to %d " 3844648edb64SGreg Kurz "or try to raise the number of threads per core\n", 3845648edb64SGreg Kurz vcpu_id * smp_threads / spapr->vsmt); 3846648edb64SGreg Kurz return; 3847648edb64SGreg Kurz } 3848648edb64SGreg Kurz 3849648edb64SGreg Kurz cpu->vcpu_id = vcpu_id; 3850648edb64SGreg Kurz } 3851648edb64SGreg Kurz 38522e886fb3SSam Bobroff PowerPCCPU *spapr_find_cpu(int vcpu_id) 38532e886fb3SSam Bobroff { 38542e886fb3SSam Bobroff CPUState *cs; 38552e886fb3SSam Bobroff 38562e886fb3SSam Bobroff CPU_FOREACH(cs) { 38572e886fb3SSam Bobroff PowerPCCPU *cpu = POWERPC_CPU(cs); 38582e886fb3SSam Bobroff 385914bb4486SGreg Kurz if (spapr_get_vcpu_id(cpu) == vcpu_id) { 38602e886fb3SSam Bobroff return cpu; 38612e886fb3SSam Bobroff } 38622e886fb3SSam Bobroff } 38632e886fb3SSam Bobroff 38642e886fb3SSam Bobroff return NULL; 38652e886fb3SSam Bobroff } 38662e886fb3SSam Bobroff 386729ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data) 386853018216SPaolo Bonzini { 386929ee3247SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 3870224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc); 387171461b0fSAlexey Kardashevskiy FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); 387234316482SAlexey Kardashevskiy NMIClass *nc = NMI_CLASS(oc); 3873c20d332aSBharata B Rao HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); 38741d1be34dSDavid Gibson PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc); 38757844e12bSCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 38766449da45SCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 387729ee3247SAlexey Kardashevskiy 38780eb9054cSDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant)"; 3879fc9f38c3SDavid Gibson 3880fc9f38c3SDavid Gibson /* 3881fc9f38c3SDavid Gibson * We set up the default / latest behaviour here. The class_init 3882fc9f38c3SDavid Gibson * functions for the specific versioned machine types can override 3883fc9f38c3SDavid Gibson * these details for backwards compatibility 3884fc9f38c3SDavid Gibson */ 3885bcb5ce08SDavid Gibson mc->init = spapr_machine_init; 3886bcb5ce08SDavid Gibson mc->reset = spapr_machine_reset; 3887958db90cSMarcel Apfelbaum mc->block_default_type = IF_SCSI; 38886244bb7eSGreg Kurz mc->max_cpus = 1024; 3889958db90cSMarcel Apfelbaum mc->no_parallel = 1; 38905b2128d2SAlexander Graf mc->default_boot_order = ""; 3891a34944feSNikunj A Dadhania mc->default_ram_size = 512 * M_BYTE; 3892958db90cSMarcel Apfelbaum mc->kvm_type = spapr_kvm_type; 38937da79a16SEduardo Habkost machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SPAPR_PCI_HOST_BRIDGE); 3894e4024630SLaurent Vivier mc->pci_allow_0_address = true; 38957ebaf795SBharata B Rao mc->get_hotplug_handler = spapr_get_hotplug_handler; 389694a94e4cSBharata B Rao hc->pre_plug = spapr_machine_device_pre_plug; 3897c20d332aSBharata B Rao hc->plug = spapr_machine_device_plug; 3898ea089eebSIgor Mammedov mc->cpu_index_to_instance_props = spapr_cpu_index_to_props; 389979e07936SIgor Mammedov mc->get_default_cpu_node_id = spapr_get_default_cpu_node_id; 3900535455fdSIgor Mammedov mc->possible_cpu_arch_ids = spapr_possible_cpu_arch_ids; 3901cf632463SBharata B Rao hc->unplug_request = spapr_machine_device_unplug_request; 390200b4fbe2SMarcel Apfelbaum 3903fc9f38c3SDavid Gibson smc->dr_lmb_enabled = true; 39042e9c10ebSIgor Mammedov mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 3905c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = true; 390652b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED; 390771461b0fSAlexey Kardashevskiy fwc->get_dev_path = spapr_get_fw_dev_path; 390834316482SAlexey Kardashevskiy nc->nmi_monitor_handler = spapr_nmi; 39096737d9adSDavid Gibson smc->phb_placement = spapr_phb_placement; 39101d1be34dSDavid Gibson vhc->hypercall = emulate_spapr_hypercall; 3911e57ca75cSDavid Gibson vhc->hpt_mask = spapr_hpt_mask; 3912e57ca75cSDavid Gibson vhc->map_hptes = spapr_map_hptes; 3913e57ca75cSDavid Gibson vhc->unmap_hptes = spapr_unmap_hptes; 3914e57ca75cSDavid Gibson vhc->store_hpte = spapr_store_hpte; 39159861bb3eSSuraj Jitindar Singh vhc->get_patbe = spapr_get_patbe; 39161ec26c75SGreg Kurz vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr; 39177844e12bSCédric Le Goater xic->ics_get = spapr_ics_get; 39187844e12bSCédric Le Goater xic->ics_resend = spapr_ics_resend; 3919b2fc59aaSCédric Le Goater xic->icp_get = spapr_icp_get; 39206449da45SCédric Le Goater ispc->print_info = spapr_pic_print_info; 392155641213SLaurent Vivier /* Force NUMA node memory size to be a multiple of 392255641213SLaurent Vivier * SPAPR_MEMORY_BLOCK_SIZE (256M) since that's the granularity 392355641213SLaurent Vivier * in which LMBs are represented and hot-added 392455641213SLaurent Vivier */ 392555641213SLaurent Vivier mc->numa_mem_align_shift = 28; 392633face6bSDavid Gibson 39274e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF; 39284e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON; 39294e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON; 39308f38eaf8SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN; 393109114fd8SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN; 39324be8d4e7SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN; 393333face6bSDavid Gibson spapr_caps_add_properties(smc, &error_abort); 393453018216SPaolo Bonzini } 393553018216SPaolo Bonzini 393629ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = { 393729ee3247SAlexey Kardashevskiy .name = TYPE_SPAPR_MACHINE, 393829ee3247SAlexey Kardashevskiy .parent = TYPE_MACHINE, 39394aee7362SDavid Gibson .abstract = true, 39406ca1502eSAlexey Kardashevskiy .instance_size = sizeof(sPAPRMachineState), 3941bcb5ce08SDavid Gibson .instance_init = spapr_instance_init, 394287bbdd9cSDavid Gibson .instance_finalize = spapr_machine_finalizefn, 3943183930c0SDavid Gibson .class_size = sizeof(sPAPRMachineClass), 394429ee3247SAlexey Kardashevskiy .class_init = spapr_machine_class_init, 394571461b0fSAlexey Kardashevskiy .interfaces = (InterfaceInfo[]) { 394671461b0fSAlexey Kardashevskiy { TYPE_FW_PATH_PROVIDER }, 394734316482SAlexey Kardashevskiy { TYPE_NMI }, 3948c20d332aSBharata B Rao { TYPE_HOTPLUG_HANDLER }, 39491d1be34dSDavid Gibson { TYPE_PPC_VIRTUAL_HYPERVISOR }, 39507844e12bSCédric Le Goater { TYPE_XICS_FABRIC }, 39516449da45SCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 395271461b0fSAlexey Kardashevskiy { } 395371461b0fSAlexey Kardashevskiy }, 395429ee3247SAlexey Kardashevskiy }; 395529ee3247SAlexey Kardashevskiy 3956fccbc785SDavid Gibson #define DEFINE_SPAPR_MACHINE(suffix, verstr, latest) \ 39575013c547SDavid Gibson static void spapr_machine_##suffix##_class_init(ObjectClass *oc, \ 39585013c547SDavid Gibson void *data) \ 39595013c547SDavid Gibson { \ 39605013c547SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); \ 39615013c547SDavid Gibson spapr_machine_##suffix##_class_options(mc); \ 3962fccbc785SDavid Gibson if (latest) { \ 3963fccbc785SDavid Gibson mc->alias = "pseries"; \ 3964fccbc785SDavid Gibson mc->is_default = 1; \ 3965fccbc785SDavid Gibson } \ 39665013c547SDavid Gibson } \ 39675013c547SDavid Gibson static void spapr_machine_##suffix##_instance_init(Object *obj) \ 39685013c547SDavid Gibson { \ 39695013c547SDavid Gibson MachineState *machine = MACHINE(obj); \ 39705013c547SDavid Gibson spapr_machine_##suffix##_instance_options(machine); \ 39715013c547SDavid Gibson } \ 39725013c547SDavid Gibson static const TypeInfo spapr_machine_##suffix##_info = { \ 39735013c547SDavid Gibson .name = MACHINE_TYPE_NAME("pseries-" verstr), \ 39745013c547SDavid Gibson .parent = TYPE_SPAPR_MACHINE, \ 39755013c547SDavid Gibson .class_init = spapr_machine_##suffix##_class_init, \ 39765013c547SDavid Gibson .instance_init = spapr_machine_##suffix##_instance_init, \ 39775013c547SDavid Gibson }; \ 39785013c547SDavid Gibson static void spapr_machine_register_##suffix(void) \ 39795013c547SDavid Gibson { \ 39805013c547SDavid Gibson type_register(&spapr_machine_##suffix##_info); \ 39815013c547SDavid Gibson } \ 39820e6aac87SEduardo Habkost type_init(spapr_machine_register_##suffix) 39835013c547SDavid Gibson 39841c5f29bbSDavid Gibson /* 39858a4fd427SDavid Gibson * pseries-2.13 3986e2676b16SGreg Kurz */ 39878a4fd427SDavid Gibson static void spapr_machine_2_13_instance_options(MachineState *machine) 3988e2676b16SGreg Kurz { 3989e2676b16SGreg Kurz } 3990e2676b16SGreg Kurz 39918a4fd427SDavid Gibson static void spapr_machine_2_13_class_options(MachineClass *mc) 3992e2676b16SGreg Kurz { 3993e2676b16SGreg Kurz /* Defaults for the latest behaviour inherited from the base class */ 3994e2676b16SGreg Kurz } 3995e2676b16SGreg Kurz 39968a4fd427SDavid Gibson DEFINE_SPAPR_MACHINE(2_13, "2.13", true); 39978a4fd427SDavid Gibson 39988a4fd427SDavid Gibson /* 39998a4fd427SDavid Gibson * pseries-2.12 40008a4fd427SDavid Gibson */ 40018a4fd427SDavid Gibson #define SPAPR_COMPAT_2_12 \ 40028a4fd427SDavid Gibson HW_COMPAT_2_12 40038a4fd427SDavid Gibson 40048a4fd427SDavid Gibson static void spapr_machine_2_12_instance_options(MachineState *machine) 40058a4fd427SDavid Gibson { 40068a4fd427SDavid Gibson spapr_machine_2_13_instance_options(machine); 40078a4fd427SDavid Gibson } 40088a4fd427SDavid Gibson 40098a4fd427SDavid Gibson static void spapr_machine_2_12_class_options(MachineClass *mc) 40108a4fd427SDavid Gibson { 40118a4fd427SDavid Gibson spapr_machine_2_13_class_options(mc); 40128a4fd427SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_12); 40138a4fd427SDavid Gibson } 40148a4fd427SDavid Gibson 40158a4fd427SDavid Gibson DEFINE_SPAPR_MACHINE(2_12, "2.12", false); 40162b615412SDavid Gibson 4017813f3cf6SSuraj Jitindar Singh static void spapr_machine_2_12_sxxm_instance_options(MachineState *machine) 4018813f3cf6SSuraj Jitindar Singh { 4019813f3cf6SSuraj Jitindar Singh spapr_machine_2_12_instance_options(machine); 4020813f3cf6SSuraj Jitindar Singh } 4021813f3cf6SSuraj Jitindar Singh 4022813f3cf6SSuraj Jitindar Singh static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc) 4023813f3cf6SSuraj Jitindar Singh { 4024813f3cf6SSuraj Jitindar Singh sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4025813f3cf6SSuraj Jitindar Singh 4026813f3cf6SSuraj Jitindar Singh spapr_machine_2_12_class_options(mc); 4027813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND; 4028813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND; 4029813f3cf6SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_FIXED_CCD; 4030813f3cf6SSuraj Jitindar Singh } 4031813f3cf6SSuraj Jitindar Singh 4032813f3cf6SSuraj Jitindar Singh DEFINE_SPAPR_MACHINE(2_12_sxxm, "2.12-sxxm", false); 4033813f3cf6SSuraj Jitindar Singh 40342b615412SDavid Gibson /* 40352b615412SDavid Gibson * pseries-2.11 40362b615412SDavid Gibson */ 40372b615412SDavid Gibson #define SPAPR_COMPAT_2_11 \ 40382b615412SDavid Gibson HW_COMPAT_2_11 40392b615412SDavid Gibson 40402b615412SDavid Gibson static void spapr_machine_2_11_instance_options(MachineState *machine) 40412b615412SDavid Gibson { 40422b615412SDavid Gibson spapr_machine_2_12_instance_options(machine); 40432b615412SDavid Gibson } 40442b615412SDavid Gibson 40452b615412SDavid Gibson static void spapr_machine_2_11_class_options(MachineClass *mc) 40462b615412SDavid Gibson { 4047ee76a09fSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4048ee76a09fSDavid Gibson 40492b615412SDavid Gibson spapr_machine_2_12_class_options(mc); 40504e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON; 40512b615412SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_11); 40522b615412SDavid Gibson } 40532b615412SDavid Gibson 40542b615412SDavid Gibson DEFINE_SPAPR_MACHINE(2_11, "2.11", false); 4055e2676b16SGreg Kurz 4056e2676b16SGreg Kurz /* 40573fa14fbeSDavid Gibson * pseries-2.10 4058db800b21SDavid Gibson */ 4059e2676b16SGreg Kurz #define SPAPR_COMPAT_2_10 \ 40602b615412SDavid Gibson HW_COMPAT_2_10 4061e2676b16SGreg Kurz 40623fa14fbeSDavid Gibson static void spapr_machine_2_10_instance_options(MachineState *machine) 4063db800b21SDavid Gibson { 40642b615412SDavid Gibson spapr_machine_2_11_instance_options(machine); 4065db800b21SDavid Gibson } 4066db800b21SDavid Gibson 40673fa14fbeSDavid Gibson static void spapr_machine_2_10_class_options(MachineClass *mc) 4068db800b21SDavid Gibson { 4069e2676b16SGreg Kurz spapr_machine_2_11_class_options(mc); 4070e2676b16SGreg Kurz SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_10); 4071db800b21SDavid Gibson } 4072db800b21SDavid Gibson 4073e2676b16SGreg Kurz DEFINE_SPAPR_MACHINE(2_10, "2.10", false); 40743fa14fbeSDavid Gibson 40753fa14fbeSDavid Gibson /* 40763fa14fbeSDavid Gibson * pseries-2.9 40773fa14fbeSDavid Gibson */ 40783fa14fbeSDavid Gibson #define SPAPR_COMPAT_2_9 \ 4079d5fc133eSDavid Gibson HW_COMPAT_2_9 \ 4080d5fc133eSDavid Gibson { \ 4081d5fc133eSDavid Gibson .driver = TYPE_POWERPC_CPU, \ 4082d5fc133eSDavid Gibson .property = "pre-2.10-migration", \ 4083d5fc133eSDavid Gibson .value = "on", \ 4084d5fc133eSDavid Gibson }, \ 40853fa14fbeSDavid Gibson 40863fa14fbeSDavid Gibson static void spapr_machine_2_9_instance_options(MachineState *machine) 40873fa14fbeSDavid Gibson { 40883fa14fbeSDavid Gibson spapr_machine_2_10_instance_options(machine); 40893fa14fbeSDavid Gibson } 40903fa14fbeSDavid Gibson 40913fa14fbeSDavid Gibson static void spapr_machine_2_9_class_options(MachineClass *mc) 40923fa14fbeSDavid Gibson { 409346f7afa3SGreg Kurz sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 409446f7afa3SGreg Kurz 40953fa14fbeSDavid Gibson spapr_machine_2_10_class_options(mc); 40963fa14fbeSDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_9); 40973bfe5716SLaurent Vivier mc->numa_auto_assign_ram = numa_legacy_auto_assign_ram; 409846f7afa3SGreg Kurz smc->pre_2_10_has_unused_icps = true; 409952b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED; 41003fa14fbeSDavid Gibson } 41013fa14fbeSDavid Gibson 41023fa14fbeSDavid Gibson DEFINE_SPAPR_MACHINE(2_9, "2.9", false); 4103fa325e6cSDavid Gibson 4104fa325e6cSDavid Gibson /* 4105fa325e6cSDavid Gibson * pseries-2.8 4106fa325e6cSDavid Gibson */ 4107fa325e6cSDavid Gibson #define SPAPR_COMPAT_2_8 \ 410882516263SDavid Gibson HW_COMPAT_2_8 \ 410982516263SDavid Gibson { \ 411082516263SDavid Gibson .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \ 411182516263SDavid Gibson .property = "pcie-extended-configuration-space", \ 411282516263SDavid Gibson .value = "off", \ 411382516263SDavid Gibson }, 4114fa325e6cSDavid Gibson 4115fa325e6cSDavid Gibson static void spapr_machine_2_8_instance_options(MachineState *machine) 4116fa325e6cSDavid Gibson { 4117fa325e6cSDavid Gibson spapr_machine_2_9_instance_options(machine); 4118fa325e6cSDavid Gibson } 4119fa325e6cSDavid Gibson 4120fa325e6cSDavid Gibson static void spapr_machine_2_8_class_options(MachineClass *mc) 4121fa325e6cSDavid Gibson { 4122fa325e6cSDavid Gibson spapr_machine_2_9_class_options(mc); 4123fa325e6cSDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_8); 412455641213SLaurent Vivier mc->numa_mem_align_shift = 23; 4125fa325e6cSDavid Gibson } 4126fa325e6cSDavid Gibson 4127fa325e6cSDavid Gibson DEFINE_SPAPR_MACHINE(2_8, "2.8", false); 4128db800b21SDavid Gibson 4129db800b21SDavid Gibson /* 41301ea1eefcSBharata B Rao * pseries-2.7 41311ea1eefcSBharata B Rao */ 4132db800b21SDavid Gibson #define SPAPR_COMPAT_2_7 \ 4133db800b21SDavid Gibson HW_COMPAT_2_7 \ 4134357d1e3bSDavid Gibson { \ 4135357d1e3bSDavid Gibson .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \ 4136357d1e3bSDavid Gibson .property = "mem_win_size", \ 4137357d1e3bSDavid Gibson .value = stringify(SPAPR_PCI_2_7_MMIO_WIN_SIZE),\ 4138357d1e3bSDavid Gibson }, \ 4139357d1e3bSDavid Gibson { \ 4140357d1e3bSDavid Gibson .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \ 4141357d1e3bSDavid Gibson .property = "mem64_win_size", \ 4142357d1e3bSDavid Gibson .value = "0", \ 4143146c11f1SDavid Gibson }, \ 4144146c11f1SDavid Gibson { \ 4145146c11f1SDavid Gibson .driver = TYPE_POWERPC_CPU, \ 4146146c11f1SDavid Gibson .property = "pre-2.8-migration", \ 4147146c11f1SDavid Gibson .value = "on", \ 41485c4537bdSDavid Gibson }, \ 41495c4537bdSDavid Gibson { \ 41505c4537bdSDavid Gibson .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \ 41515c4537bdSDavid Gibson .property = "pre-2.8-migration", \ 41525c4537bdSDavid Gibson .value = "on", \ 4153357d1e3bSDavid Gibson }, 4154357d1e3bSDavid Gibson 4155357d1e3bSDavid Gibson static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index, 4156357d1e3bSDavid Gibson uint64_t *buid, hwaddr *pio, 4157357d1e3bSDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 4158357d1e3bSDavid Gibson unsigned n_dma, uint32_t *liobns, Error **errp) 4159357d1e3bSDavid Gibson { 4160357d1e3bSDavid Gibson /* Legacy PHB placement for pseries-2.7 and earlier machine types */ 4161357d1e3bSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 4162357d1e3bSDavid Gibson const hwaddr phb_spacing = 0x1000000000ULL; /* 64 GiB */ 4163357d1e3bSDavid Gibson const hwaddr mmio_offset = 0xa0000000; /* 2 GiB + 512 MiB */ 4164357d1e3bSDavid Gibson const hwaddr pio_offset = 0x80000000; /* 2 GiB */ 4165357d1e3bSDavid Gibson const uint32_t max_index = 255; 4166357d1e3bSDavid Gibson const hwaddr phb0_alignment = 0x10000000000ULL; /* 1 TiB */ 4167357d1e3bSDavid Gibson 4168357d1e3bSDavid Gibson uint64_t ram_top = MACHINE(spapr)->ram_size; 4169357d1e3bSDavid Gibson hwaddr phb0_base, phb_base; 4170357d1e3bSDavid Gibson int i; 4171357d1e3bSDavid Gibson 4172357d1e3bSDavid Gibson /* Do we have hotpluggable memory? */ 4173357d1e3bSDavid Gibson if (MACHINE(spapr)->maxram_size > ram_top) { 4174357d1e3bSDavid Gibson /* Can't just use maxram_size, because there may be an 4175357d1e3bSDavid Gibson * alignment gap between normal and hotpluggable memory 4176357d1e3bSDavid Gibson * regions */ 4177357d1e3bSDavid Gibson ram_top = spapr->hotplug_memory.base + 4178357d1e3bSDavid Gibson memory_region_size(&spapr->hotplug_memory.mr); 4179357d1e3bSDavid Gibson } 4180357d1e3bSDavid Gibson 4181357d1e3bSDavid Gibson phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment); 4182357d1e3bSDavid Gibson 4183357d1e3bSDavid Gibson if (index > max_index) { 4184357d1e3bSDavid Gibson error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", 4185357d1e3bSDavid Gibson max_index); 4186357d1e3bSDavid Gibson return; 4187357d1e3bSDavid Gibson } 4188357d1e3bSDavid Gibson 4189357d1e3bSDavid Gibson *buid = base_buid + index; 4190357d1e3bSDavid Gibson for (i = 0; i < n_dma; ++i) { 4191357d1e3bSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 4192357d1e3bSDavid Gibson } 4193357d1e3bSDavid Gibson 4194357d1e3bSDavid Gibson phb_base = phb0_base + index * phb_spacing; 4195357d1e3bSDavid Gibson *pio = phb_base + pio_offset; 4196357d1e3bSDavid Gibson *mmio32 = phb_base + mmio_offset; 4197357d1e3bSDavid Gibson /* 4198357d1e3bSDavid Gibson * We don't set the 64-bit MMIO window, relying on the PHB's 4199357d1e3bSDavid Gibson * fallback behaviour of automatically splitting a large "32-bit" 4200357d1e3bSDavid Gibson * window into contiguous 32-bit and 64-bit windows 4201357d1e3bSDavid Gibson */ 4202357d1e3bSDavid Gibson } 4203db800b21SDavid Gibson 42041ea1eefcSBharata B Rao static void spapr_machine_2_7_instance_options(MachineState *machine) 42051ea1eefcSBharata B Rao { 4206f6229214SMichael Roth sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 4207f6229214SMichael Roth 4208672de881SMichael Roth spapr_machine_2_8_instance_options(machine); 4209f6229214SMichael Roth spapr->use_hotplug_event_source = false; 42101ea1eefcSBharata B Rao } 42111ea1eefcSBharata B Rao 42121ea1eefcSBharata B Rao static void spapr_machine_2_7_class_options(MachineClass *mc) 42131ea1eefcSBharata B Rao { 42143daa4a9fSThomas Huth sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 42153daa4a9fSThomas Huth 4216db800b21SDavid Gibson spapr_machine_2_8_class_options(mc); 42172e9c10ebSIgor Mammedov mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power7_v2.3"); 4218db800b21SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_7); 4219357d1e3bSDavid Gibson smc->phb_placement = phb_placement_2_7; 42201ea1eefcSBharata B Rao } 42211ea1eefcSBharata B Rao 4222db800b21SDavid Gibson DEFINE_SPAPR_MACHINE(2_7, "2.7", false); 42231ea1eefcSBharata B Rao 42241ea1eefcSBharata B Rao /* 42254b23699cSDavid Gibson * pseries-2.6 42264b23699cSDavid Gibson */ 42271ea1eefcSBharata B Rao #define SPAPR_COMPAT_2_6 \ 4228ae4de14cSAlexey Kardashevskiy HW_COMPAT_2_6 \ 4229ae4de14cSAlexey Kardashevskiy { \ 4230ae4de14cSAlexey Kardashevskiy .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\ 4231ae4de14cSAlexey Kardashevskiy .property = "ddw",\ 4232ae4de14cSAlexey Kardashevskiy .value = stringify(off),\ 4233ae4de14cSAlexey Kardashevskiy }, 42341ea1eefcSBharata B Rao 42354b23699cSDavid Gibson static void spapr_machine_2_6_instance_options(MachineState *machine) 42364b23699cSDavid Gibson { 4237672de881SMichael Roth spapr_machine_2_7_instance_options(machine); 42384b23699cSDavid Gibson } 42394b23699cSDavid Gibson 42404b23699cSDavid Gibson static void spapr_machine_2_6_class_options(MachineClass *mc) 42414b23699cSDavid Gibson { 42421ea1eefcSBharata B Rao spapr_machine_2_7_class_options(mc); 4243c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = false; 42441ea1eefcSBharata B Rao SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_6); 42454b23699cSDavid Gibson } 42464b23699cSDavid Gibson 42471ea1eefcSBharata B Rao DEFINE_SPAPR_MACHINE(2_6, "2.6", false); 42484b23699cSDavid Gibson 42494b23699cSDavid Gibson /* 42501c5f29bbSDavid Gibson * pseries-2.5 42511c5f29bbSDavid Gibson */ 42524b23699cSDavid Gibson #define SPAPR_COMPAT_2_5 \ 425357c522f4SThomas Huth HW_COMPAT_2_5 \ 425457c522f4SThomas Huth { \ 425557c522f4SThomas Huth .driver = "spapr-vlan", \ 425657c522f4SThomas Huth .property = "use-rx-buffer-pools", \ 425757c522f4SThomas Huth .value = "off", \ 425857c522f4SThomas Huth }, 42594b23699cSDavid Gibson 42605013c547SDavid Gibson static void spapr_machine_2_5_instance_options(MachineState *machine) 42611c5f29bbSDavid Gibson { 4262672de881SMichael Roth spapr_machine_2_6_instance_options(machine); 42635013c547SDavid Gibson } 42645013c547SDavid Gibson 42655013c547SDavid Gibson static void spapr_machine_2_5_class_options(MachineClass *mc) 42665013c547SDavid Gibson { 426757040d45SThomas Huth sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 426857040d45SThomas Huth 42694b23699cSDavid Gibson spapr_machine_2_6_class_options(mc); 427057040d45SThomas Huth smc->use_ohci_by_default = true; 42714b23699cSDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_5); 42721c5f29bbSDavid Gibson } 42731c5f29bbSDavid Gibson 42744b23699cSDavid Gibson DEFINE_SPAPR_MACHINE(2_5, "2.5", false); 42751c5f29bbSDavid Gibson 42761c5f29bbSDavid Gibson /* 42771c5f29bbSDavid Gibson * pseries-2.4 42781c5f29bbSDavid Gibson */ 427980fd50f9SCornelia Huck #define SPAPR_COMPAT_2_4 \ 428080fd50f9SCornelia Huck HW_COMPAT_2_4 428180fd50f9SCornelia Huck 42825013c547SDavid Gibson static void spapr_machine_2_4_instance_options(MachineState *machine) 42831c5f29bbSDavid Gibson { 42845013c547SDavid Gibson spapr_machine_2_5_instance_options(machine); 42855013c547SDavid Gibson } 42861c5f29bbSDavid Gibson 42875013c547SDavid Gibson static void spapr_machine_2_4_class_options(MachineClass *mc) 42885013c547SDavid Gibson { 4289fc9f38c3SDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 4290fc9f38c3SDavid Gibson 4291fc9f38c3SDavid Gibson spapr_machine_2_5_class_options(mc); 4292fc9f38c3SDavid Gibson smc->dr_lmb_enabled = false; 4293f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_4); 42941c5f29bbSDavid Gibson } 42951c5f29bbSDavid Gibson 4296fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_4, "2.4", false); 42971c5f29bbSDavid Gibson 42981c5f29bbSDavid Gibson /* 42991c5f29bbSDavid Gibson * pseries-2.3 43001c5f29bbSDavid Gibson */ 430138ff32c6SEduardo Habkost #define SPAPR_COMPAT_2_3 \ 43027619c7b0SMichael Roth HW_COMPAT_2_3 \ 43037619c7b0SMichael Roth {\ 43047619c7b0SMichael Roth .driver = "spapr-pci-host-bridge",\ 43057619c7b0SMichael Roth .property = "dynamic-reconfiguration",\ 43067619c7b0SMichael Roth .value = "off",\ 43077619c7b0SMichael Roth }, 430838ff32c6SEduardo Habkost 43095013c547SDavid Gibson static void spapr_machine_2_3_instance_options(MachineState *machine) 43101c5f29bbSDavid Gibson { 43115013c547SDavid Gibson spapr_machine_2_4_instance_options(machine); 43121c5f29bbSDavid Gibson } 43131c5f29bbSDavid Gibson 43145013c547SDavid Gibson static void spapr_machine_2_3_class_options(MachineClass *mc) 43151c5f29bbSDavid Gibson { 4316fc9f38c3SDavid Gibson spapr_machine_2_4_class_options(mc); 4317f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_3); 43181c5f29bbSDavid Gibson } 4319fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_3, "2.3", false); 43201c5f29bbSDavid Gibson 43211c5f29bbSDavid Gibson /* 43221c5f29bbSDavid Gibson * pseries-2.2 43231c5f29bbSDavid Gibson */ 43241c5f29bbSDavid Gibson 4325b194df47SAlexey Kardashevskiy #define SPAPR_COMPAT_2_2 \ 43264dfd8eaaSEduardo Habkost HW_COMPAT_2_2 \ 4327b194df47SAlexey Kardashevskiy {\ 4328b194df47SAlexey Kardashevskiy .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\ 4329b194df47SAlexey Kardashevskiy .property = "mem_win_size",\ 4330b194df47SAlexey Kardashevskiy .value = "0x20000000",\ 4331dd754bafSEduardo Habkost }, 4332b194df47SAlexey Kardashevskiy 43335013c547SDavid Gibson static void spapr_machine_2_2_instance_options(MachineState *machine) 4334b0e966d0SJason Wang { 43355013c547SDavid Gibson spapr_machine_2_3_instance_options(machine); 4336cba0e779SGreg Kurz machine->suppress_vmdesc = true; 4337b0e966d0SJason Wang } 4338b0e966d0SJason Wang 43395013c547SDavid Gibson static void spapr_machine_2_2_class_options(MachineClass *mc) 4340b0e966d0SJason Wang { 4341fc9f38c3SDavid Gibson spapr_machine_2_3_class_options(mc); 4342f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_2); 43431c5f29bbSDavid Gibson } 4344fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_2, "2.2", false); 43451c5f29bbSDavid Gibson 43461c5f29bbSDavid Gibson /* 43471c5f29bbSDavid Gibson * pseries-2.1 43481c5f29bbSDavid Gibson */ 43491c5f29bbSDavid Gibson #define SPAPR_COMPAT_2_1 \ 43501c5f29bbSDavid Gibson HW_COMPAT_2_1 43511c5f29bbSDavid Gibson 43525013c547SDavid Gibson static void spapr_machine_2_1_instance_options(MachineState *machine) 43531c5f29bbSDavid Gibson { 43545013c547SDavid Gibson spapr_machine_2_2_instance_options(machine); 43551c5f29bbSDavid Gibson } 43561c5f29bbSDavid Gibson 43575013c547SDavid Gibson static void spapr_machine_2_1_class_options(MachineClass *mc) 4358b0e966d0SJason Wang { 4359fc9f38c3SDavid Gibson spapr_machine_2_2_class_options(mc); 4360f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_1); 43616026db45SAlexey Kardashevskiy } 4362fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_1, "2.1", false); 43636026db45SAlexey Kardashevskiy 436429ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void) 436529ee3247SAlexey Kardashevskiy { 436629ee3247SAlexey Kardashevskiy type_register_static(&spapr_machine_info); 436729ee3247SAlexey Kardashevskiy } 436829ee3247SAlexey Kardashevskiy 436929ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types) 4370