153018216SPaolo Bonzini /*
253018216SPaolo Bonzini * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
353018216SPaolo Bonzini *
453018216SPaolo Bonzini * Copyright (c) 2004-2007 Fabrice Bellard
553018216SPaolo Bonzini * Copyright (c) 2007 Jocelyn Mayer
653018216SPaolo Bonzini * Copyright (c) 2010 David Gibson, IBM Corporation.
753018216SPaolo Bonzini *
853018216SPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy
953018216SPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal
1053018216SPaolo Bonzini * in the Software without restriction, including without limitation the rights
1153018216SPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1253018216SPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is
1353018216SPaolo Bonzini * furnished to do so, subject to the following conditions:
1453018216SPaolo Bonzini *
1553018216SPaolo Bonzini * The above copyright notice and this permission notice shall be included in
1653018216SPaolo Bonzini * all copies or substantial portions of the Software.
1753018216SPaolo Bonzini *
1853018216SPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1953018216SPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2053018216SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2153018216SPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2253018216SPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2353018216SPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2453018216SPaolo Bonzini * THE SOFTWARE.
2553018216SPaolo Bonzini */
26a8d25326SMarkus Armbruster
270d75590dSPeter Maydell #include "qemu/osdep.h"
282c65db5eSPaolo Bonzini #include "qemu/datadir.h"
295df022cfSPeter Maydell #include "qemu/memalign.h"
30c4b07531SJason A. Donenfeld #include "qemu/guest-random.h"
31da34e65cSMarkus Armbruster #include "qapi/error.h"
32eb7f80fdSDaniel Henrique Barboza #include "qapi/qapi-events-machine.h"
334b08cd56SDaniel Henrique Barboza #include "qapi/qapi-events-qdev.h"
34fa98fbfcSSam Bobroff #include "qapi/visitor.h"
3553018216SPaolo Bonzini #include "sysemu/sysemu.h"
36b58c5c2dSMarkus Armbruster #include "sysemu/hostmem.h"
37e35704baSEduardo Habkost #include "sysemu/numa.h"
38beb0b62cSPhilippe Mathieu-Daudé #include "sysemu/tcg.h"
3923ff81bdSGreg Kurz #include "sysemu/qtest.h"
4071e8a915SMarkus Armbruster #include "sysemu/reset.h"
4154d31236SMarkus Armbruster #include "sysemu/runstate.h"
4203dd024fSPaolo Bonzini #include "qemu/log.h"
4371461b0fSAlexey Kardashevskiy #include "hw/fw-path-provider.h"
4453018216SPaolo Bonzini #include "elf.h"
4553018216SPaolo Bonzini #include "net/net.h"
46ad440b4aSAndrew Jones #include "sysemu/device_tree.h"
4753018216SPaolo Bonzini #include "sysemu/cpus.h"
48b3946626SVincent Palatin #include "sysemu/hw_accel.h"
4953018216SPaolo Bonzini #include "kvm_ppc.h"
50c4b63b7cSJuan Quintela #include "migration/misc.h"
51ca77ee28SMarkus Armbruster #include "migration/qemu-file-types.h"
5284a899deSJuan Quintela #include "migration/global_state.h"
53f2a8f0a6SJuan Quintela #include "migration/register.h"
542500fb42SAravinda Prasad #include "migration/blocker.h"
554be21d56SDavid Gibson #include "mmu-hash64.h"
56b4db5413SSuraj Jitindar Singh #include "mmu-book3s-v3.h"
577abd43baSSuraj Jitindar Singh #include "cpu-models.h"
582e5b09fdSMarkus Armbruster #include "hw/core/cpu.h"
5953018216SPaolo Bonzini
600d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h"
6153018216SPaolo Bonzini #include "hw/loader.h"
6253018216SPaolo Bonzini
637804c353SCédric Le Goater #include "hw/ppc/fdt.h"
640d09e41aSPaolo Bonzini #include "hw/ppc/spapr.h"
656b8a0537SNicholas Piggin #include "hw/ppc/spapr_nested.h"
660d09e41aSPaolo Bonzini #include "hw/ppc/spapr_vio.h"
6746d80a56SPhilippe Mathieu-Daudé #include "hw/ppc/vof.h"
68a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
690d09e41aSPaolo Bonzini #include "hw/pci-host/spapr.h"
7053018216SPaolo Bonzini #include "hw/pci/msi.h"
7153018216SPaolo Bonzini
7253018216SPaolo Bonzini #include "hw/pci/pci.h"
7371461b0fSAlexey Kardashevskiy #include "hw/scsi/scsi.h"
7471461b0fSAlexey Kardashevskiy #include "hw/virtio/virtio-scsi.h"
75c4e13492SFelipe Franciosi #include "hw/virtio/vhost-scsi-common.h"
7653018216SPaolo Bonzini
772309832aSDavid Gibson #include "exec/ram_addr.h"
7800a238b1SXiaoyao Li #include "exec/confidential-guest-support.h"
7953018216SPaolo Bonzini #include "hw/usb.h"
8053018216SPaolo Bonzini #include "qemu/config-file.h"
81135a129aSAneesh Kumar K.V #include "qemu/error-report.h"
822a6593cbSAlexey Kardashevskiy #include "trace.h"
8334316482SAlexey Kardashevskiy #include "hw/nmi.h"
846449da45SCédric Le Goater #include "hw/intc/intc.h"
8553018216SPaolo Bonzini
8694a94e4cSBharata B Rao #include "hw/ppc/spapr_cpu_core.h"
872cc0e2e8SDavid Hildenbrand #include "hw/mem/memory-device.h"
880fb6bd07SMichael Roth #include "hw/ppc/spapr_tpm_proxy.h"
89ee3a71e3SShivaprasad G Bhat #include "hw/ppc/spapr_nvdimm.h"
901eee9950SDaniel Henrique Barboza #include "hw/ppc/spapr_numa.h"
9168a27b20SMichael S. Tsirkin
9253018216SPaolo Bonzini #include <libfdt.h>
9353018216SPaolo Bonzini
9453018216SPaolo Bonzini /* SLOF memory layout:
9553018216SPaolo Bonzini *
9653018216SPaolo Bonzini * SLOF raw image loaded at 0, copies its romfs right below the flat
9753018216SPaolo Bonzini * device-tree, then position SLOF itself 31M below that
9853018216SPaolo Bonzini *
9953018216SPaolo Bonzini * So we set FW_OVERHEAD to 40MB which should account for all of that
10053018216SPaolo Bonzini * and more
10153018216SPaolo Bonzini *
10253018216SPaolo Bonzini * We load our kernel at 4M, leaving space for SLOF initial image
10353018216SPaolo Bonzini */
1044b98e72dSAlexey Kardashevskiy #define FDT_MAX_ADDR 0x80000000 /* FDT must stay below that */
10553018216SPaolo Bonzini #define FW_MAX_SIZE 0x400000
10653018216SPaolo Bonzini #define FW_FILE_NAME "slof.bin"
107fc8c745dSAlexey Kardashevskiy #define FW_FILE_NAME_VOF "vof.bin"
10853018216SPaolo Bonzini #define FW_OVERHEAD 0x2800000
10953018216SPaolo Bonzini #define KERNEL_LOAD_ADDR FW_MAX_SIZE
11053018216SPaolo Bonzini
1119943266eSDavid Gibson #define MIN_RMA_SLOF (128 * MiB)
11253018216SPaolo Bonzini
1135c7adcf4SGreg Kurz #define PHANDLE_INTC 0x00001111
11453018216SPaolo Bonzini
1155d0fb150SGreg Kurz /* These two functions implement the VCPU id numbering: one to compute them
1165d0fb150SGreg Kurz * all and one to identify thread 0 of a VCORE. Any change to the first one
1175d0fb150SGreg Kurz * is likely to have an impact on the second one, so let's keep them close.
1185d0fb150SGreg Kurz */
spapr_vcpu_id(SpaprMachineState * spapr,int cpu_index)119ce2918cbSDavid Gibson static int spapr_vcpu_id(SpaprMachineState *spapr, int cpu_index)
1205d0fb150SGreg Kurz {
121fe6b6346SLike Xu MachineState *ms = MACHINE(spapr);
122fe6b6346SLike Xu unsigned int smp_threads = ms->smp.threads;
123fe6b6346SLike Xu
1241a5008fcSGreg Kurz assert(spapr->vsmt);
1255d0fb150SGreg Kurz return
1265d0fb150SGreg Kurz (cpu_index / smp_threads) * spapr->vsmt + cpu_index % smp_threads;
1275d0fb150SGreg Kurz }
spapr_is_thread0_in_vcore(SpaprMachineState * spapr,PowerPCCPU * cpu)128ce2918cbSDavid Gibson static bool spapr_is_thread0_in_vcore(SpaprMachineState *spapr,
1295d0fb150SGreg Kurz PowerPCCPU *cpu)
1305d0fb150SGreg Kurz {
1311a5008fcSGreg Kurz assert(spapr->vsmt);
1325d0fb150SGreg Kurz return spapr_get_vcpu_id(cpu) % spapr->vsmt == 0;
1335d0fb150SGreg Kurz }
1345d0fb150SGreg Kurz
spapr_max_server_number(SpaprMachineState * spapr)135ce2918cbSDavid Gibson int spapr_max_server_number(SpaprMachineState *spapr)
13646f7afa3SGreg Kurz {
137fe6b6346SLike Xu MachineState *ms = MACHINE(spapr);
138fe6b6346SLike Xu
1391a5008fcSGreg Kurz assert(spapr->vsmt);
140fe6b6346SLike Xu return DIV_ROUND_UP(ms->smp.max_cpus * spapr->vsmt, ms->smp.threads);
14146f7afa3SGreg Kurz }
14246f7afa3SGreg Kurz
spapr_fixup_cpu_smt_dt(void * fdt,int offset,PowerPCCPU * cpu,int smt_threads)143833d4668SAlexey Kardashevskiy static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu,
144833d4668SAlexey Kardashevskiy int smt_threads)
145833d4668SAlexey Kardashevskiy {
146833d4668SAlexey Kardashevskiy int i, ret = 0;
147a580fdcdSPhilippe Mathieu-Daudé g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads);
148a580fdcdSPhilippe Mathieu-Daudé g_autofree uint32_t *gservers_prop = g_new(uint32_t, smt_threads * 2);
14914bb4486SGreg Kurz int index = spapr_get_vcpu_id(cpu);
150833d4668SAlexey Kardashevskiy
151d6e166c0SDavid Gibson if (cpu->compat_pvr) {
152d6e166c0SDavid Gibson ret = fdt_setprop_cell(fdt, offset, "cpu-version", cpu->compat_pvr);
1536d9412eaSAlexey Kardashevskiy if (ret < 0) {
1546d9412eaSAlexey Kardashevskiy return ret;
1556d9412eaSAlexey Kardashevskiy }
1566d9412eaSAlexey Kardashevskiy }
1576d9412eaSAlexey Kardashevskiy
158833d4668SAlexey Kardashevskiy /* Build interrupt servers and gservers properties */
159833d4668SAlexey Kardashevskiy for (i = 0; i < smt_threads; i++) {
160833d4668SAlexey Kardashevskiy servers_prop[i] = cpu_to_be32(index + i);
161833d4668SAlexey Kardashevskiy /* Hack, direct the group queues back to cpu 0 */
162833d4668SAlexey Kardashevskiy gservers_prop[i*2] = cpu_to_be32(index + i);
163833d4668SAlexey Kardashevskiy gservers_prop[i*2 + 1] = 0;
164833d4668SAlexey Kardashevskiy }
165833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
166a580fdcdSPhilippe Mathieu-Daudé servers_prop, sizeof(*servers_prop) * smt_threads);
167833d4668SAlexey Kardashevskiy if (ret < 0) {
168833d4668SAlexey Kardashevskiy return ret;
169833d4668SAlexey Kardashevskiy }
170833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-gserver#s",
171a580fdcdSPhilippe Mathieu-Daudé gservers_prop, sizeof(*gservers_prop) * smt_threads * 2);
172833d4668SAlexey Kardashevskiy
173833d4668SAlexey Kardashevskiy return ret;
174833d4668SAlexey Kardashevskiy }
175833d4668SAlexey Kardashevskiy
spapr_dt_pa_features(SpaprMachineState * spapr,PowerPCCPU * cpu,void * fdt,int offset)17691335a5eSDavid Gibson static void spapr_dt_pa_features(SpaprMachineState *spapr,
177ee76a09fSDavid Gibson PowerPCCPU *cpu,
178daa36379SDavid Gibson void *fdt, int offset)
17986d5771aSSam Bobroff {
180a5a57786SNicholas Piggin /*
181a5a57786SNicholas Piggin * SSO (SAO) ordering is supported on KVM and thread=single hosts,
182a5a57786SNicholas Piggin * but not MTTCG, so disable it. To advertise it, a cap would have
183a5a57786SNicholas Piggin * to be added, or support implemented for MTTCG.
18417aa684fSNicholas Piggin *
18517aa684fSNicholas Piggin * Copy/paste is not supported by TCG, so it is not advertised. KVM
18617aa684fSNicholas Piggin * can execute them but it has no accelerator drivers which are usable,
18717aa684fSNicholas Piggin * so there isn't much need for it anyway.
188a5a57786SNicholas Piggin */
189a5a57786SNicholas Piggin
19024a9d20cSNicholas Piggin /* These should be kept in sync with pnv */
19186d5771aSSam Bobroff uint8_t pa_features_206[] = { 6, 0,
192a5a57786SNicholas Piggin 0xf6, 0x1f, 0xc7, 0x00, 0x00, 0xc0 };
19386d5771aSSam Bobroff uint8_t pa_features_207[] = { 24, 0,
194a5a57786SNicholas Piggin 0xf6, 0x1f, 0xc7, 0xc0, 0x00, 0xf0,
19586d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
19686d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
19786d5771aSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 };
1989fb4541fSSam Bobroff uint8_t pa_features_300[] = { 66, 0,
1999fb4541fSSam Bobroff /* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */
200a5a57786SNicholas Piggin /* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, 5: LE|CFAR|EB|LSQ */
201a5a57786SNicholas Piggin 0xf6, 0x1f, 0xc7, 0xc0, 0x00, 0xf0, /* 0 - 5 */
2029fb4541fSSam Bobroff /* 6: DS207 */
20386d5771aSSam Bobroff 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */
2049fb4541fSSam Bobroff /* 16: Vector */
20586d5771aSSam Bobroff 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */
2068b0e3fb8SNicholas Piggin /* 18: Vec. Scalar, 20: Vec. XOR */
2079bf502feSDavid Gibson 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */
2089fb4541fSSam Bobroff /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */
2099fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */
2108b0e3fb8SNicholas Piggin /* 32: LE atomic, 34: EBB + ext EBB */
2118b0e3fb8SNicholas Piggin 0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */
2128b0e3fb8SNicholas Piggin /* 40: Radix MMU */
2138b0e3fb8SNicholas Piggin 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 36 - 41 */
2149fb4541fSSam Bobroff /* 42: PM, 44: PC RA, 46: SC vec'd */
2159fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */
2169fb4541fSSam Bobroff /* 48: SIMD, 50: QP BFP, 52: String */
2179fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */
2189fb4541fSSam Bobroff /* 54: DecFP, 56: DecI, 58: SHA */
2199fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */
2209fb4541fSSam Bobroff /* 60: NM atomic, 62: RNG */
2219fb4541fSSam Bobroff 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */
2229fb4541fSSam Bobroff };
223d83d350cSBenjamin Gray /* 3.1 removes SAO, HTM support */
224d83d350cSBenjamin Gray uint8_t pa_features_31[] = { 74, 0,
225d83d350cSBenjamin Gray /* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */
226d83d350cSBenjamin Gray /* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, 5: LE|CFAR|EB|LSQ */
227d83d350cSBenjamin Gray 0xf6, 0x1f, 0xc7, 0xc0, 0x00, 0xf0, /* 0 - 5 */
228d83d350cSBenjamin Gray /* 6: DS207 */
229d83d350cSBenjamin Gray 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */
230d83d350cSBenjamin Gray /* 16: Vector */
231d83d350cSBenjamin Gray 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */
232d83d350cSBenjamin Gray /* 18: Vec. Scalar, 20: Vec. XOR */
233d83d350cSBenjamin Gray 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */
234d83d350cSBenjamin Gray /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */
235d83d350cSBenjamin Gray 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */
236d83d350cSBenjamin Gray /* 32: LE atomic, 34: EBB + ext EBB */
237d83d350cSBenjamin Gray 0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */
238d83d350cSBenjamin Gray /* 40: Radix MMU */
239d83d350cSBenjamin Gray 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 36 - 41 */
240d83d350cSBenjamin Gray /* 42: PM, 44: PC RA, 46: SC vec'd */
241d83d350cSBenjamin Gray 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */
242d83d350cSBenjamin Gray /* 48: SIMD, 50: QP BFP, 52: String */
243d83d350cSBenjamin Gray 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */
244d83d350cSBenjamin Gray /* 54: DecFP, 56: DecI, 58: SHA */
245d83d350cSBenjamin Gray 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */
246d83d350cSBenjamin Gray /* 60: NM atomic, 62: RNG */
247d83d350cSBenjamin Gray 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */
248d83d350cSBenjamin Gray /* 68: DEXCR[SBHE|IBRTPDUS|SRAPD|NPHIE|PHIE] */
249d83d350cSBenjamin Gray 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, /* 66 - 71 */
250d83d350cSBenjamin Gray /* 72: [P]HASHST/[P]HASHCHK */
251d83d350cSBenjamin Gray 0x80, 0x00, /* 72 - 73 */
252d83d350cSBenjamin Gray };
2537abd43baSSuraj Jitindar Singh uint8_t *pa_features = NULL;
25486d5771aSSam Bobroff size_t pa_size;
25586d5771aSSam Bobroff
2567abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06, 0, cpu->compat_pvr)) {
25786d5771aSSam Bobroff pa_features = pa_features_206;
25886d5771aSSam Bobroff pa_size = sizeof(pa_features_206);
2597abd43baSSuraj Jitindar Singh }
2607abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07, 0, cpu->compat_pvr)) {
26186d5771aSSam Bobroff pa_features = pa_features_207;
26286d5771aSSam Bobroff pa_size = sizeof(pa_features_207);
2637abd43baSSuraj Jitindar Singh }
2647abd43baSSuraj Jitindar Singh if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0, cpu->compat_pvr)) {
26586d5771aSSam Bobroff pa_features = pa_features_300;
26686d5771aSSam Bobroff pa_size = sizeof(pa_features_300);
2677abd43baSSuraj Jitindar Singh }
268d83d350cSBenjamin Gray if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_10, 0, cpu->compat_pvr)) {
269d83d350cSBenjamin Gray pa_features = pa_features_31;
270d83d350cSBenjamin Gray pa_size = sizeof(pa_features_31);
271d83d350cSBenjamin Gray }
2727abd43baSSuraj Jitindar Singh if (!pa_features) {
27386d5771aSSam Bobroff return;
27486d5771aSSam Bobroff }
27586d5771aSSam Bobroff
27626cd35b8SDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_CI_LARGEPAGE)) {
27786d5771aSSam Bobroff /*
27886d5771aSSam Bobroff * Note: we keep CI large pages off by default because a 64K capable
27986d5771aSSam Bobroff * guest provisioned with large pages might otherwise try to map a qemu
28086d5771aSSam Bobroff * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages
28186d5771aSSam Bobroff * even if that qemu runs on a 4k host.
28286d5771aSSam Bobroff * We dd this bit back here if we are confident this is not an issue
28386d5771aSSam Bobroff */
28486d5771aSSam Bobroff pa_features[3] |= 0x20;
28586d5771aSSam Bobroff }
2864e5fe368SSuraj Jitindar Singh if ((spapr_get_cap(spapr, SPAPR_CAP_HTM) != 0) && pa_size > 24) {
28786d5771aSSam Bobroff pa_features[24] |= 0x80; /* Transactional memory support */
28886d5771aSSam Bobroff }
289daa36379SDavid Gibson if (spapr->cas_pre_isa3_guest && pa_size > 40) {
290e957f6a9SSam Bobroff /* Workaround for broken kernels that attempt (guest) radix
291e957f6a9SSam Bobroff * mode when they can't handle it, if they see the radix bit set
292e957f6a9SSam Bobroff * in pa-features. So hide it from them. */
293e957f6a9SSam Bobroff pa_features[40 + 2] &= ~0x80; /* Radix MMU */
294e957f6a9SSam Bobroff }
29586d5771aSSam Bobroff
29686d5771aSSam Bobroff _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size)));
29786d5771aSSam Bobroff }
29886d5771aSSam Bobroff
spapr_dt_pi_features(SpaprMachineState * spapr,PowerPCCPU * cpu,void * fdt,int offset)29995912ce1SNicholas Piggin static void spapr_dt_pi_features(SpaprMachineState *spapr,
30095912ce1SNicholas Piggin PowerPCCPU *cpu,
30195912ce1SNicholas Piggin void *fdt, int offset)
30295912ce1SNicholas Piggin {
30395912ce1SNicholas Piggin uint8_t pi_features[] = { 1, 0,
30495912ce1SNicholas Piggin 0x00 };
30595912ce1SNicholas Piggin
30695912ce1SNicholas Piggin if (kvm_enabled() && ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00,
30795912ce1SNicholas Piggin 0, cpu->compat_pvr)) {
30895912ce1SNicholas Piggin /*
30995912ce1SNicholas Piggin * POWER9 and later CPUs with KVM run in LPAR-per-thread mode where
31095912ce1SNicholas Piggin * all threads are essentially independent CPUs, and msgsndp does not
31195912ce1SNicholas Piggin * work (because it is physically-addressed) and therefore is
31295912ce1SNicholas Piggin * emulated by KVM, so disable it here to ensure XIVE will be used.
31395912ce1SNicholas Piggin * This is both KVM and CPU implementation-specific behaviour so a KVM
31495912ce1SNicholas Piggin * cap would be cleanest, but for now this works. If KVM ever permits
31595912ce1SNicholas Piggin * native msgsndp execution by guests, a cap could be added at that
31695912ce1SNicholas Piggin * time.
31795912ce1SNicholas Piggin */
31895912ce1SNicholas Piggin pi_features[2] |= 0x08; /* 4: No msgsndp */
31995912ce1SNicholas Piggin }
32095912ce1SNicholas Piggin
32195912ce1SNicholas Piggin _FDT((fdt_setprop(fdt, offset, "ibm,pi-features", pi_features,
32295912ce1SNicholas Piggin sizeof(pi_features))));
32395912ce1SNicholas Piggin }
32495912ce1SNicholas Piggin
spapr_node0_size(MachineState * machine)325c86c1affSDaniel Henrique Barboza static hwaddr spapr_node0_size(MachineState *machine)
326b082d65aSAlexey Kardashevskiy {
327aa570207STao Xu if (machine->numa_state->num_nodes) {
328b082d65aSAlexey Kardashevskiy int i;
329aa570207STao Xu for (i = 0; i < machine->numa_state->num_nodes; ++i) {
3307e721e7bSTao Xu if (machine->numa_state->nodes[i].node_mem) {
3317e721e7bSTao Xu return MIN(pow2floor(machine->numa_state->nodes[i].node_mem),
332fb164994SDavid Gibson machine->ram_size);
333b082d65aSAlexey Kardashevskiy }
334b082d65aSAlexey Kardashevskiy }
335b082d65aSAlexey Kardashevskiy }
336fb164994SDavid Gibson return machine->ram_size;
337b082d65aSAlexey Kardashevskiy }
338b082d65aSAlexey Kardashevskiy
add_str(GString * s,const gchar * s1)339a1d59c0fSAlexey Kardashevskiy static void add_str(GString *s, const gchar *s1)
340a1d59c0fSAlexey Kardashevskiy {
341a1d59c0fSAlexey Kardashevskiy g_string_append_len(s, s1, strlen(s1) + 1);
342a1d59c0fSAlexey Kardashevskiy }
34353018216SPaolo Bonzini
spapr_dt_memory_node(SpaprMachineState * spapr,void * fdt,int nodeid,hwaddr start,hwaddr size)344f1aa45ffSDaniel Henrique Barboza static int spapr_dt_memory_node(SpaprMachineState *spapr, void *fdt, int nodeid,
345f1aa45ffSDaniel Henrique Barboza hwaddr start, hwaddr size)
34626a8c353SAlexey Kardashevskiy {
34726a8c353SAlexey Kardashevskiy char mem_name[32];
34826a8c353SAlexey Kardashevskiy uint64_t mem_reg_property[2];
34926a8c353SAlexey Kardashevskiy int off;
35026a8c353SAlexey Kardashevskiy
35126a8c353SAlexey Kardashevskiy mem_reg_property[0] = cpu_to_be64(start);
35226a8c353SAlexey Kardashevskiy mem_reg_property[1] = cpu_to_be64(size);
35326a8c353SAlexey Kardashevskiy
3543a17e38fSAlexey Kardashevskiy sprintf(mem_name, "memory@%" HWADDR_PRIx, start);
35526a8c353SAlexey Kardashevskiy off = fdt_add_subnode(fdt, 0, mem_name);
35626a8c353SAlexey Kardashevskiy _FDT(off);
35726a8c353SAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
35826a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
35926a8c353SAlexey Kardashevskiy sizeof(mem_reg_property))));
360f1aa45ffSDaniel Henrique Barboza spapr_numa_write_associativity_dt(spapr, fdt, off, nodeid);
36103d196b7SBharata B Rao return off;
36226a8c353SAlexey Kardashevskiy }
36326a8c353SAlexey Kardashevskiy
spapr_pc_dimm_node(MemoryDeviceInfoList * list,ram_addr_t addr)364f47bd1c8SIgor Mammedov static uint32_t spapr_pc_dimm_node(MemoryDeviceInfoList *list, ram_addr_t addr)
365f47bd1c8SIgor Mammedov {
366f47bd1c8SIgor Mammedov MemoryDeviceInfoList *info;
367f47bd1c8SIgor Mammedov
368f47bd1c8SIgor Mammedov for (info = list; info; info = info->next) {
369f47bd1c8SIgor Mammedov MemoryDeviceInfo *value = info->value;
370f47bd1c8SIgor Mammedov
371f47bd1c8SIgor Mammedov if (value && value->type == MEMORY_DEVICE_INFO_KIND_DIMM) {
372f47bd1c8SIgor Mammedov PCDIMMDeviceInfo *pcdimm_info = value->u.dimm.data;
373f47bd1c8SIgor Mammedov
374ccc2cef8SDavid Gibson if (addr >= pcdimm_info->addr &&
375f47bd1c8SIgor Mammedov addr < (pcdimm_info->addr + pcdimm_info->size)) {
376f47bd1c8SIgor Mammedov return pcdimm_info->node;
377f47bd1c8SIgor Mammedov }
378f47bd1c8SIgor Mammedov }
379f47bd1c8SIgor Mammedov }
380f47bd1c8SIgor Mammedov
381f47bd1c8SIgor Mammedov return -1;
382f47bd1c8SIgor Mammedov }
383f47bd1c8SIgor Mammedov
384a324d6f1SBharata B Rao struct sPAPRDrconfCellV2 {
385a324d6f1SBharata B Rao uint32_t seq_lmbs;
386a324d6f1SBharata B Rao uint64_t base_addr;
387a324d6f1SBharata B Rao uint32_t drc_index;
388a324d6f1SBharata B Rao uint32_t aa_index;
389a324d6f1SBharata B Rao uint32_t flags;
390a324d6f1SBharata B Rao } QEMU_PACKED;
391a324d6f1SBharata B Rao
392a324d6f1SBharata B Rao typedef struct DrconfCellQueue {
393a324d6f1SBharata B Rao struct sPAPRDrconfCellV2 cell;
394a324d6f1SBharata B Rao QSIMPLEQ_ENTRY(DrconfCellQueue) entry;
395a324d6f1SBharata B Rao } DrconfCellQueue;
396a324d6f1SBharata B Rao
397a324d6f1SBharata B Rao static DrconfCellQueue *
spapr_get_drconf_cell(uint32_t seq_lmbs,uint64_t base_addr,uint32_t drc_index,uint32_t aa_index,uint32_t flags)398a324d6f1SBharata B Rao spapr_get_drconf_cell(uint32_t seq_lmbs, uint64_t base_addr,
399a324d6f1SBharata B Rao uint32_t drc_index, uint32_t aa_index,
400a324d6f1SBharata B Rao uint32_t flags)
40103d196b7SBharata B Rao {
402a324d6f1SBharata B Rao DrconfCellQueue *elem;
403a324d6f1SBharata B Rao
404a324d6f1SBharata B Rao elem = g_malloc0(sizeof(*elem));
405a324d6f1SBharata B Rao elem->cell.seq_lmbs = cpu_to_be32(seq_lmbs);
406a324d6f1SBharata B Rao elem->cell.base_addr = cpu_to_be64(base_addr);
407a324d6f1SBharata B Rao elem->cell.drc_index = cpu_to_be32(drc_index);
408a324d6f1SBharata B Rao elem->cell.aa_index = cpu_to_be32(aa_index);
409a324d6f1SBharata B Rao elem->cell.flags = cpu_to_be32(flags);
410a324d6f1SBharata B Rao
411a324d6f1SBharata B Rao return elem;
412a324d6f1SBharata B Rao }
413a324d6f1SBharata B Rao
spapr_dt_dynamic_memory_v2(SpaprMachineState * spapr,void * fdt,int offset,MemoryDeviceInfoList * dimms)41491335a5eSDavid Gibson static int spapr_dt_dynamic_memory_v2(SpaprMachineState *spapr, void *fdt,
415a324d6f1SBharata B Rao int offset, MemoryDeviceInfoList *dimms)
4162a6593cbSAlexey Kardashevskiy {
4172a6593cbSAlexey Kardashevskiy MachineState *machine = MACHINE(spapr);
418cc941111SFabiano Rosas uint8_t *int_buf, *cur_index;
419a324d6f1SBharata B Rao int ret;
42003d196b7SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
421a324d6f1SBharata B Rao uint64_t addr, cur_addr, size;
422b0c14ec4SDavid Hildenbrand uint32_t nr_boot_lmbs = (machine->device_memory->base / lmb_size);
423b0c14ec4SDavid Hildenbrand uint64_t mem_end = machine->device_memory->base +
424b0c14ec4SDavid Hildenbrand memory_region_size(&machine->device_memory->mr);
425cc941111SFabiano Rosas uint32_t node, buf_len, nr_entries = 0;
426ce2918cbSDavid Gibson SpaprDrc *drc;
427a324d6f1SBharata B Rao DrconfCellQueue *elem, *next;
428a324d6f1SBharata B Rao MemoryDeviceInfoList *info;
429a324d6f1SBharata B Rao QSIMPLEQ_HEAD(, DrconfCellQueue) drconf_queue
430a324d6f1SBharata B Rao = QSIMPLEQ_HEAD_INITIALIZER(drconf_queue);
431a324d6f1SBharata B Rao
432a324d6f1SBharata B Rao /* Entry to cover RAM and the gap area */
433a324d6f1SBharata B Rao elem = spapr_get_drconf_cell(nr_boot_lmbs, 0, 0, -1,
434a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_RESERVED |
435a324d6f1SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID);
436a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry);
437a324d6f1SBharata B Rao nr_entries++;
438a324d6f1SBharata B Rao
439b0c14ec4SDavid Hildenbrand cur_addr = machine->device_memory->base;
440a324d6f1SBharata B Rao for (info = dimms; info; info = info->next) {
441a324d6f1SBharata B Rao PCDIMMDeviceInfo *di = info->value->u.dimm.data;
442a324d6f1SBharata B Rao
443a324d6f1SBharata B Rao addr = di->addr;
444a324d6f1SBharata B Rao size = di->size;
445a324d6f1SBharata B Rao node = di->node;
446a324d6f1SBharata B Rao
447ee3a71e3SShivaprasad G Bhat /*
448ee3a71e3SShivaprasad G Bhat * The NVDIMM area is hotpluggable after the NVDIMM is unplugged. The
449ee3a71e3SShivaprasad G Bhat * area is marked hotpluggable in the next iteration for the bigger
450ee3a71e3SShivaprasad G Bhat * chunk including the NVDIMM occupied area.
451ee3a71e3SShivaprasad G Bhat */
452ee3a71e3SShivaprasad G Bhat if (info->value->type == MEMORY_DEVICE_INFO_KIND_NVDIMM)
453ee3a71e3SShivaprasad G Bhat continue;
454ee3a71e3SShivaprasad G Bhat
455a324d6f1SBharata B Rao /* Entry for hot-pluggable area */
456a324d6f1SBharata B Rao if (cur_addr < addr) {
457a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size);
458a324d6f1SBharata B Rao g_assert(drc);
459a324d6f1SBharata B Rao elem = spapr_get_drconf_cell((addr - cur_addr) / lmb_size,
460a324d6f1SBharata B Rao cur_addr, spapr_drc_index(drc), -1, 0);
461a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry);
462a324d6f1SBharata B Rao nr_entries++;
463a324d6f1SBharata B Rao }
464a324d6f1SBharata B Rao
465a324d6f1SBharata B Rao /* Entry for DIMM */
466a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr / lmb_size);
467a324d6f1SBharata B Rao g_assert(drc);
468a324d6f1SBharata B Rao elem = spapr_get_drconf_cell(size / lmb_size, addr,
469a324d6f1SBharata B Rao spapr_drc_index(drc), node,
4700911a60cSLeonardo Bras (SPAPR_LMB_FLAGS_ASSIGNED |
4710911a60cSLeonardo Bras SPAPR_LMB_FLAGS_HOTREMOVABLE));
472a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry);
473a324d6f1SBharata B Rao nr_entries++;
474a324d6f1SBharata B Rao cur_addr = addr + size;
475a324d6f1SBharata B Rao }
476a324d6f1SBharata B Rao
477a324d6f1SBharata B Rao /* Entry for remaining hotpluggable area */
478a324d6f1SBharata B Rao if (cur_addr < mem_end) {
479a324d6f1SBharata B Rao drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size);
480a324d6f1SBharata B Rao g_assert(drc);
481a324d6f1SBharata B Rao elem = spapr_get_drconf_cell((mem_end - cur_addr) / lmb_size,
482a324d6f1SBharata B Rao cur_addr, spapr_drc_index(drc), -1, 0);
483a324d6f1SBharata B Rao QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry);
484a324d6f1SBharata B Rao nr_entries++;
485a324d6f1SBharata B Rao }
486a324d6f1SBharata B Rao
487a324d6f1SBharata B Rao buf_len = nr_entries * sizeof(struct sPAPRDrconfCellV2) + sizeof(uint32_t);
488a324d6f1SBharata B Rao int_buf = cur_index = g_malloc0(buf_len);
489a324d6f1SBharata B Rao *(uint32_t *)int_buf = cpu_to_be32(nr_entries);
490a324d6f1SBharata B Rao cur_index += sizeof(nr_entries);
491a324d6f1SBharata B Rao
492a324d6f1SBharata B Rao QSIMPLEQ_FOREACH_SAFE(elem, &drconf_queue, entry, next) {
493a324d6f1SBharata B Rao memcpy(cur_index, &elem->cell, sizeof(elem->cell));
494a324d6f1SBharata B Rao cur_index += sizeof(elem->cell);
495a324d6f1SBharata B Rao QSIMPLEQ_REMOVE(&drconf_queue, elem, DrconfCellQueue, entry);
496a324d6f1SBharata B Rao g_free(elem);
497a324d6f1SBharata B Rao }
498a324d6f1SBharata B Rao
499a324d6f1SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory-v2", int_buf, buf_len);
500a324d6f1SBharata B Rao g_free(int_buf);
501a324d6f1SBharata B Rao if (ret < 0) {
502a324d6f1SBharata B Rao return -1;
503a324d6f1SBharata B Rao }
504a324d6f1SBharata B Rao return 0;
505a324d6f1SBharata B Rao }
506a324d6f1SBharata B Rao
spapr_dt_dynamic_memory(SpaprMachineState * spapr,void * fdt,int offset,MemoryDeviceInfoList * dimms)50791335a5eSDavid Gibson static int spapr_dt_dynamic_memory(SpaprMachineState *spapr, void *fdt,
508a324d6f1SBharata B Rao int offset, MemoryDeviceInfoList *dimms)
509a324d6f1SBharata B Rao {
510b0c14ec4SDavid Hildenbrand MachineState *machine = MACHINE(spapr);
511a324d6f1SBharata B Rao int i, ret;
512a324d6f1SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
5130c9269a5SDavid Hildenbrand uint32_t device_lmb_start = machine->device_memory->base / lmb_size;
514b0c14ec4SDavid Hildenbrand uint32_t nr_lmbs = (machine->device_memory->base +
515b0c14ec4SDavid Hildenbrand memory_region_size(&machine->device_memory->mr)) /
516d0e5a8f2SBharata B Rao lmb_size;
51703d196b7SBharata B Rao uint32_t *int_buf, *cur_index, buf_len;
51816c25aefSBharata B Rao
51916c25aefSBharata B Rao /*
520ef001f06SThomas Huth * Allocate enough buffer size to fit in ibm,dynamic-memory
521ef001f06SThomas Huth */
522a324d6f1SBharata B Rao buf_len = (nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1) * sizeof(uint32_t);
52303d196b7SBharata B Rao cur_index = int_buf = g_malloc0(buf_len);
52403d196b7SBharata B Rao int_buf[0] = cpu_to_be32(nr_lmbs);
52503d196b7SBharata B Rao cur_index++;
52603d196b7SBharata B Rao for (i = 0; i < nr_lmbs; i++) {
527d0e5a8f2SBharata B Rao uint64_t addr = i * lmb_size;
52803d196b7SBharata B Rao uint32_t *dynamic_memory = cur_index;
52903d196b7SBharata B Rao
5300c9269a5SDavid Hildenbrand if (i >= device_lmb_start) {
531ce2918cbSDavid Gibson SpaprDrc *drc;
532d0e5a8f2SBharata B Rao
533fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, i);
53403d196b7SBharata B Rao g_assert(drc);
53503d196b7SBharata B Rao
53603d196b7SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32);
53703d196b7SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff);
5380b55aa91SDavid Gibson dynamic_memory[2] = cpu_to_be32(spapr_drc_index(drc));
53903d196b7SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */
540f47bd1c8SIgor Mammedov dynamic_memory[4] = cpu_to_be32(spapr_pc_dimm_node(dimms, addr));
541d0e5a8f2SBharata B Rao if (memory_region_present(get_system_memory(), addr)) {
54203d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED);
54303d196b7SBharata B Rao } else {
54403d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(0);
54503d196b7SBharata B Rao }
546d0e5a8f2SBharata B Rao } else {
547d0e5a8f2SBharata B Rao /*
548d0e5a8f2SBharata B Rao * LMB information for RMA, boot time RAM and gap b/n RAM and
5490c9269a5SDavid Hildenbrand * device memory region -- all these are marked as reserved
550d0e5a8f2SBharata B Rao * and as having no valid DRC.
551d0e5a8f2SBharata B Rao */
552d0e5a8f2SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32);
553d0e5a8f2SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff);
554d0e5a8f2SBharata B Rao dynamic_memory[2] = cpu_to_be32(0);
555d0e5a8f2SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */
556d0e5a8f2SBharata B Rao dynamic_memory[4] = cpu_to_be32(-1);
557d0e5a8f2SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED |
558d0e5a8f2SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID);
559d0e5a8f2SBharata B Rao }
56003d196b7SBharata B Rao
56103d196b7SBharata B Rao cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE;
56203d196b7SBharata B Rao }
56303d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len);
564a324d6f1SBharata B Rao g_free(int_buf);
56503d196b7SBharata B Rao if (ret < 0) {
566a324d6f1SBharata B Rao return -1;
567a324d6f1SBharata B Rao }
568a324d6f1SBharata B Rao return 0;
569a324d6f1SBharata B Rao }
570a324d6f1SBharata B Rao
571a324d6f1SBharata B Rao /*
572a324d6f1SBharata B Rao * Adds ibm,dynamic-reconfiguration-memory node.
573a324d6f1SBharata B Rao * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation
574a324d6f1SBharata B Rao * of this device tree node.
575a324d6f1SBharata B Rao */
spapr_dt_dynamic_reconfiguration_memory(SpaprMachineState * spapr,void * fdt)57691335a5eSDavid Gibson static int spapr_dt_dynamic_reconfiguration_memory(SpaprMachineState *spapr,
57791335a5eSDavid Gibson void *fdt)
578a324d6f1SBharata B Rao {
579a324d6f1SBharata B Rao MachineState *machine = MACHINE(spapr);
5800ee52012SDaniel Henrique Barboza int ret, offset;
581a324d6f1SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
5827abf9797SAnton Blanchard uint32_t prop_lmb_size[] = {cpu_to_be32(lmb_size >> 32),
5837abf9797SAnton Blanchard cpu_to_be32(lmb_size & 0xffffffff)};
584a324d6f1SBharata B Rao MemoryDeviceInfoList *dimms = NULL;
585a324d6f1SBharata B Rao
586c0ce7b4aSDavid Hildenbrand /* Don't create the node if there is no device memory. */
587c0ce7b4aSDavid Hildenbrand if (!machine->device_memory) {
588a324d6f1SBharata B Rao return 0;
589a324d6f1SBharata B Rao }
590a324d6f1SBharata B Rao
591a324d6f1SBharata B Rao offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory");
592a324d6f1SBharata B Rao
593a324d6f1SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size,
594a324d6f1SBharata B Rao sizeof(prop_lmb_size));
595a324d6f1SBharata B Rao if (ret < 0) {
596a324d6f1SBharata B Rao return ret;
597a324d6f1SBharata B Rao }
598a324d6f1SBharata B Rao
599a324d6f1SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff);
600a324d6f1SBharata B Rao if (ret < 0) {
601a324d6f1SBharata B Rao return ret;
602a324d6f1SBharata B Rao }
603a324d6f1SBharata B Rao
604a324d6f1SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0);
605a324d6f1SBharata B Rao if (ret < 0) {
606a324d6f1SBharata B Rao return ret;
607a324d6f1SBharata B Rao }
608a324d6f1SBharata B Rao
609a324d6f1SBharata B Rao /* ibm,dynamic-memory or ibm,dynamic-memory-v2 */
6102cc0e2e8SDavid Hildenbrand dimms = qmp_memory_device_list();
611a324d6f1SBharata B Rao if (spapr_ovec_test(spapr->ov5_cas, OV5_DRMEM_V2)) {
61291335a5eSDavid Gibson ret = spapr_dt_dynamic_memory_v2(spapr, fdt, offset, dimms);
613a324d6f1SBharata B Rao } else {
61491335a5eSDavid Gibson ret = spapr_dt_dynamic_memory(spapr, fdt, offset, dimms);
615a324d6f1SBharata B Rao }
616a324d6f1SBharata B Rao qapi_free_MemoryDeviceInfoList(dimms);
617a324d6f1SBharata B Rao
618a324d6f1SBharata B Rao if (ret < 0) {
619a324d6f1SBharata B Rao return ret;
62003d196b7SBharata B Rao }
62103d196b7SBharata B Rao
6220ee52012SDaniel Henrique Barboza ret = spapr_numa_write_assoc_lookup_arrays(spapr, fdt, offset);
623a324d6f1SBharata B Rao
62403d196b7SBharata B Rao return ret;
62503d196b7SBharata B Rao }
62603d196b7SBharata B Rao
spapr_dt_memory(SpaprMachineState * spapr,void * fdt)62791335a5eSDavid Gibson static int spapr_dt_memory(SpaprMachineState *spapr, void *fdt)
6286787d27bSMichael Roth {
629fa523f0dSDavid Gibson MachineState *machine = MACHINE(spapr);
63053018216SPaolo Bonzini hwaddr mem_start, node_size;
63153018216SPaolo Bonzini int i, nb_nodes = machine->numa_state->num_nodes;
63253018216SPaolo Bonzini NodeInfo *nodes = machine->numa_state->nodes;
63353018216SPaolo Bonzini
63453018216SPaolo Bonzini for (i = 0, mem_start = 0; i < nb_nodes; ++i) {
63553018216SPaolo Bonzini if (!nodes[i].node_mem) {
63653018216SPaolo Bonzini continue;
63753018216SPaolo Bonzini }
63853018216SPaolo Bonzini if (mem_start >= machine->ram_size) {
63953018216SPaolo Bonzini node_size = 0;
64053018216SPaolo Bonzini } else {
64153018216SPaolo Bonzini node_size = nodes[i].node_mem;
64253018216SPaolo Bonzini if (node_size > machine->ram_size - mem_start) {
64353018216SPaolo Bonzini node_size = machine->ram_size - mem_start;
64453018216SPaolo Bonzini }
64553018216SPaolo Bonzini }
64653018216SPaolo Bonzini if (!mem_start) {
64753018216SPaolo Bonzini /* spapr_machine_init() checks for rma_size <= node0_size
64853018216SPaolo Bonzini * already */
649f1aa45ffSDaniel Henrique Barboza spapr_dt_memory_node(spapr, fdt, i, 0, spapr->rma_size);
65053018216SPaolo Bonzini mem_start += spapr->rma_size;
65153018216SPaolo Bonzini node_size -= spapr->rma_size;
65253018216SPaolo Bonzini }
65353018216SPaolo Bonzini for ( ; node_size; ) {
65453018216SPaolo Bonzini hwaddr sizetmp = pow2floor(node_size);
65553018216SPaolo Bonzini
65653018216SPaolo Bonzini /* mem_start != 0 here */
65753018216SPaolo Bonzini if (ctzl(mem_start) < ctzl(sizetmp)) {
65853018216SPaolo Bonzini sizetmp = 1ULL << ctzl(mem_start);
65953018216SPaolo Bonzini }
66053018216SPaolo Bonzini
661f1aa45ffSDaniel Henrique Barboza spapr_dt_memory_node(spapr, fdt, i, mem_start, sizetmp);
66253018216SPaolo Bonzini node_size -= sizetmp;
66353018216SPaolo Bonzini mem_start += sizetmp;
66453018216SPaolo Bonzini }
66553018216SPaolo Bonzini }
66653018216SPaolo Bonzini
6676787d27bSMichael Roth /* Generate ibm,dynamic-reconfiguration-memory node if required */
668fa523f0dSDavid Gibson if (spapr_ovec_test(spapr->ov5_cas, OV5_DRCONF_MEMORY)) {
669fa523f0dSDavid Gibson int ret;
670fa523f0dSDavid Gibson
67191335a5eSDavid Gibson ret = spapr_dt_dynamic_reconfiguration_memory(spapr, fdt);
672417ece33SMichael Roth if (ret) {
6739b6c1da5SDaniel Henrique Barboza return ret;
674417ece33SMichael Roth }
6756787d27bSMichael Roth }
6766787d27bSMichael Roth
67753018216SPaolo Bonzini return 0;
67853018216SPaolo Bonzini }
67953018216SPaolo Bonzini
spapr_dt_cpu(CPUState * cs,void * fdt,int offset,SpaprMachineState * spapr)68091335a5eSDavid Gibson static void spapr_dt_cpu(CPUState *cs, void *fdt, int offset,
68153018216SPaolo Bonzini SpaprMachineState *spapr)
68253018216SPaolo Bonzini {
68353018216SPaolo Bonzini MachineState *ms = MACHINE(spapr);
68453018216SPaolo Bonzini PowerPCCPU *cpu = POWERPC_CPU(cs);
68553018216SPaolo Bonzini CPUPPCState *env = &cpu->env;
68653018216SPaolo Bonzini PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
68753018216SPaolo Bonzini int index = spapr_get_vcpu_id(cpu);
68853018216SPaolo Bonzini uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
68953018216SPaolo Bonzini 0xffffffff, 0xffffffff};
69053018216SPaolo Bonzini uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq()
69153018216SPaolo Bonzini : SPAPR_TIMEBASE_FREQ;
69253018216SPaolo Bonzini uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000;
69353018216SPaolo Bonzini uint32_t page_sizes_prop[64];
69453018216SPaolo Bonzini size_t page_sizes_prop_size;
69553018216SPaolo Bonzini unsigned int smp_threads = ms->smp.threads;
69653018216SPaolo Bonzini uint32_t vcpus_per_socket = smp_threads * ms->smp.cores;
69753018216SPaolo Bonzini uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
69853018216SPaolo Bonzini int compat_smt = MIN(smp_threads, ppc_compat_max_vthreads(cpu));
69953018216SPaolo Bonzini SpaprDrc *drc;
70053018216SPaolo Bonzini int drc_index;
70153018216SPaolo Bonzini uint32_t radix_AP_encodings[PPC_PAGE_SIZES_MAX_SZ];
70253018216SPaolo Bonzini int i;
70353018216SPaolo Bonzini
704*e8185fdcSHarsh Prateek Bora drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, env->core_index);
70553018216SPaolo Bonzini if (drc) {
70653018216SPaolo Bonzini drc_index = spapr_drc_index(drc);
70753018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index)));
7082a6593cbSAlexey Kardashevskiy }
7092a6593cbSAlexey Kardashevskiy
7102a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "reg", index)));
7112a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
7122a6593cbSAlexey Kardashevskiy
7132a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
7142a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
7152a6593cbSAlexey Kardashevskiy env->dcache_line_size)));
7162a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
7172a6593cbSAlexey Kardashevskiy env->dcache_line_size)));
7182a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
7192a6593cbSAlexey Kardashevskiy env->icache_line_size)));
7202a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
7212a6593cbSAlexey Kardashevskiy env->icache_line_size)));
7222a6593cbSAlexey Kardashevskiy
7232a6593cbSAlexey Kardashevskiy if (pcc->l1_dcache_size) {
7242a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
7252a6593cbSAlexey Kardashevskiy pcc->l1_dcache_size)));
7262a6593cbSAlexey Kardashevskiy } else {
7272a6593cbSAlexey Kardashevskiy warn_report("Unknown L1 dcache size for cpu");
7282a6593cbSAlexey Kardashevskiy }
7292a6593cbSAlexey Kardashevskiy if (pcc->l1_icache_size) {
7302a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
7312a6593cbSAlexey Kardashevskiy pcc->l1_icache_size)));
7322a6593cbSAlexey Kardashevskiy } else {
7332a6593cbSAlexey Kardashevskiy warn_report("Unknown L1 icache size for cpu");
7342a6593cbSAlexey Kardashevskiy }
7352a6593cbSAlexey Kardashevskiy
7362a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
7372a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
7382a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "slb-size", cpu->hash64_opts->slb_size)));
7392a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", cpu->hash64_opts->slb_size)));
7402a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
7412a6593cbSAlexey Kardashevskiy _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
7422a6593cbSAlexey Kardashevskiy
74303282a3aSLucas Mateus Castro (alqotel) if (ppc_has_spr(cpu, SPR_PURR)) {
74453018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,purr", 1)));
74553018216SPaolo Bonzini }
74603282a3aSLucas Mateus Castro (alqotel) if (ppc_has_spr(cpu, SPR_PURR)) {
74753018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,spurr", 1)));
74853018216SPaolo Bonzini }
74953018216SPaolo Bonzini
75053018216SPaolo Bonzini if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
75153018216SPaolo Bonzini _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
75253018216SPaolo Bonzini segs, sizeof(segs))));
75353018216SPaolo Bonzini }
75453018216SPaolo Bonzini
75553018216SPaolo Bonzini /* Advertise VSX (vector extensions) if available
75653018216SPaolo Bonzini * 1 == VMX / Altivec available
75753018216SPaolo Bonzini * 2 == VSX available
75853018216SPaolo Bonzini *
75953018216SPaolo Bonzini * Only CPUs for which we create core types in spapr_cpu_core.c
76053018216SPaolo Bonzini * are possible, and all of those have VMX */
7612460e1d7SCédric Le Goater if (env->insns_flags & PPC_ALTIVEC) {
76253018216SPaolo Bonzini if (spapr_get_cap(spapr, SPAPR_CAP_VSX) != 0) {
76353018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2)));
76453018216SPaolo Bonzini } else {
76553018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1)));
76653018216SPaolo Bonzini }
7672460e1d7SCédric Le Goater }
76853018216SPaolo Bonzini
76953018216SPaolo Bonzini /* Advertise DFP (Decimal Floating Point) if available
77028e02042SDavid Gibson * 0 / no property == no DFP
77153018216SPaolo Bonzini * 1 == DFP available */
772fb164994SDavid Gibson if (spapr_get_cap(spapr, SPAPR_CAP_DFP) != 0) {
7737db8a127SAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
7747db8a127SAlexey Kardashevskiy }
7757db8a127SAlexey Kardashevskiy
7767db8a127SAlexey Kardashevskiy page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
77753018216SPaolo Bonzini sizeof(page_sizes_prop));
7787db8a127SAlexey Kardashevskiy if (page_sizes_prop_size) {
7797db8a127SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
7807db8a127SAlexey Kardashevskiy page_sizes_prop, page_sizes_prop_size)));
781fb164994SDavid Gibson }
7827db8a127SAlexey Kardashevskiy
78391335a5eSDavid Gibson spapr_dt_pa_features(spapr, cpu, fdt, offset);
78453018216SPaolo Bonzini
78595912ce1SNicholas Piggin spapr_dt_pi_features(spapr, cpu, fdt, offset);
78695912ce1SNicholas Piggin
7877db8a127SAlexey Kardashevskiy _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id",
7887db8a127SAlexey Kardashevskiy cs->cpu_index / vcpus_per_socket)));
7897db8a127SAlexey Kardashevskiy
79053018216SPaolo Bonzini _FDT((fdt_setprop(fdt, offset, "ibm,pft-size",
791fb164994SDavid Gibson pft_size_prop, sizeof(pft_size_prop))));
7925fe269b1SPaul Mackerras
7935fe269b1SPaul Mackerras if (ms->numa_state->num_nodes > 1) {
7948f86a408SDaniel Henrique Barboza _FDT(spapr_numa_fixup_cpu_dt(spapr, fdt, offset, cpu));
7955fe269b1SPaul Mackerras }
7965fe269b1SPaul Mackerras
7977db8a127SAlexey Kardashevskiy _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt));
7987db8a127SAlexey Kardashevskiy
7997db8a127SAlexey Kardashevskiy if (pcc->radix_page_info) {
8007db8a127SAlexey Kardashevskiy for (i = 0; i < pcc->radix_page_info->count; i++) {
8017db8a127SAlexey Kardashevskiy radix_AP_encodings[i] =
8027db8a127SAlexey Kardashevskiy cpu_to_be32(pcc->radix_page_info->entries[i]);
8036010818cSAlexey Kardashevskiy }
8046010818cSAlexey Kardashevskiy _FDT((fdt_setprop(fdt, offset, "ibm,processor-radix-AP-encodings",
8056010818cSAlexey Kardashevskiy radix_AP_encodings,
8066010818cSAlexey Kardashevskiy pcc->radix_page_info->count *
8076010818cSAlexey Kardashevskiy sizeof(radix_AP_encodings[0]))));
8086010818cSAlexey Kardashevskiy }
8096010818cSAlexey Kardashevskiy
8106010818cSAlexey Kardashevskiy /*
8116010818cSAlexey Kardashevskiy * We set this property to let the guest know that it can use the large
8126010818cSAlexey Kardashevskiy * decrementer and its width in bits.
8136010818cSAlexey Kardashevskiy */
8146010818cSAlexey Kardashevskiy if (spapr_get_cap(spapr, SPAPR_CAP_LARGE_DECREMENTER) != SPAPR_CAP_OFF)
81553018216SPaolo Bonzini _FDT((fdt_setprop_u32(fdt, offset, "ibm,dec-bits",
81653018216SPaolo Bonzini pcc->lrg_decr_bits)));
81753018216SPaolo Bonzini }
81853018216SPaolo Bonzini
spapr_dt_one_cpu(void * fdt,SpaprMachineState * spapr,CPUState * cs,int cpus_offset)819bd87a59fSCédric Le Goater static void spapr_dt_one_cpu(void *fdt, SpaprMachineState *spapr, CPUState *cs,
820bd87a59fSCédric Le Goater int cpus_offset)
821bd87a59fSCédric Le Goater {
822bd87a59fSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs);
823bd87a59fSCédric Le Goater int index = spapr_get_vcpu_id(cpu);
824bd87a59fSCédric Le Goater DeviceClass *dc = DEVICE_GET_CLASS(cs);
825bd87a59fSCédric Le Goater g_autofree char *nodename = NULL;
826bd87a59fSCédric Le Goater int offset;
827bd87a59fSCédric Le Goater
828bd87a59fSCédric Le Goater if (!spapr_is_thread0_in_vcore(spapr, cpu)) {
829bd87a59fSCédric Le Goater return;
830bd87a59fSCédric Le Goater }
831bd87a59fSCédric Le Goater
832bd87a59fSCédric Le Goater nodename = g_strdup_printf("%s@%x", dc->fw_name, index);
833bd87a59fSCédric Le Goater offset = fdt_add_subnode(fdt, cpus_offset, nodename);
834bd87a59fSCédric Le Goater _FDT(offset);
835bd87a59fSCédric Le Goater spapr_dt_cpu(cs, fdt, offset, spapr);
836bd87a59fSCédric Le Goater }
837bd87a59fSCédric Le Goater
838bd87a59fSCédric Le Goater
spapr_dt_cpus(void * fdt,SpaprMachineState * spapr)83991335a5eSDavid Gibson static void spapr_dt_cpus(void *fdt, SpaprMachineState *spapr)
84053018216SPaolo Bonzini {
84153018216SPaolo Bonzini CPUState **rev;
84253018216SPaolo Bonzini CPUState *cs;
84353018216SPaolo Bonzini int n_cpus;
84453018216SPaolo Bonzini int cpus_offset;
84553018216SPaolo Bonzini int i;
84653018216SPaolo Bonzini
84753018216SPaolo Bonzini cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
84853018216SPaolo Bonzini _FDT(cpus_offset);
84953018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
85053018216SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
85153018216SPaolo Bonzini
85253018216SPaolo Bonzini /*
85353018216SPaolo Bonzini * We walk the CPUs in reverse order to ensure that CPU DT nodes
85453018216SPaolo Bonzini * created by fdt_add_subnode() end up in the right order in FDT
85553018216SPaolo Bonzini * for the guest kernel the enumerate the CPUs correctly.
85653018216SPaolo Bonzini *
85753018216SPaolo Bonzini * The CPU list cannot be traversed in reverse order, so we need
85853018216SPaolo Bonzini * to do extra work.
85953018216SPaolo Bonzini */
86053018216SPaolo Bonzini n_cpus = 0;
86153018216SPaolo Bonzini rev = NULL;
86253018216SPaolo Bonzini CPU_FOREACH(cs) {
86353018216SPaolo Bonzini rev = g_renew(CPUState *, rev, n_cpus + 1);
86453018216SPaolo Bonzini rev[n_cpus++] = cs;
86553018216SPaolo Bonzini }
86653018216SPaolo Bonzini
86753018216SPaolo Bonzini for (i = n_cpus - 1; i >= 0; i--) {
868bd87a59fSCédric Le Goater spapr_dt_one_cpu(fdt, spapr, rev[i], cpus_offset);
8690da6f3feSBharata B Rao }
8700da6f3feSBharata B Rao
8710da6f3feSBharata B Rao g_free(rev);
8720da6f3feSBharata B Rao }
87322419c2aSDavid Gibson
spapr_dt_rng(void * fdt)87491335a5eSDavid Gibson static int spapr_dt_rng(void *fdt)
8750da6f3feSBharata B Rao {
8760da6f3feSBharata B Rao int node;
8770da6f3feSBharata B Rao int ret;
8780da6f3feSBharata B Rao
8790da6f3feSBharata B Rao node = qemu_fdt_add_subnode(fdt, "/ibm,platform-facilities");
8800da6f3feSBharata B Rao if (node <= 0) {
8810da6f3feSBharata B Rao return -1;
8820da6f3feSBharata B Rao }
8830da6f3feSBharata B Rao ret = fdt_setprop_string(fdt, node, "device_type",
8840da6f3feSBharata B Rao "ibm,platform-facilities");
8850da6f3feSBharata B Rao ret |= fdt_setprop_cell(fdt, node, "#address-cells", 0x1);
8860da6f3feSBharata B Rao ret |= fdt_setprop_cell(fdt, node, "#size-cells", 0x0);
8870da6f3feSBharata B Rao
8880da6f3feSBharata B Rao node = fdt_add_subnode(fdt, node, "ibm,random-v1");
8890da6f3feSBharata B Rao if (node <= 0) {
8900da6f3feSBharata B Rao return -1;
8910da6f3feSBharata B Rao }
8920da6f3feSBharata B Rao ret |= fdt_setprop_string(fdt, node, "compatible", "ibm,random");
8930da6f3feSBharata B Rao
8940da6f3feSBharata B Rao return ret ? -1 : 0;
8950da6f3feSBharata B Rao }
8960da6f3feSBharata B Rao
spapr_dt_rtas(SpaprMachineState * spapr,void * fdt)897ce2918cbSDavid Gibson static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt)
8983f5dabceSDavid Gibson {
899fe6b6346SLike Xu MachineState *ms = MACHINE(spapr);
9003f5dabceSDavid Gibson int rtas;
9013f5dabceSDavid Gibson GString *hypertas = g_string_sized_new(256);
9023f5dabceSDavid Gibson GString *qemu_hypertas = g_string_sized_new(256);
9033f5dabceSDavid Gibson uint32_t lrdr_capacity[] = {
904c0ce7b4aSDavid Hildenbrand 0,
905c0ce7b4aSDavid Hildenbrand 0,
9067abf9797SAnton Blanchard cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE >> 32),
9077abf9797SAnton Blanchard cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE & 0xffffffff),
908fe6b6346SLike Xu cpu_to_be32(ms->smp.max_cpus / ms->smp.threads),
9093f5dabceSDavid Gibson };
9103f5dabceSDavid Gibson
911c0ce7b4aSDavid Hildenbrand /* Do we have device memory? */
912c0ce7b4aSDavid Hildenbrand if (MACHINE(spapr)->device_memory) {
913c0ce7b4aSDavid Hildenbrand uint64_t max_device_addr = MACHINE(spapr)->device_memory->base +
914c0ce7b4aSDavid Hildenbrand memory_region_size(&MACHINE(spapr)->device_memory->mr);
915c0ce7b4aSDavid Hildenbrand
916c0ce7b4aSDavid Hildenbrand lrdr_capacity[0] = cpu_to_be32(max_device_addr >> 32);
917c0ce7b4aSDavid Hildenbrand lrdr_capacity[1] = cpu_to_be32(max_device_addr & 0xffffffff);
918c0ce7b4aSDavid Hildenbrand }
919c0ce7b4aSDavid Hildenbrand
9203f5dabceSDavid Gibson _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas"));
9213f5dabceSDavid Gibson
9223f5dabceSDavid Gibson /* hypertas */
9233f5dabceSDavid Gibson add_str(hypertas, "hcall-pft");
9243f5dabceSDavid Gibson add_str(hypertas, "hcall-term");
9253f5dabceSDavid Gibson add_str(hypertas, "hcall-dabr");
9263f5dabceSDavid Gibson add_str(hypertas, "hcall-interrupt");
9273f5dabceSDavid Gibson add_str(hypertas, "hcall-tce");
9283f5dabceSDavid Gibson add_str(hypertas, "hcall-vio");
9293f5dabceSDavid Gibson add_str(hypertas, "hcall-splpar");
93010741314SNicholas Piggin add_str(hypertas, "hcall-join");
9313f5dabceSDavid Gibson add_str(hypertas, "hcall-bulk");
9323f5dabceSDavid Gibson add_str(hypertas, "hcall-set-mode");
9333f5dabceSDavid Gibson add_str(hypertas, "hcall-sprg0");
9343f5dabceSDavid Gibson add_str(hypertas, "hcall-copy");
9353f5dabceSDavid Gibson add_str(hypertas, "hcall-debug");
936c24ba3d0SLaurent Vivier add_str(hypertas, "hcall-vphn");
93782123b75SBharata B Rao if (spapr_get_cap(spapr, SPAPR_CAP_RPT_INVALIDATE) == SPAPR_CAP_ON) {
93882123b75SBharata B Rao add_str(hypertas, "hcall-rpt-invalidate");
93982123b75SBharata B Rao }
94082123b75SBharata B Rao
9413f5dabceSDavid Gibson add_str(qemu_hypertas, "hcall-memop1");
9423f5dabceSDavid Gibson
9433f5dabceSDavid Gibson if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
9443f5dabceSDavid Gibson add_str(hypertas, "hcall-multi-tce");
9453f5dabceSDavid Gibson }
94630f4b05bSDavid Gibson
94730f4b05bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) {
94830f4b05bSDavid Gibson add_str(hypertas, "hcall-hpt-resize");
94930f4b05bSDavid Gibson }
95030f4b05bSDavid Gibson
95181b205ceSAlexey Kardashevskiy add_str(hypertas, "hcall-watchdog");
95281b205ceSAlexey Kardashevskiy
9533f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions",
9543f5dabceSDavid Gibson hypertas->str, hypertas->len));
9553f5dabceSDavid Gibson g_string_free(hypertas, TRUE);
9563f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "qemu,hypertas-functions",
9573f5dabceSDavid Gibson qemu_hypertas->str, qemu_hypertas->len));
9583f5dabceSDavid Gibson g_string_free(qemu_hypertas, TRUE);
9593f5dabceSDavid Gibson
9601eee9950SDaniel Henrique Barboza spapr_numa_write_rtas_dt(spapr, fdt, rtas);
961da9f80fbSSerhii Popovych
9620e236d34SNicholas Piggin /*
9630e236d34SNicholas Piggin * FWNMI reserves RTAS_ERROR_LOG_MAX for the machine check error log,
9640e236d34SNicholas Piggin * and 16 bytes per CPU for system reset error log plus an extra 8 bytes.
9650e236d34SNicholas Piggin *
9660e236d34SNicholas Piggin * The system reset requirements are driven by existing Linux and PowerVM
9670e236d34SNicholas Piggin * implementation which (contrary to PAPR) saves r3 in the error log
9680e236d34SNicholas Piggin * structure like machine check, so Linux expects to find the saved r3
9690e236d34SNicholas Piggin * value at the address in r3 upon FWNMI-enabled sreset interrupt (and
9700e236d34SNicholas Piggin * does not look at the error value).
9710e236d34SNicholas Piggin *
9720e236d34SNicholas Piggin * System reset interrupts are not subject to interlock like machine
9730e236d34SNicholas Piggin * check, so this memory area could be corrupted if the sreset is
9740e236d34SNicholas Piggin * interrupted by a machine check (or vice versa) if it was shared. To
9750e236d34SNicholas Piggin * prevent this, system reset uses per-CPU areas for the sreset save
9760e236d34SNicholas Piggin * area. A system reset that interrupts a system reset handler could
9770e236d34SNicholas Piggin * still overwrite this area, but Linux doesn't try to recover in that
9780e236d34SNicholas Piggin * case anyway.
9790e236d34SNicholas Piggin *
9800e236d34SNicholas Piggin * The extra 8 bytes is required because Linux's FWNMI error log check
9810e236d34SNicholas Piggin * is off-by-one.
9827381c5d1SAlexey Kardashevskiy *
9837381c5d1SAlexey Kardashevskiy * RTAS_MIN_SIZE is required for the RTAS blob itself.
9840e236d34SNicholas Piggin */
9857381c5d1SAlexey Kardashevskiy _FDT(fdt_setprop_cell(fdt, rtas, "rtas-size", RTAS_MIN_SIZE +
9867381c5d1SAlexey Kardashevskiy RTAS_ERROR_LOG_MAX +
9877381c5d1SAlexey Kardashevskiy ms->smp.max_cpus * sizeof(uint64_t) * 2 +
9887381c5d1SAlexey Kardashevskiy sizeof(uint64_t)));
9893f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-error-log-max",
9903f5dabceSDavid Gibson RTAS_ERROR_LOG_MAX));
9913f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-event-scan-rate",
9923f5dabceSDavid Gibson RTAS_EVENT_SCAN_RATE));
9933f5dabceSDavid Gibson
9944f441474SDavid Gibson g_assert(msi_nonbroken);
9953f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,change-msix-capable", NULL, 0));
9963f5dabceSDavid Gibson
9973f5dabceSDavid Gibson /*
9983f5dabceSDavid Gibson * According to PAPR, rtas ibm,os-term does not guarantee a return
9993f5dabceSDavid Gibson * back to the guest cpu.
10003f5dabceSDavid Gibson *
10013f5dabceSDavid Gibson * While an additional ibm,extended-os-term property indicates
10023f5dabceSDavid Gibson * that rtas call return will always occur. Set this property.
10033f5dabceSDavid Gibson */
10043f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,extended-os-term", NULL, 0));
10053f5dabceSDavid Gibson
10063f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,lrdr-capacity",
10073f5dabceSDavid Gibson lrdr_capacity, sizeof(lrdr_capacity)));
10083f5dabceSDavid Gibson
10093f5dabceSDavid Gibson spapr_dt_rtas_tokens(fdt, rtas);
10103f5dabceSDavid Gibson }
10113f5dabceSDavid Gibson
1012db592b5bSCédric Le Goater /*
1013db592b5bSCédric Le Goater * Prepare ibm,arch-vec-5-platform-support, which indicates the MMU
1014db592b5bSCédric Le Goater * and the XIVE features that the guest may request and thus the valid
1015db592b5bSCédric Le Goater * values for bytes 23..26 of option vector 5:
1016db592b5bSCédric Le Goater */
spapr_dt_ov5_platform_support(SpaprMachineState * spapr,void * fdt,int chosen)1017ce2918cbSDavid Gibson static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt,
1018db592b5bSCédric Le Goater int chosen)
10199fb4541fSSam Bobroff {
1020545d6e2bSSuraj Jitindar Singh PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu);
1021545d6e2bSSuraj Jitindar Singh
1022f2b14e3aSCédric Le Goater char val[2 * 4] = {
1023ca62823bSDavid Gibson 23, 0x00, /* XICS / XIVE mode */
10249fb4541fSSam Bobroff 24, 0x00, /* Hash/Radix, filled in below. */
10259fb4541fSSam Bobroff 25, 0x00, /* Hash options: Segment Tables == no, GTSE == no. */
10269fb4541fSSam Bobroff 26, 0x40, /* Radix options: GTSE == yes. */
10279fb4541fSSam Bobroff };
10289fb4541fSSam Bobroff
1029ca62823bSDavid Gibson if (spapr->irq->xics && spapr->irq->xive) {
1030ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_BOTH;
1031ca62823bSDavid Gibson } else if (spapr->irq->xive) {
1032ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_EXPLOIT;
1033ca62823bSDavid Gibson } else {
1034ca62823bSDavid Gibson assert(spapr->irq->xics);
1035ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_LEGACY;
1036ca62823bSDavid Gibson }
1037ca62823bSDavid Gibson
10387abd43baSSuraj Jitindar Singh if (!ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0,
10397abd43baSSuraj Jitindar Singh first_ppc_cpu->compat_pvr)) {
1040db592b5bSCédric Le Goater /*
1041db592b5bSCédric Le Goater * If we're in a pre POWER9 compat mode then the guest should
1042db592b5bSCédric Le Goater * do hash and use the legacy interrupt mode
1043db592b5bSCédric Le Goater */
1044ca62823bSDavid Gibson val[1] = SPAPR_OV5_XIVE_LEGACY; /* XICS */
10457abd43baSSuraj Jitindar Singh val[3] = 0x00; /* Hash */
1046ab5add4cSFabiano Rosas spapr_check_mmu_mode(false);
10477abd43baSSuraj Jitindar Singh } else if (kvm_enabled()) {
10489fb4541fSSam Bobroff if (kvmppc_has_cap_mmu_radix() && kvmppc_has_cap_mmu_hash_v3()) {
1049f2b14e3aSCédric Le Goater val[3] = 0x80; /* OV5_MMU_BOTH */
10509fb4541fSSam Bobroff } else if (kvmppc_has_cap_mmu_radix()) {
1051f2b14e3aSCédric Le Goater val[3] = 0x40; /* OV5_MMU_RADIX_300 */
10529fb4541fSSam Bobroff } else {
1053f2b14e3aSCédric Le Goater val[3] = 0x00; /* Hash */
10549fb4541fSSam Bobroff }
10559fb4541fSSam Bobroff } else {
10567abd43baSSuraj Jitindar Singh /* V3 MMU supports both hash and radix in tcg (with dynamic switching) */
1057f2b14e3aSCédric Le Goater val[3] = 0xC0;
1058545d6e2bSSuraj Jitindar Singh }
10599fb4541fSSam Bobroff _FDT(fdt_setprop(fdt, chosen, "ibm,arch-vec-5-platform-support",
10609fb4541fSSam Bobroff val, sizeof(val)));
10619fb4541fSSam Bobroff }
10629fb4541fSSam Bobroff
spapr_dt_chosen(SpaprMachineState * spapr,void * fdt,bool reset)10631e0e1108SDavid Gibson static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt, bool reset)
10647c866c6aSDavid Gibson {
10657c866c6aSDavid Gibson MachineState *machine = MACHINE(spapr);
10666c3829a2SAlexey Kardashevskiy SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
10677c866c6aSDavid Gibson int chosen;
10681e0e1108SDavid Gibson
10691e0e1108SDavid Gibson _FDT(chosen = fdt_add_subnode(fdt, 0, "chosen"));
10701e0e1108SDavid Gibson
10711e0e1108SDavid Gibson if (reset) {
10723bf0844fSGreg Kurz const char *boot_device = spapr->boot_device;
1073aebb9b9cSDaniel Henrique Barboza g_autofree char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus);
10747c866c6aSDavid Gibson size_t cb = 0;
1075aebb9b9cSDaniel Henrique Barboza g_autofree char *bootlist = get_boot_devices_list(&cb);
10767c866c6aSDavid Gibson
10775ced7895SAlexey Kardashevskiy if (machine->kernel_cmdline && machine->kernel_cmdline[0]) {
10785ced7895SAlexey Kardashevskiy _FDT(fdt_setprop_string(fdt, chosen, "bootargs",
10795ced7895SAlexey Kardashevskiy machine->kernel_cmdline));
10805ced7895SAlexey Kardashevskiy }
10811e0e1108SDavid Gibson
10825ced7895SAlexey Kardashevskiy if (spapr->initrd_size) {
10837c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-start",
10847c866c6aSDavid Gibson spapr->initrd_base));
10857c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-end",
10867c866c6aSDavid Gibson spapr->initrd_base + spapr->initrd_size));
10875ced7895SAlexey Kardashevskiy }
10887c866c6aSDavid Gibson
10897c866c6aSDavid Gibson if (spapr->kernel_size) {
109087262806SAlexey Kardashevskiy uint64_t kprop[2] = { cpu_to_be64(spapr->kernel_addr),
10917c866c6aSDavid Gibson cpu_to_be64(spapr->kernel_size) };
10927c866c6aSDavid Gibson
10937c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel",
10947c866c6aSDavid Gibson &kprop, sizeof(kprop)));
10957c866c6aSDavid Gibson if (spapr->kernel_le) {
10967c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel-le", NULL, 0));
10977c866c6aSDavid Gibson }
10987c866c6aSDavid Gibson }
109997ec4d21SPaolo Bonzini if (machine->boot_config.has_menu && machine->boot_config.menu) {
110097ec4d21SPaolo Bonzini _FDT((fdt_setprop_cell(fdt, chosen, "qemu,boot-menu", true)));
11017c866c6aSDavid Gibson }
11027c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-width", graphic_width));
11037c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-height", graphic_height));
11047c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-depth", graphic_depth));
11057c866c6aSDavid Gibson
11067c866c6aSDavid Gibson if (cb && bootlist) {
11077c866c6aSDavid Gibson int i;
11087c866c6aSDavid Gibson
11097c866c6aSDavid Gibson for (i = 0; i < cb; i++) {
11107c866c6aSDavid Gibson if (bootlist[i] == '\n') {
11117c866c6aSDavid Gibson bootlist[i] = ' ';
11127c866c6aSDavid Gibson }
11137c866c6aSDavid Gibson }
11147c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-list", bootlist));
11157c866c6aSDavid Gibson }
11167c866c6aSDavid Gibson
11177c866c6aSDavid Gibson if (boot_device && strlen(boot_device)) {
11187c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-device", boot_device));
11197c866c6aSDavid Gibson }
11207c866c6aSDavid Gibson
1121f73eb948SPaolo Bonzini if (spapr->want_stdout_path && stdout_path) {
112290ee4e01SNikunj A Dadhania /*
11231e0e1108SDavid Gibson * "linux,stdout-path" and "stdout" properties are
11241e0e1108SDavid Gibson * deprecated by linux kernel. New platforms should only
11251e0e1108SDavid Gibson * use the "stdout-path" property. Set the new property
11261e0e1108SDavid Gibson * and continue using older property to remain compatible
11271e0e1108SDavid Gibson * with the existing firmware.
112890ee4e01SNikunj A Dadhania */
11297c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "linux,stdout-path", stdout_path));
113090ee4e01SNikunj A Dadhania _FDT(fdt_setprop_string(fdt, chosen, "stdout-path", stdout_path));
11317c866c6aSDavid Gibson }
11327c866c6aSDavid Gibson
11331e0e1108SDavid Gibson /*
11341e0e1108SDavid Gibson * We can deal with BAR reallocation just fine, advertise it
11351e0e1108SDavid Gibson * to the guest
11361e0e1108SDavid Gibson */
11376c3829a2SAlexey Kardashevskiy if (smc->linux_pci_probe) {
11386c3829a2SAlexey Kardashevskiy _FDT(fdt_setprop_cell(fdt, chosen, "linux,pci-probe-only", 0));
11396c3829a2SAlexey Kardashevskiy }
11406c3829a2SAlexey Kardashevskiy
1141db592b5bSCédric Le Goater spapr_dt_ov5_platform_support(spapr, fdt, chosen);
11427c866c6aSDavid Gibson }
11437c866c6aSDavid Gibson
1144b27fcb28SNicholas Piggin _FDT(fdt_setprop(fdt, chosen, "rng-seed", spapr->fdt_rng_seed, 32));
1145c4b07531SJason A. Donenfeld
114691335a5eSDavid Gibson _FDT(spapr_dt_ovec(fdt, chosen, spapr->ov5_cas, "ibm,architecture-vec-5"));
11471e0e1108SDavid Gibson }
11481e0e1108SDavid Gibson
spapr_dt_hypervisor(SpaprMachineState * spapr,void * fdt)1149ce2918cbSDavid Gibson static void spapr_dt_hypervisor(SpaprMachineState *spapr, void *fdt)
1150fca5f2dcSDavid Gibson {
1151fca5f2dcSDavid Gibson /* The /hypervisor node isn't in PAPR - this is a hack to allow PR
1152fca5f2dcSDavid Gibson * KVM to work under pHyp with some guest co-operation */
1153fca5f2dcSDavid Gibson int hypervisor;
1154fca5f2dcSDavid Gibson uint8_t hypercall[16];
1155fca5f2dcSDavid Gibson
1156fca5f2dcSDavid Gibson _FDT(hypervisor = fdt_add_subnode(fdt, 0, "hypervisor"));
1157fca5f2dcSDavid Gibson /* indicate KVM hypercall interface */
1158fca5f2dcSDavid Gibson _FDT(fdt_setprop_string(fdt, hypervisor, "compatible", "linux,kvm"));
1159fca5f2dcSDavid Gibson if (kvmppc_has_cap_fixup_hcalls()) {
1160fca5f2dcSDavid Gibson /*
1161fca5f2dcSDavid Gibson * Older KVM versions with older guest kernels were broken
1162fca5f2dcSDavid Gibson * with the magic page, don't allow the guest to map it.
1163fca5f2dcSDavid Gibson */
1164b77af26eSRichard Henderson if (!kvmppc_get_hypercall(cpu_env(first_cpu), hypercall,
1165fca5f2dcSDavid Gibson sizeof(hypercall))) {
1166fca5f2dcSDavid Gibson _FDT(fdt_setprop(fdt, hypervisor, "hcall-instructions",
1167fca5f2dcSDavid Gibson hypercall, sizeof(hypercall)));
1168fca5f2dcSDavid Gibson }
1169fca5f2dcSDavid Gibson }
1170fca5f2dcSDavid Gibson }
1171fca5f2dcSDavid Gibson
spapr_build_fdt(SpaprMachineState * spapr,bool reset,size_t space)11720c21e073SDavid Gibson void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space)
117353018216SPaolo Bonzini {
1174c86c1affSDaniel Henrique Barboza MachineState *machine = MACHINE(spapr);
11753c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine);
1176ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
1177776e887fSGreg Kurz uint32_t root_drc_type_mask = 0;
11787c866c6aSDavid Gibson int ret;
117953018216SPaolo Bonzini void *fdt;
1180ce2918cbSDavid Gibson SpaprPhbState *phb;
1181398a0bd5SDavid Gibson char *buf;
118253018216SPaolo Bonzini
118397b32a6aSDavid Gibson fdt = g_malloc0(space);
118497b32a6aSDavid Gibson _FDT((fdt_create_empty_tree(fdt, space)));
118553018216SPaolo Bonzini
1186398a0bd5SDavid Gibson /* Root node */
1187398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "device_type", "chrp"));
1188398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "model", "IBM pSeries (emulated by qemu)"));
1189398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "compatible", "qemu,pseries"));
1190398a0bd5SDavid Gibson
11910a794529SDavid Gibson /* Guest UUID & Name*/
1192398a0bd5SDavid Gibson buf = qemu_uuid_unparse_strdup(&qemu_uuid);
1193398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "vm,uuid", buf));
1194398a0bd5SDavid Gibson if (qemu_uuid_set) {
1195398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "system-id", buf));
1196398a0bd5SDavid Gibson }
1197398a0bd5SDavid Gibson g_free(buf);
1198398a0bd5SDavid Gibson
1199398a0bd5SDavid Gibson if (qemu_get_vm_name()) {
1200398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "ibm,partition-name",
1201398a0bd5SDavid Gibson qemu_get_vm_name()));
1202398a0bd5SDavid Gibson }
1203398a0bd5SDavid Gibson
12040a794529SDavid Gibson /* Host Model & Serial Number */
12050a794529SDavid Gibson if (spapr->host_model) {
12060a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model));
12070a794529SDavid Gibson } else if (smc->broken_host_serial_model && kvmppc_get_host_model(&buf)) {
12080a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-model", buf));
12090a794529SDavid Gibson g_free(buf);
12100a794529SDavid Gibson }
12110a794529SDavid Gibson
12120a794529SDavid Gibson if (spapr->host_serial) {
12130a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial));
12140a794529SDavid Gibson } else if (smc->broken_host_serial_model && kvmppc_get_host_serial(&buf)) {
12150a794529SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf));
12160a794529SDavid Gibson g_free(buf);
12170a794529SDavid Gibson }
12180a794529SDavid Gibson
1219398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#address-cells", 2));
1220398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2));
122153018216SPaolo Bonzini
1222fc7e0765SDavid Gibson /* /interrupt controller */
122305289273SDavid Gibson spapr_irq_dt(spapr, spapr_max_server_number(spapr), fdt, PHANDLE_INTC);
1224fc7e0765SDavid Gibson
122591335a5eSDavid Gibson ret = spapr_dt_memory(spapr, fdt);
1226e8f986fcSBharata B Rao if (ret < 0) {
1227ce9863b7SCédric Le Goater error_report("couldn't setup memory nodes in fdt");
1228e8f986fcSBharata B Rao exit(1);
122953018216SPaolo Bonzini }
123053018216SPaolo Bonzini
1231bf5a6696SDavid Gibson /* /vdevice */
1232bf5a6696SDavid Gibson spapr_dt_vdevice(spapr->vio_bus, fdt);
123353018216SPaolo Bonzini
12344d9392beSThomas Huth if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) {
123591335a5eSDavid Gibson ret = spapr_dt_rng(fdt);
12364d9392beSThomas Huth if (ret < 0) {
1237ce9863b7SCédric Le Goater error_report("could not set up rng device in the fdt");
12384d9392beSThomas Huth exit(1);
12394d9392beSThomas Huth }
12404d9392beSThomas Huth }
12414d9392beSThomas Huth
124253018216SPaolo Bonzini QLIST_FOREACH(phb, &spapr->phbs, list) {
12438cbe71ecSDavid Gibson ret = spapr_dt_phb(spapr, phb, PHANDLE_INTC, fdt, NULL);
124453018216SPaolo Bonzini if (ret < 0) {
1245da34fed7SThomas Huth error_report("couldn't setup PCI devices in fdt");
124653018216SPaolo Bonzini exit(1);
124753018216SPaolo Bonzini }
1248da34fed7SThomas Huth }
124953018216SPaolo Bonzini
125091335a5eSDavid Gibson spapr_dt_cpus(fdt, spapr);
125153018216SPaolo Bonzini
1252776e887fSGreg Kurz /* ibm,drc-indexes and friends */
1253776e887fSGreg Kurz root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_LMB;
1254776e887fSGreg Kurz if (smc->dr_phb_enabled) {
1255776e887fSGreg Kurz root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_PHB;
1256776e887fSGreg Kurz }
1257776e887fSGreg Kurz if (mc->nvdimm_supported) {
1258776e887fSGreg Kurz root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_PMEM;
1259776e887fSGreg Kurz }
1260776e887fSGreg Kurz if (root_drc_type_mask) {
1261776e887fSGreg Kurz _FDT(spapr_dt_drc(fdt, 0, NULL, root_drc_type_mask));
1262c20d332aSBharata B Rao }
1263c20d332aSBharata B Rao
1264c5514d0eSIgor Mammedov if (mc->has_hotpluggable_cpus) {
1265af81cf32SBharata B Rao int offset = fdt_path_offset(fdt, "/cpus");
12669e7d38e8SDavid Gibson ret = spapr_dt_drc(fdt, offset, NULL, SPAPR_DR_CONNECTOR_TYPE_CPU);
1267af81cf32SBharata B Rao if (ret < 0) {
1268af81cf32SBharata B Rao error_report("Couldn't set up CPU DR device tree properties");
1269af81cf32SBharata B Rao exit(1);
1270af81cf32SBharata B Rao }
1271af81cf32SBharata B Rao }
1272af81cf32SBharata B Rao
1273ffb1e275SDavid Gibson /* /event-sources */
1274ffbb1705SMichael Roth spapr_dt_events(spapr, fdt);
1275ffb1e275SDavid Gibson
12763f5dabceSDavid Gibson /* /rtas */
12773f5dabceSDavid Gibson spapr_dt_rtas(spapr, fdt);
12783f5dabceSDavid Gibson
12797c866c6aSDavid Gibson /* /chosen */
12801e0e1108SDavid Gibson spapr_dt_chosen(spapr, fdt, reset);
1281cf6e5223SDavid Gibson
1282fca5f2dcSDavid Gibson /* /hypervisor */
1283fca5f2dcSDavid Gibson if (kvm_enabled()) {
1284fca5f2dcSDavid Gibson spapr_dt_hypervisor(spapr, fdt);
1285fca5f2dcSDavid Gibson }
1286fca5f2dcSDavid Gibson
1287cf6e5223SDavid Gibson /* Build memory reserve map */
1288a49f62b9SAlexey Kardashevskiy if (reset) {
1289cf6e5223SDavid Gibson if (spapr->kernel_size) {
129087262806SAlexey Kardashevskiy _FDT((fdt_add_mem_rsv(fdt, spapr->kernel_addr,
129187262806SAlexey Kardashevskiy spapr->kernel_size)));
1292cf6e5223SDavid Gibson }
1293cf6e5223SDavid Gibson if (spapr->initrd_size) {
1294a49f62b9SAlexey Kardashevskiy _FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base,
1295a49f62b9SAlexey Kardashevskiy spapr->initrd_size)));
1296a49f62b9SAlexey Kardashevskiy }
1297cf6e5223SDavid Gibson }
1298cf6e5223SDavid Gibson
1299ee3a71e3SShivaprasad G Bhat /* NVDIMM devices */
1300ee3a71e3SShivaprasad G Bhat if (mc->nvdimm_supported) {
1301f1aa45ffSDaniel Henrique Barboza spapr_dt_persistent_memory(spapr, fdt);
1302ee3a71e3SShivaprasad G Bhat }
1303ee3a71e3SShivaprasad G Bhat
1304997b6cfcSDavid Gibson return fdt;
130553018216SPaolo Bonzini }
130653018216SPaolo Bonzini
translate_kernel_address(void * opaque,uint64_t addr)130753018216SPaolo Bonzini static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
130853018216SPaolo Bonzini {
130987262806SAlexey Kardashevskiy SpaprMachineState *spapr = opaque;
131087262806SAlexey Kardashevskiy
131187262806SAlexey Kardashevskiy return (addr & 0x0fffffff) + spapr->kernel_addr;
131253018216SPaolo Bonzini }
131353018216SPaolo Bonzini
emulate_spapr_hypercall(PPCVirtualHypervisor * vhyp,PowerPCCPU * cpu)13141d1be34dSDavid Gibson static void emulate_spapr_hypercall(PPCVirtualHypervisor *vhyp,
13151d1be34dSDavid Gibson PowerPCCPU *cpu)
131653018216SPaolo Bonzini {
131753018216SPaolo Bonzini CPUPPCState *env = &cpu->env;
131853018216SPaolo Bonzini
13198d04fb55SJan Kiszka /* The TCG path should also be holding the BQL at this point */
1320195801d7SStefan Hajnoczi g_assert(bql_locked());
13218d04fb55SJan Kiszka
1322120f738aSNicholas Piggin g_assert(!vhyp_cpu_in_nested(cpu));
1323120f738aSNicholas Piggin
1324d41ccf6eSVíctor Colombo if (FIELD_EX64(env->msr, MSR, PR)) {
132553018216SPaolo Bonzini hcall_dprintf("Hypercall made with MSR[PR]=1\n");
132653018216SPaolo Bonzini env->gpr[3] = H_PRIVILEGE;
132753018216SPaolo Bonzini } else {
132853018216SPaolo Bonzini env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]);
132953018216SPaolo Bonzini }
133053018216SPaolo Bonzini }
133153018216SPaolo Bonzini
133200fd075eSBenjamin Herrenschmidt struct LPCRSyncState {
133300fd075eSBenjamin Herrenschmidt target_ulong value;
133400fd075eSBenjamin Herrenschmidt target_ulong mask;
133500fd075eSBenjamin Herrenschmidt };
133600fd075eSBenjamin Herrenschmidt
do_lpcr_sync(CPUState * cs,run_on_cpu_data arg)133700fd075eSBenjamin Herrenschmidt static void do_lpcr_sync(CPUState *cs, run_on_cpu_data arg)
133800fd075eSBenjamin Herrenschmidt {
133900fd075eSBenjamin Herrenschmidt struct LPCRSyncState *s = arg.host_ptr;
134000fd075eSBenjamin Herrenschmidt PowerPCCPU *cpu = POWERPC_CPU(cs);
134100fd075eSBenjamin Herrenschmidt CPUPPCState *env = &cpu->env;
134200fd075eSBenjamin Herrenschmidt target_ulong lpcr;
134300fd075eSBenjamin Herrenschmidt
134400fd075eSBenjamin Herrenschmidt cpu_synchronize_state(cs);
134500fd075eSBenjamin Herrenschmidt lpcr = env->spr[SPR_LPCR];
134600fd075eSBenjamin Herrenschmidt lpcr &= ~s->mask;
134700fd075eSBenjamin Herrenschmidt lpcr |= s->value;
134800fd075eSBenjamin Herrenschmidt ppc_store_lpcr(cpu, lpcr);
134900fd075eSBenjamin Herrenschmidt }
135000fd075eSBenjamin Herrenschmidt
spapr_set_all_lpcrs(target_ulong value,target_ulong mask)135100fd075eSBenjamin Herrenschmidt void spapr_set_all_lpcrs(target_ulong value, target_ulong mask)
135200fd075eSBenjamin Herrenschmidt {
135300fd075eSBenjamin Herrenschmidt CPUState *cs;
135400fd075eSBenjamin Herrenschmidt struct LPCRSyncState s = {
135500fd075eSBenjamin Herrenschmidt .value = value,
135600fd075eSBenjamin Herrenschmidt .mask = mask
135700fd075eSBenjamin Herrenschmidt };
135800fd075eSBenjamin Herrenschmidt CPU_FOREACH(cs) {
135900fd075eSBenjamin Herrenschmidt run_on_cpu(cs, do_lpcr_sync, RUN_ON_CPU_HOST_PTR(&s));
136000fd075eSBenjamin Herrenschmidt }
136100fd075eSBenjamin Herrenschmidt }
136200fd075eSBenjamin Herrenschmidt
13639c7b7f01SNicholas Piggin /* May be used when the machine is not running */
spapr_init_all_lpcrs(target_ulong value,target_ulong mask)13649c7b7f01SNicholas Piggin void spapr_init_all_lpcrs(target_ulong value, target_ulong mask)
13659c7b7f01SNicholas Piggin {
13669c7b7f01SNicholas Piggin CPUState *cs;
13679c7b7f01SNicholas Piggin CPU_FOREACH(cs) {
13689c7b7f01SNicholas Piggin PowerPCCPU *cpu = POWERPC_CPU(cs);
13699c7b7f01SNicholas Piggin CPUPPCState *env = &cpu->env;
13709c7b7f01SNicholas Piggin target_ulong lpcr;
13719c7b7f01SNicholas Piggin
13729c7b7f01SNicholas Piggin lpcr = env->spr[SPR_LPCR];
13739c7b7f01SNicholas Piggin lpcr &= ~(LPCR_HR | LPCR_UPRT);
13749c7b7f01SNicholas Piggin ppc_store_lpcr(cpu, lpcr);
13759c7b7f01SNicholas Piggin }
13769c7b7f01SNicholas Piggin }
13779c7b7f01SNicholas Piggin
spapr_get_pate(PPCVirtualHypervisor * vhyp,PowerPCCPU * cpu,target_ulong lpid,ppc_v3_pate_t * entry)1378f32d4ab4SNicholas Piggin static bool spapr_get_pate(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu,
1379f32d4ab4SNicholas Piggin target_ulong lpid, ppc_v3_pate_t *entry)
13809861bb3eSSuraj Jitindar Singh {
1381ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
1382120f738aSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
13839861bb3eSSuraj Jitindar Singh
1384120f738aSNicholas Piggin if (!spapr_cpu->in_nested) {
1385f32d4ab4SNicholas Piggin assert(lpid == 0);
1386f32d4ab4SNicholas Piggin
138779825f4dSBenjamin Herrenschmidt /* Copy PATE1:GR into PATE0:HR */
138879825f4dSBenjamin Herrenschmidt entry->dw0 = spapr->patb_entry & PATE0_HR;
138979825f4dSBenjamin Herrenschmidt entry->dw1 = spapr->patb_entry;
1390f32d4ab4SNicholas Piggin return true;
1391c2813a35SHarsh Prateek Bora } else {
139221a8d22fSHarsh Prateek Bora if (spapr_nested_api(spapr) == NESTED_API_KVM_HV) {
1393c2813a35SHarsh Prateek Bora return spapr_get_pate_nested_hv(spapr, cpu, lpid, entry);
139498823ce0SHarsh Prateek Bora } else if (spapr_nested_api(spapr) == NESTED_API_PAPR) {
139598823ce0SHarsh Prateek Bora return spapr_get_pate_nested_papr(spapr, cpu, lpid, entry);
139698823ce0SHarsh Prateek Bora } else {
139798823ce0SHarsh Prateek Bora g_assert_not_reached();
1398c2813a35SHarsh Prateek Bora }
139921a8d22fSHarsh Prateek Bora }
14009861bb3eSSuraj Jitindar Singh }
14019861bb3eSSuraj Jitindar Singh
1402e6b8fd24SSamuel Mendoza-Jonas #define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2))
1403e6b8fd24SSamuel Mendoza-Jonas #define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID)
1404e6b8fd24SSamuel Mendoza-Jonas #define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY)
1405e6b8fd24SSamuel Mendoza-Jonas #define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY))
1406e6b8fd24SSamuel Mendoza-Jonas #define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY))
1407e6b8fd24SSamuel Mendoza-Jonas
1408715c5407SDavid Gibson /*
1409715c5407SDavid Gibson * Get the fd to access the kernel htab, re-opening it if necessary
1410715c5407SDavid Gibson */
get_htab_fd(SpaprMachineState * spapr)1411ce2918cbSDavid Gibson static int get_htab_fd(SpaprMachineState *spapr)
1412715c5407SDavid Gibson {
141314b0d748SGreg Kurz Error *local_err = NULL;
141414b0d748SGreg Kurz
1415715c5407SDavid Gibson if (spapr->htab_fd >= 0) {
1416715c5407SDavid Gibson return spapr->htab_fd;
1417715c5407SDavid Gibson }
1418715c5407SDavid Gibson
141914b0d748SGreg Kurz spapr->htab_fd = kvmppc_get_htab_fd(false, 0, &local_err);
1420715c5407SDavid Gibson if (spapr->htab_fd < 0) {
142114b0d748SGreg Kurz error_report_err(local_err);
1422715c5407SDavid Gibson }
1423715c5407SDavid Gibson
1424715c5407SDavid Gibson return spapr->htab_fd;
1425715c5407SDavid Gibson }
1426715c5407SDavid Gibson
close_htab_fd(SpaprMachineState * spapr)1427ce2918cbSDavid Gibson void close_htab_fd(SpaprMachineState *spapr)
1428715c5407SDavid Gibson {
1429715c5407SDavid Gibson if (spapr->htab_fd >= 0) {
1430715c5407SDavid Gibson close(spapr->htab_fd);
1431715c5407SDavid Gibson }
1432715c5407SDavid Gibson spapr->htab_fd = -1;
1433715c5407SDavid Gibson }
1434715c5407SDavid Gibson
spapr_hpt_mask(PPCVirtualHypervisor * vhyp)1435e57ca75cSDavid Gibson static hwaddr spapr_hpt_mask(PPCVirtualHypervisor *vhyp)
1436e57ca75cSDavid Gibson {
1437ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
1438e57ca75cSDavid Gibson
1439e57ca75cSDavid Gibson return HTAB_SIZE(spapr) / HASH_PTEG_SIZE_64 - 1;
1440e57ca75cSDavid Gibson }
1441e57ca75cSDavid Gibson
spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor * vhyp)14421ec26c75SGreg Kurz static target_ulong spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp)
14431ec26c75SGreg Kurz {
1444ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
14451ec26c75SGreg Kurz
14461ec26c75SGreg Kurz assert(kvm_enabled());
14471ec26c75SGreg Kurz
14481ec26c75SGreg Kurz if (!spapr->htab) {
14491ec26c75SGreg Kurz return 0;
14501ec26c75SGreg Kurz }
14511ec26c75SGreg Kurz
14521ec26c75SGreg Kurz return (target_ulong)(uintptr_t)spapr->htab | (spapr->htab_shift - 18);
14531ec26c75SGreg Kurz }
14541ec26c75SGreg Kurz
spapr_map_hptes(PPCVirtualHypervisor * vhyp,hwaddr ptex,int n)1455e57ca75cSDavid Gibson static const ppc_hash_pte64_t *spapr_map_hptes(PPCVirtualHypervisor *vhyp,
1456e57ca75cSDavid Gibson hwaddr ptex, int n)
1457e57ca75cSDavid Gibson {
1458ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
1459e57ca75cSDavid Gibson hwaddr pte_offset = ptex * HASH_PTE_SIZE_64;
1460e57ca75cSDavid Gibson
1461e57ca75cSDavid Gibson if (!spapr->htab) {
1462e57ca75cSDavid Gibson /*
1463e57ca75cSDavid Gibson * HTAB is controlled by KVM. Fetch into temporary buffer
1464e57ca75cSDavid Gibson */
1465e57ca75cSDavid Gibson ppc_hash_pte64_t *hptes = g_malloc(n * HASH_PTE_SIZE_64);
1466e57ca75cSDavid Gibson kvmppc_read_hptes(hptes, ptex, n);
1467e57ca75cSDavid Gibson return hptes;
1468e57ca75cSDavid Gibson }
1469e57ca75cSDavid Gibson
1470e57ca75cSDavid Gibson /*
1471e57ca75cSDavid Gibson * HTAB is controlled by QEMU. Just point to the internally
1472e57ca75cSDavid Gibson * accessible PTEG.
1473e57ca75cSDavid Gibson */
1474e57ca75cSDavid Gibson return (const ppc_hash_pte64_t *)(spapr->htab + pte_offset);
1475e57ca75cSDavid Gibson }
1476e57ca75cSDavid Gibson
spapr_unmap_hptes(PPCVirtualHypervisor * vhyp,const ppc_hash_pte64_t * hptes,hwaddr ptex,int n)1477e57ca75cSDavid Gibson static void spapr_unmap_hptes(PPCVirtualHypervisor *vhyp,
1478e57ca75cSDavid Gibson const ppc_hash_pte64_t *hptes,
1479e57ca75cSDavid Gibson hwaddr ptex, int n)
1480e57ca75cSDavid Gibson {
1481ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
1482e57ca75cSDavid Gibson
1483e57ca75cSDavid Gibson if (!spapr->htab) {
1484e57ca75cSDavid Gibson g_free((void *)hptes);
1485e57ca75cSDavid Gibson }
1486e57ca75cSDavid Gibson
1487e57ca75cSDavid Gibson /* Nothing to do for qemu managed HPT */
1488e57ca75cSDavid Gibson }
1489e57ca75cSDavid Gibson
spapr_store_hpte(PowerPCCPU * cpu,hwaddr ptex,uint64_t pte0,uint64_t pte1)1490a2dd4e83SBenjamin Herrenschmidt void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
1491e57ca75cSDavid Gibson uint64_t pte0, uint64_t pte1)
1492e57ca75cSDavid Gibson {
1493a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(cpu->vhyp);
1494e57ca75cSDavid Gibson hwaddr offset = ptex * HASH_PTE_SIZE_64;
1495e57ca75cSDavid Gibson
1496e57ca75cSDavid Gibson if (!spapr->htab) {
1497e57ca75cSDavid Gibson kvmppc_write_hpte(ptex, pte0, pte1);
1498e57ca75cSDavid Gibson } else {
14993054b0caSBenjamin Herrenschmidt if (pte0 & HPTE64_V_VALID) {
15007bf00dfbSLeandro Lupori stq_p(spapr->htab + offset + HPTE64_DW1, pte1);
15013054b0caSBenjamin Herrenschmidt /*
15023054b0caSBenjamin Herrenschmidt * When setting valid, we write PTE1 first. This ensures
15033054b0caSBenjamin Herrenschmidt * proper synchronization with the reading code in
15043054b0caSBenjamin Herrenschmidt * ppc_hash64_pteg_search()
15053054b0caSBenjamin Herrenschmidt */
15063054b0caSBenjamin Herrenschmidt smp_wmb();
15073054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset, pte0);
15083054b0caSBenjamin Herrenschmidt } else {
15093054b0caSBenjamin Herrenschmidt stq_p(spapr->htab + offset, pte0);
15103054b0caSBenjamin Herrenschmidt /*
15113054b0caSBenjamin Herrenschmidt * When clearing it we set PTE0 first. This ensures proper
15123054b0caSBenjamin Herrenschmidt * synchronization with the reading code in
15133054b0caSBenjamin Herrenschmidt * ppc_hash64_pteg_search()
15143054b0caSBenjamin Herrenschmidt */
15153054b0caSBenjamin Herrenschmidt smp_wmb();
15167bf00dfbSLeandro Lupori stq_p(spapr->htab + offset + HPTE64_DW1, pte1);
15173054b0caSBenjamin Herrenschmidt }
1518e57ca75cSDavid Gibson }
1519e57ca75cSDavid Gibson }
1520e57ca75cSDavid Gibson
spapr_hpte_set_c(PPCVirtualHypervisor * vhyp,hwaddr ptex,uint64_t pte1)1521a2dd4e83SBenjamin Herrenschmidt static void spapr_hpte_set_c(PPCVirtualHypervisor *vhyp, hwaddr ptex,
1522a2dd4e83SBenjamin Herrenschmidt uint64_t pte1)
1523a2dd4e83SBenjamin Herrenschmidt {
15247bf00dfbSLeandro Lupori hwaddr offset = ptex * HASH_PTE_SIZE_64 + HPTE64_DW1_C;
1525a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
1526a2dd4e83SBenjamin Herrenschmidt
1527a2dd4e83SBenjamin Herrenschmidt if (!spapr->htab) {
1528a2dd4e83SBenjamin Herrenschmidt /* There should always be a hash table when this is called */
1529a2dd4e83SBenjamin Herrenschmidt error_report("spapr_hpte_set_c called with no hash table !");
1530a2dd4e83SBenjamin Herrenschmidt return;
1531a2dd4e83SBenjamin Herrenschmidt }
1532a2dd4e83SBenjamin Herrenschmidt
1533a2dd4e83SBenjamin Herrenschmidt /* The HW performs a non-atomic byte update */
1534a2dd4e83SBenjamin Herrenschmidt stb_p(spapr->htab + offset, (pte1 & 0xff) | 0x80);
1535a2dd4e83SBenjamin Herrenschmidt }
1536a2dd4e83SBenjamin Herrenschmidt
spapr_hpte_set_r(PPCVirtualHypervisor * vhyp,hwaddr ptex,uint64_t pte1)1537a2dd4e83SBenjamin Herrenschmidt static void spapr_hpte_set_r(PPCVirtualHypervisor *vhyp, hwaddr ptex,
1538a2dd4e83SBenjamin Herrenschmidt uint64_t pte1)
1539a2dd4e83SBenjamin Herrenschmidt {
15407bf00dfbSLeandro Lupori hwaddr offset = ptex * HASH_PTE_SIZE_64 + HPTE64_DW1_R;
1541a2dd4e83SBenjamin Herrenschmidt SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
1542a2dd4e83SBenjamin Herrenschmidt
1543a2dd4e83SBenjamin Herrenschmidt if (!spapr->htab) {
1544a2dd4e83SBenjamin Herrenschmidt /* There should always be a hash table when this is called */
1545a2dd4e83SBenjamin Herrenschmidt error_report("spapr_hpte_set_r called with no hash table !");
1546a2dd4e83SBenjamin Herrenschmidt return;
1547a2dd4e83SBenjamin Herrenschmidt }
1548a2dd4e83SBenjamin Herrenschmidt
1549a2dd4e83SBenjamin Herrenschmidt /* The HW performs a non-atomic byte update */
1550a2dd4e83SBenjamin Herrenschmidt stb_p(spapr->htab + offset, ((pte1 >> 8) & 0xff) | 0x01);
1551a2dd4e83SBenjamin Herrenschmidt }
1552a2dd4e83SBenjamin Herrenschmidt
spapr_hpt_shift_for_ramsize(uint64_t ramsize)15530b0b8310SDavid Gibson int spapr_hpt_shift_for_ramsize(uint64_t ramsize)
15548dfe8e7fSDavid Gibson {
15558dfe8e7fSDavid Gibson int shift;
15568dfe8e7fSDavid Gibson
15578dfe8e7fSDavid Gibson /* We aim for a hash table of size 1/128 the size of RAM (rounded
15588dfe8e7fSDavid Gibson * up). The PAPR recommendation is actually 1/64 of RAM size, but
15598dfe8e7fSDavid Gibson * that's much more than is needed for Linux guests */
15608dfe8e7fSDavid Gibson shift = ctz64(pow2ceil(ramsize)) - 7;
15618dfe8e7fSDavid Gibson shift = MAX(shift, 18); /* Minimum architected size */
15628dfe8e7fSDavid Gibson shift = MIN(shift, 46); /* Maximum architected size */
15638dfe8e7fSDavid Gibson return shift;
15648dfe8e7fSDavid Gibson }
15658dfe8e7fSDavid Gibson
spapr_free_hpt(SpaprMachineState * spapr)1566ce2918cbSDavid Gibson void spapr_free_hpt(SpaprMachineState *spapr)
156706ec79e8SBharata B Rao {
1568cb5b5ab9SXuzhou Cheng qemu_vfree(spapr->htab);
156906ec79e8SBharata B Rao spapr->htab = NULL;
157006ec79e8SBharata B Rao spapr->htab_shift = 0;
157106ec79e8SBharata B Rao close_htab_fd(spapr);
157206ec79e8SBharata B Rao }
157306ec79e8SBharata B Rao
spapr_reallocate_hpt(SpaprMachineState * spapr,int shift,Error ** errp)1574a4e3a7c0SGreg Kurz int spapr_reallocate_hpt(SpaprMachineState *spapr, int shift, Error **errp)
157553018216SPaolo Bonzini {
1576c3e051edSGreg Kurz ERRP_GUARD();
1577c5f54f3eSDavid Gibson long rc;
157853018216SPaolo Bonzini
1579c5f54f3eSDavid Gibson /* Clean up any HPT info from a previous boot */
158006ec79e8SBharata B Rao spapr_free_hpt(spapr);
158153018216SPaolo Bonzini
1582c5f54f3eSDavid Gibson rc = kvmppc_reset_htab(shift);
1583f0638a0bSFabiano Rosas
1584f0638a0bSFabiano Rosas if (rc == -EOPNOTSUPP) {
1585f0638a0bSFabiano Rosas error_setg(errp, "HPT not supported in nested guests");
1586a4e3a7c0SGreg Kurz return -EOPNOTSUPP;
1587f0638a0bSFabiano Rosas }
1588f0638a0bSFabiano Rosas
1589c5f54f3eSDavid Gibson if (rc < 0) {
1590c5f54f3eSDavid Gibson /* kernel-side HPT needed, but couldn't allocate one */
1591c3e051edSGreg Kurz error_setg_errno(errp, errno, "Failed to allocate KVM HPT of order %d",
1592c5f54f3eSDavid Gibson shift);
1593c3e051edSGreg Kurz error_append_hint(errp, "Try smaller maxmem?\n");
1594a4e3a7c0SGreg Kurz return -errno;
1595c5f54f3eSDavid Gibson } else if (rc > 0) {
1596c5f54f3eSDavid Gibson /* kernel-side HPT allocated */
1597c5f54f3eSDavid Gibson if (rc != shift) {
1598c5f54f3eSDavid Gibson error_setg(errp,
1599c3e051edSGreg Kurz "Requested order %d HPT, but kernel allocated order %ld",
1600c5f54f3eSDavid Gibson shift, rc);
1601c3e051edSGreg Kurz error_append_hint(errp, "Try smaller maxmem?\n");
1602a4e3a7c0SGreg Kurz return -ENOSPC;
16037735fedaSBharata B Rao }
16047735fedaSBharata B Rao
160553018216SPaolo Bonzini spapr->htab_shift = shift;
1606c18ad9a5SDavid Gibson spapr->htab = NULL;
1607b817772aSBharata B Rao } else {
1608c5f54f3eSDavid Gibson /* kernel-side HPT not needed, allocate in userspace instead */
1609c5f54f3eSDavid Gibson size_t size = 1ULL << shift;
1610c5f54f3eSDavid Gibson int i;
161101a57972SSamuel Mendoza-Jonas
1612c5f54f3eSDavid Gibson spapr->htab = qemu_memalign(size, size);
1613c5f54f3eSDavid Gibson memset(spapr->htab, 0, size);
1614c5f54f3eSDavid Gibson spapr->htab_shift = shift;
1615b817772aSBharata B Rao
1616c5f54f3eSDavid Gibson for (i = 0; i < size / HASH_PTE_SIZE_64; i++) {
1617c5f54f3eSDavid Gibson DIRTY_HPTE(HPTE(spapr->htab, i));
16187735fedaSBharata B Rao }
161953018216SPaolo Bonzini }
1620ee4d9eccSSuraj Jitindar Singh /* We're setting up a hash table, so that means we're not radix */
1621176dcceeSSuraj Jitindar Singh spapr->patb_entry = 0;
16229c7b7f01SNicholas Piggin spapr_init_all_lpcrs(0, LPCR_HR | LPCR_UPRT);
1623a4e3a7c0SGreg Kurz return 0;
162453018216SPaolo Bonzini }
162553018216SPaolo Bonzini
spapr_setup_hpt(SpaprMachineState * spapr)16268897ea5aSDavid Gibson void spapr_setup_hpt(SpaprMachineState *spapr)
1627b4db5413SSuraj Jitindar Singh {
16282772cf6bSDavid Gibson int hpt_shift;
16292772cf6bSDavid Gibson
1630087820e3SGreg Kurz if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DISABLED) {
16312772cf6bSDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(MACHINE(spapr)->maxram_size);
16322772cf6bSDavid Gibson } else {
1633768a20f3SDavid Gibson uint64_t current_ram_size;
1634768a20f3SDavid Gibson
1635768a20f3SDavid Gibson current_ram_size = MACHINE(spapr)->ram_size + get_plugged_memory_size();
1636768a20f3SDavid Gibson hpt_shift = spapr_hpt_shift_for_ramsize(current_ram_size);
16372772cf6bSDavid Gibson }
16382772cf6bSDavid Gibson spapr_reallocate_hpt(spapr, hpt_shift, &error_fatal);
16392772cf6bSDavid Gibson
16408897ea5aSDavid Gibson if (kvm_enabled()) {
16416a84737cSDavid Gibson hwaddr vrma_limit = kvmppc_vrma_limit(spapr->htab_shift);
16426a84737cSDavid Gibson
16438897ea5aSDavid Gibson /* Check our RMA fits in the possible VRMA */
16448897ea5aSDavid Gibson if (vrma_limit < spapr->rma_size) {
16458897ea5aSDavid Gibson error_report("Unable to create %" HWADDR_PRIu
16468897ea5aSDavid Gibson "MiB RMA (VRMA only allows %" HWADDR_PRIu "MiB",
16478897ea5aSDavid Gibson spapr->rma_size / MiB, vrma_limit / MiB);
16488897ea5aSDavid Gibson exit(EXIT_FAILURE);
16498897ea5aSDavid Gibson }
1650b4db5413SSuraj Jitindar Singh }
1651b4db5413SSuraj Jitindar Singh }
1652b4db5413SSuraj Jitindar Singh
spapr_check_mmu_mode(bool guest_radix)1653068479e1SFabiano Rosas void spapr_check_mmu_mode(bool guest_radix)
1654068479e1SFabiano Rosas {
1655068479e1SFabiano Rosas if (guest_radix) {
1656068479e1SFabiano Rosas if (kvm_enabled() && !kvmppc_has_cap_mmu_radix()) {
1657068479e1SFabiano Rosas error_report("Guest requested unavailable MMU mode (radix).");
1658068479e1SFabiano Rosas exit(EXIT_FAILURE);
1659068479e1SFabiano Rosas }
1660068479e1SFabiano Rosas } else {
1661068479e1SFabiano Rosas if (kvm_enabled() && kvmppc_has_cap_mmu_radix()
1662068479e1SFabiano Rosas && !kvmppc_has_cap_mmu_hash_v3()) {
1663068479e1SFabiano Rosas error_report("Guest requested unavailable MMU mode (hash).");
1664068479e1SFabiano Rosas exit(EXIT_FAILURE);
1665068479e1SFabiano Rosas }
1666068479e1SFabiano Rosas }
1667068479e1SFabiano Rosas }
1668068479e1SFabiano Rosas
spapr_machine_reset(MachineState * machine,ResetType type)16691b063fe2SJuraj Marcin static void spapr_machine_reset(MachineState *machine, ResetType type)
167053018216SPaolo Bonzini {
1671ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(machine);
1672182735efSAndreas Färber PowerPCCPU *first_ppc_cpu;
1673744a928cSAlexey Kardashevskiy hwaddr fdt_addr;
1674997b6cfcSDavid Gibson void *fdt;
1675997b6cfcSDavid Gibson int rc;
1676259186a7SAndreas Färber
16771b063fe2SJuraj Marcin if (type != RESET_TYPE_SNAPSHOT_LOAD) {
1678b27fcb28SNicholas Piggin /*
1679b27fcb28SNicholas Piggin * Record-replay snapshot load must not consume random, this was
1680b27fcb28SNicholas Piggin * already replayed from initial machine reset.
1681b27fcb28SNicholas Piggin */
1682b27fcb28SNicholas Piggin qemu_guest_getrandom_nofail(spapr->fdt_rng_seed, 32);
1683b27fcb28SNicholas Piggin }
1684b27fcb28SNicholas Piggin
168500a238b1SXiaoyao Li if (machine->cgs) {
168600a238b1SXiaoyao Li confidential_guest_kvm_reset(machine->cgs, &error_fatal);
168700a238b1SXiaoyao Li }
16889f6edd06SDavid Gibson spapr_caps_apply(spapr);
16896026fdbdSHarsh Prateek Bora spapr_nested_reset(spapr);
169033face6bSDavid Gibson
16911481fe5fSLaurent Vivier first_ppc_cpu = POWERPC_CPU(first_cpu);
16921481fe5fSLaurent Vivier if (kvm_enabled() && kvmppc_has_cap_mmu_radix() &&
1693ad99d04cSDavid Gibson ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0,
16941481fe5fSLaurent Vivier spapr->max_compat_pvr)) {
169579825f4dSBenjamin Herrenschmidt /*
169679825f4dSBenjamin Herrenschmidt * If using KVM with radix mode available, VCPUs can be started
1697b4db5413SSuraj Jitindar Singh * without a HPT because KVM will start them in radix mode.
169879825f4dSBenjamin Herrenschmidt * Set the GR bit in PATE so that we know there is no HPT.
169979825f4dSBenjamin Herrenschmidt */
170079825f4dSBenjamin Herrenschmidt spapr->patb_entry = PATE1_GR;
170100fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(LPCR_HR | LPCR_UPRT, LPCR_HR | LPCR_UPRT);
1702b4db5413SSuraj Jitindar Singh } else {
17038897ea5aSDavid Gibson spapr_setup_hpt(spapr);
1704c5f54f3eSDavid Gibson }
170553018216SPaolo Bonzini
17061b063fe2SJuraj Marcin qemu_devices_reset(type);
170725c9780dSDavid Gibson
17089012a53fSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas);
17099012a53fSGreg Kurz spapr->ov5_cas = spapr_ovec_new();
17109012a53fSGreg Kurz
17119c7b7f01SNicholas Piggin ppc_init_compat_all(spapr->max_compat_pvr, &error_fatal);
17129012a53fSGreg Kurz
1713ec132efaSAlexey Kardashevskiy /*
1714b2e22477SCédric Le Goater * This is fixing some of the default configuration of the XIVE
1715b2e22477SCédric Le Goater * devices. To be called after the reset of the machine devices.
1716b2e22477SCédric Le Goater */
1717b2e22477SCédric Le Goater spapr_irq_reset(spapr, &error_fatal);
1718b2e22477SCédric Le Goater
171923ff81bdSGreg Kurz /*
172023ff81bdSGreg Kurz * There is no CAS under qtest. Simulate one to please the code that
172123ff81bdSGreg Kurz * depends on spapr->ov5_cas. This is especially needed to test device
172223ff81bdSGreg Kurz * unplug, so we do that before resetting the DRCs.
172323ff81bdSGreg Kurz */
172423ff81bdSGreg Kurz if (qtest_enabled()) {
172523ff81bdSGreg Kurz spapr_ovec_cleanup(spapr->ov5_cas);
172623ff81bdSGreg Kurz spapr->ov5_cas = spapr_ovec_clone(spapr->ov5);
172723ff81bdSGreg Kurz }
172823ff81bdSGreg Kurz
1729b5513584SShivaprasad G Bhat spapr_nvdimm_finish_flushes();
1730b5513584SShivaprasad G Bhat
173182512483SGreg Kurz /* DRC reset may cause a device to be unplugged. This will cause troubles
173282512483SGreg Kurz * if this device is used by another device (eg, a running vhost backend
173382512483SGreg Kurz * will crash QEMU if the DIMM holding the vring goes away). To avoid such
173482512483SGreg Kurz * situations, we reset DRCs after all devices have been reset.
173582512483SGreg Kurz */
173611055041SGreg Kurz spapr_drc_reset_all(spapr);
173782512483SGreg Kurz
173856258174SDaniel Henrique Barboza spapr_clear_pending_events(spapr);
173953018216SPaolo Bonzini
1740b7d1f77aSBenjamin Herrenschmidt /*
17414b98e72dSAlexey Kardashevskiy * We place the device tree just below either the top of the RMA,
1742df269271SAlexey Kardashevskiy * or just below 2GB, whichever is lower, so that it can be
1743b7d1f77aSBenjamin Herrenschmidt * processed with 32-bit real mode code if necessary
1744b7d1f77aSBenjamin Herrenschmidt */
17454b98e72dSAlexey Kardashevskiy fdt_addr = MIN(spapr->rma_size, FDT_MAX_ADDR) - FDT_MAX_SIZE;
1746b7d1f77aSBenjamin Herrenschmidt
174797b32a6aSDavid Gibson fdt = spapr_build_fdt(spapr, true, FDT_MAX_SIZE);
1748fc8c745dSAlexey Kardashevskiy if (spapr->vof) {
174921bde1ecSAlexey Kardashevskiy spapr_vof_reset(spapr, fdt, &error_fatal);
1750fc8c745dSAlexey Kardashevskiy /*
1751fc8c745dSAlexey Kardashevskiy * Do not pack the FDT as the client may change properties.
1752fc8c745dSAlexey Kardashevskiy * VOF client does not expect the FDT so we do not load it to the VM.
1753fc8c745dSAlexey Kardashevskiy */
1754fc8c745dSAlexey Kardashevskiy } else {
1755997b6cfcSDavid Gibson rc = fdt_pack(fdt);
1756997b6cfcSDavid Gibson /* Should only fail if we've built a corrupted tree */
1757997b6cfcSDavid Gibson assert(rc == 0);
1758997b6cfcSDavid Gibson
1759fc8c745dSAlexey Kardashevskiy spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT,
1760fc8c745dSAlexey Kardashevskiy 0, fdt_addr, 0);
1761cae172abSDavid Gibson cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
1762fc8c745dSAlexey Kardashevskiy }
1763fc8c745dSAlexey Kardashevskiy qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
1764fc8c745dSAlexey Kardashevskiy
1765fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob);
1766fea35ca4SAlexey Kardashevskiy spapr->fdt_size = fdt_totalsize(fdt);
1767fea35ca4SAlexey Kardashevskiy spapr->fdt_initial_size = spapr->fdt_size;
1768fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = fdt;
1769997b6cfcSDavid Gibson
1770d890f2faSDaniel Henrique Barboza /* Set machine->fdt for 'dumpdtb' QMP/HMP command */
1771d890f2faSDaniel Henrique Barboza machine->fdt = fdt;
1772d890f2faSDaniel Henrique Barboza
177353018216SPaolo Bonzini /* Set up the entry state */
1774182735efSAndreas Färber first_ppc_cpu->env.gpr[5] = 0;
177553018216SPaolo Bonzini
1776edfdbf9cSNicholas Piggin spapr->fwnmi_system_reset_addr = -1;
17778af7e1feSNicholas Piggin spapr->fwnmi_machine_check_addr = -1;
17788af7e1feSNicholas Piggin spapr->fwnmi_machine_check_interlock = -1;
17799ac703acSAravinda Prasad
17809ac703acSAravinda Prasad /* Signal all vCPUs waiting on this condition */
17818af7e1feSNicholas Piggin qemu_cond_broadcast(&spapr->fwnmi_machine_check_interlock_cond);
17822500fb42SAravinda Prasad
1783c8a7fc51SSteve Sistare migrate_del_blocker(&spapr->fwnmi_migration_blocker);
178453018216SPaolo Bonzini }
178553018216SPaolo Bonzini
spapr_create_nvram(SpaprMachineState * spapr)1786ce2918cbSDavid Gibson static void spapr_create_nvram(SpaprMachineState *spapr)
178753018216SPaolo Bonzini {
17883e80f690SMarkus Armbruster DeviceState *dev = qdev_new("spapr-nvram");
17893978b863SPaolo Bonzini DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
179053018216SPaolo Bonzini
17913978b863SPaolo Bonzini if (dinfo) {
1792934df912SMarkus Armbruster qdev_prop_set_drive_err(dev, "drive", blk_by_legacy_dinfo(dinfo),
17936231a6daSMarkus Armbruster &error_fatal);
179453018216SPaolo Bonzini }
179553018216SPaolo Bonzini
17963e80f690SMarkus Armbruster qdev_realize_and_unref(dev, &spapr->vio_bus->bus, &error_fatal);
179753018216SPaolo Bonzini
1798ce2918cbSDavid Gibson spapr->nvram = (struct SpaprNvram *)dev;
179953018216SPaolo Bonzini }
180053018216SPaolo Bonzini
spapr_rtc_create(SpaprMachineState * spapr)1801ce2918cbSDavid Gibson static void spapr_rtc_create(SpaprMachineState *spapr)
180228df36a1SDavid Gibson {
18039fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(spapr), "rtc", &spapr->rtc,
18049fc7fc4dSMarkus Armbruster sizeof(spapr->rtc), TYPE_SPAPR_RTC,
1805f6d4dca8SThomas Huth &error_fatal, NULL);
1806ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&spapr->rtc), NULL, &error_fatal);
1807147ff807SCédric Le Goater object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc),
1808d2623129SMarkus Armbruster "date");
180928df36a1SDavid Gibson }
181028df36a1SDavid Gibson
181153018216SPaolo Bonzini /* Returns whether we want to use VGA or not */
spapr_vga_init(PCIBus * pci_bus,Error ** errp)181214c6a894SDavid Gibson static bool spapr_vga_init(PCIBus *pci_bus, Error **errp)
181353018216SPaolo Bonzini {
1814f9bcb2d6SGautam Agrawal vga_interface_created = true;
181553018216SPaolo Bonzini switch (vga_interface_type) {
181653018216SPaolo Bonzini case VGA_NONE:
18177effdaa3SMark Wu return false;
18187effdaa3SMark Wu case VGA_DEVICE:
18197effdaa3SMark Wu return true;
182053018216SPaolo Bonzini case VGA_STD:
1821b798c190SBenjamin Herrenschmidt case VGA_VIRTIO:
18226e66d0c6SThomas Huth case VGA_CIRRUS:
182353018216SPaolo Bonzini return pci_vga_init(pci_bus) != NULL;
182453018216SPaolo Bonzini default:
182514c6a894SDavid Gibson error_setg(errp,
182614c6a894SDavid Gibson "Unsupported VGA mode, only -vga std or -vga virtio is supported");
182714c6a894SDavid Gibson return false;
182853018216SPaolo Bonzini }
182953018216SPaolo Bonzini }
183053018216SPaolo Bonzini
spapr_pre_load(void * opaque)18314e5fe368SSuraj Jitindar Singh static int spapr_pre_load(void *opaque)
18324e5fe368SSuraj Jitindar Singh {
18334e5fe368SSuraj Jitindar Singh int rc;
18344e5fe368SSuraj Jitindar Singh
18354e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_load(opaque);
18364e5fe368SSuraj Jitindar Singh if (rc) {
18374e5fe368SSuraj Jitindar Singh return rc;
18384e5fe368SSuraj Jitindar Singh }
18394e5fe368SSuraj Jitindar Singh
18404e5fe368SSuraj Jitindar Singh return 0;
18414e5fe368SSuraj Jitindar Singh }
18424e5fe368SSuraj Jitindar Singh
spapr_post_load(void * opaque,int version_id)1843880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id)
1844880ae7deSDavid Gibson {
1845ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque;
1846880ae7deSDavid Gibson int err = 0;
1847880ae7deSDavid Gibson
1848be85537dSDavid Gibson err = spapr_caps_post_migration(spapr);
1849be85537dSDavid Gibson if (err) {
1850be85537dSDavid Gibson return err;
1851be85537dSDavid Gibson }
1852be85537dSDavid Gibson
1853e502202cSCédric Le Goater /*
1854e502202cSCédric Le Goater * In earlier versions, there was no separate qdev for the PAPR
1855880ae7deSDavid Gibson * RTC, so the RTC offset was stored directly in sPAPREnvironment.
1856880ae7deSDavid Gibson * So when migrating from those versions, poke the incoming offset
1857e502202cSCédric Le Goater * value into the RTC device
1858e502202cSCédric Le Goater */
1859880ae7deSDavid Gibson if (version_id < 3) {
1860147ff807SCédric Le Goater err = spapr_rtc_import_offset(&spapr->rtc, spapr->rtc_offset);
1861e502202cSCédric Le Goater if (err) {
1862e502202cSCédric Le Goater return err;
1863e502202cSCédric Le Goater }
1864880ae7deSDavid Gibson }
1865880ae7deSDavid Gibson
18660c86b2dfSLaurent Vivier if (kvm_enabled() && spapr->patb_entry) {
1867d39c90f5SBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
186879825f4dSBenjamin Herrenschmidt bool radix = !!(spapr->patb_entry & PATE1_GR);
1869d39c90f5SBharata B Rao bool gtse = !!(cpu->env.spr[SPR_LPCR] & LPCR_GTSE);
1870d39c90f5SBharata B Rao
187100fd075eSBenjamin Herrenschmidt /*
187200fd075eSBenjamin Herrenschmidt * Update LPCR:HR and UPRT as they may not be set properly in
187300fd075eSBenjamin Herrenschmidt * the stream
187400fd075eSBenjamin Herrenschmidt */
187500fd075eSBenjamin Herrenschmidt spapr_set_all_lpcrs(radix ? (LPCR_HR | LPCR_UPRT) : 0,
187600fd075eSBenjamin Herrenschmidt LPCR_HR | LPCR_UPRT);
187700fd075eSBenjamin Herrenschmidt
1878d39c90f5SBharata B Rao err = kvmppc_configure_v3_mmu(cpu, radix, gtse, spapr->patb_entry);
1879d39c90f5SBharata B Rao if (err) {
1880d39c90f5SBharata B Rao error_report("Process table config unsupported by the host");
1881d39c90f5SBharata B Rao return -EINVAL;
1882d39c90f5SBharata B Rao }
1883d39c90f5SBharata B Rao }
1884d39c90f5SBharata B Rao
18851c53b06cSCédric Le Goater err = spapr_irq_post_load(spapr, version_id);
18861c53b06cSCédric Le Goater if (err) {
18871c53b06cSCédric Le Goater return err;
18881c53b06cSCédric Le Goater }
18891c53b06cSCédric Le Goater
1890880ae7deSDavid Gibson return err;
1891880ae7deSDavid Gibson }
1892880ae7deSDavid Gibson
spapr_pre_save(void * opaque)18934e5fe368SSuraj Jitindar Singh static int spapr_pre_save(void *opaque)
18944e5fe368SSuraj Jitindar Singh {
18954e5fe368SSuraj Jitindar Singh int rc;
18964e5fe368SSuraj Jitindar Singh
18974e5fe368SSuraj Jitindar Singh rc = spapr_caps_pre_save(opaque);
18984e5fe368SSuraj Jitindar Singh if (rc) {
18994e5fe368SSuraj Jitindar Singh return rc;
19004e5fe368SSuraj Jitindar Singh }
19014e5fe368SSuraj Jitindar Singh
19024e5fe368SSuraj Jitindar Singh return 0;
19034e5fe368SSuraj Jitindar Singh }
19044e5fe368SSuraj Jitindar Singh
version_before_3(void * opaque,int version_id)1905880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id)
1906880ae7deSDavid Gibson {
1907880ae7deSDavid Gibson return version_id < 3;
1908880ae7deSDavid Gibson }
1909880ae7deSDavid Gibson
spapr_pending_events_needed(void * opaque)1910fd38804bSDaniel Henrique Barboza static bool spapr_pending_events_needed(void *opaque)
1911fd38804bSDaniel Henrique Barboza {
1912ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque;
1913fd38804bSDaniel Henrique Barboza return !QTAILQ_EMPTY(&spapr->pending_events);
1914fd38804bSDaniel Henrique Barboza }
1915fd38804bSDaniel Henrique Barboza
1916fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_event_entry = {
1917fd38804bSDaniel Henrique Barboza .name = "spapr_event_log_entry",
1918fd38804bSDaniel Henrique Barboza .version_id = 1,
1919fd38804bSDaniel Henrique Barboza .minimum_version_id = 1,
1920078ddbc9SRichard Henderson .fields = (const VMStateField[]) {
1921ce2918cbSDavid Gibson VMSTATE_UINT32(summary, SpaprEventLogEntry),
1922ce2918cbSDavid Gibson VMSTATE_UINT32(extended_length, SpaprEventLogEntry),
1923ce2918cbSDavid Gibson VMSTATE_VBUFFER_ALLOC_UINT32(extended_log, SpaprEventLogEntry, 0,
19245341258eSDavid Gibson NULL, extended_length),
1925fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST()
1926fd38804bSDaniel Henrique Barboza },
1927fd38804bSDaniel Henrique Barboza };
1928fd38804bSDaniel Henrique Barboza
1929fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_pending_events = {
1930fd38804bSDaniel Henrique Barboza .name = "spapr_pending_events",
1931fd38804bSDaniel Henrique Barboza .version_id = 1,
1932fd38804bSDaniel Henrique Barboza .minimum_version_id = 1,
1933fd38804bSDaniel Henrique Barboza .needed = spapr_pending_events_needed,
1934078ddbc9SRichard Henderson .fields = (const VMStateField[]) {
1935ce2918cbSDavid Gibson VMSTATE_QTAILQ_V(pending_events, SpaprMachineState, 1,
1936ce2918cbSDavid Gibson vmstate_spapr_event_entry, SpaprEventLogEntry, next),
1937fd38804bSDaniel Henrique Barboza VMSTATE_END_OF_LIST()
1938fd38804bSDaniel Henrique Barboza },
1939fd38804bSDaniel Henrique Barboza };
1940fd38804bSDaniel Henrique Barboza
spapr_ov5_cas_needed(void * opaque)194162ef3760SMichael Roth static bool spapr_ov5_cas_needed(void *opaque)
194262ef3760SMichael Roth {
1943ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque;
1944ce2918cbSDavid Gibson SpaprOptionVector *ov5_mask = spapr_ovec_new();
194562ef3760SMichael Roth bool cas_needed;
194662ef3760SMichael Roth
1947ce2918cbSDavid Gibson /* Prior to the introduction of SpaprOptionVector, we had two option
194862ef3760SMichael Roth * vectors we dealt with: OV5_FORM1_AFFINITY, and OV5_DRCONF_MEMORY.
194962ef3760SMichael Roth * Both of these options encode machine topology into the device-tree
195062ef3760SMichael Roth * in such a way that the now-booted OS should still be able to interact
195162ef3760SMichael Roth * appropriately with QEMU regardless of what options were actually
195262ef3760SMichael Roth * negotiatied on the source side.
195362ef3760SMichael Roth *
195462ef3760SMichael Roth * As such, we can avoid migrating the CAS-negotiated options if these
195562ef3760SMichael Roth * are the only options available on the current machine/platform.
195662ef3760SMichael Roth * Since these are the only options available for pseries-2.7 and
195762ef3760SMichael Roth * earlier, this allows us to maintain old->new/new->old migration
195862ef3760SMichael Roth * compatibility.
195962ef3760SMichael Roth *
196062ef3760SMichael Roth * For QEMU 2.8+, there are additional CAS-negotiatable options available
196162ef3760SMichael Roth * via default pseries-2.8 machines and explicit command-line parameters.
196262ef3760SMichael Roth * Some of these options, like OV5_HP_EVT, *do* require QEMU to be aware
196362ef3760SMichael Roth * of the actual CAS-negotiated values to continue working properly. For
196462ef3760SMichael Roth * example, availability of memory unplug depends on knowing whether
196562ef3760SMichael Roth * OV5_HP_EVT was negotiated via CAS.
196662ef3760SMichael Roth *
196762ef3760SMichael Roth * Thus, for any cases where the set of available CAS-negotiatable
196862ef3760SMichael Roth * options extends beyond OV5_FORM1_AFFINITY and OV5_DRCONF_MEMORY, we
1969aef19c04SGreg Kurz * include the CAS-negotiated options in the migration stream, unless
1970aef19c04SGreg Kurz * if they affect boot time behaviour only.
197162ef3760SMichael Roth */
197262ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_FORM1_AFFINITY);
197362ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_DRCONF_MEMORY);
1974aef19c04SGreg Kurz spapr_ovec_set(ov5_mask, OV5_DRMEM_V2);
197562ef3760SMichael Roth
1976d1d32d62SDavid Gibson /* We need extra information if we have any bits outside the mask
1977d1d32d62SDavid Gibson * defined above */
1978d1d32d62SDavid Gibson cas_needed = !spapr_ovec_subset(spapr->ov5, ov5_mask);
197962ef3760SMichael Roth
198062ef3760SMichael Roth spapr_ovec_cleanup(ov5_mask);
198162ef3760SMichael Roth
198262ef3760SMichael Roth return cas_needed;
198362ef3760SMichael Roth }
198462ef3760SMichael Roth
198562ef3760SMichael Roth static const VMStateDescription vmstate_spapr_ov5_cas = {
198662ef3760SMichael Roth .name = "spapr_option_vector_ov5_cas",
198762ef3760SMichael Roth .version_id = 1,
198862ef3760SMichael Roth .minimum_version_id = 1,
198962ef3760SMichael Roth .needed = spapr_ov5_cas_needed,
1990078ddbc9SRichard Henderson .fields = (const VMStateField[]) {
1991ce2918cbSDavid Gibson VMSTATE_STRUCT_POINTER_V(ov5_cas, SpaprMachineState, 1,
1992ce2918cbSDavid Gibson vmstate_spapr_ovec, SpaprOptionVector),
199362ef3760SMichael Roth VMSTATE_END_OF_LIST()
199462ef3760SMichael Roth },
199562ef3760SMichael Roth };
199662ef3760SMichael Roth
spapr_patb_entry_needed(void * opaque)19979861bb3eSSuraj Jitindar Singh static bool spapr_patb_entry_needed(void *opaque)
19989861bb3eSSuraj Jitindar Singh {
1999ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque;
20009861bb3eSSuraj Jitindar Singh
20019861bb3eSSuraj Jitindar Singh return !!spapr->patb_entry;
20029861bb3eSSuraj Jitindar Singh }
20039861bb3eSSuraj Jitindar Singh
20049861bb3eSSuraj Jitindar Singh static const VMStateDescription vmstate_spapr_patb_entry = {
20059861bb3eSSuraj Jitindar Singh .name = "spapr_patb_entry",
20069861bb3eSSuraj Jitindar Singh .version_id = 1,
20079861bb3eSSuraj Jitindar Singh .minimum_version_id = 1,
20089861bb3eSSuraj Jitindar Singh .needed = spapr_patb_entry_needed,
2009078ddbc9SRichard Henderson .fields = (const VMStateField[]) {
2010ce2918cbSDavid Gibson VMSTATE_UINT64(patb_entry, SpaprMachineState),
20119861bb3eSSuraj Jitindar Singh VMSTATE_END_OF_LIST()
20129861bb3eSSuraj Jitindar Singh },
20139861bb3eSSuraj Jitindar Singh };
20149861bb3eSSuraj Jitindar Singh
spapr_irq_map_needed(void * opaque)201582cffa2eSCédric Le Goater static bool spapr_irq_map_needed(void *opaque)
201682cffa2eSCédric Le Goater {
2017ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque;
201882cffa2eSCédric Le Goater
201982cffa2eSCédric Le Goater return spapr->irq_map && !bitmap_empty(spapr->irq_map, spapr->irq_map_nr);
202082cffa2eSCédric Le Goater }
202182cffa2eSCédric Le Goater
202282cffa2eSCédric Le Goater static const VMStateDescription vmstate_spapr_irq_map = {
202382cffa2eSCédric Le Goater .name = "spapr_irq_map",
202482cffa2eSCédric Le Goater .version_id = 1,
202582cffa2eSCédric Le Goater .minimum_version_id = 1,
202682cffa2eSCédric Le Goater .needed = spapr_irq_map_needed,
2027078ddbc9SRichard Henderson .fields = (const VMStateField[]) {
2028ce2918cbSDavid Gibson VMSTATE_BITMAP(irq_map, SpaprMachineState, 0, irq_map_nr),
202982cffa2eSCédric Le Goater VMSTATE_END_OF_LIST()
203082cffa2eSCédric Le Goater },
203182cffa2eSCédric Le Goater };
203282cffa2eSCédric Le Goater
spapr_dtb_needed(void * opaque)2033fea35ca4SAlexey Kardashevskiy static bool spapr_dtb_needed(void *opaque)
2034fea35ca4SAlexey Kardashevskiy {
2035ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(opaque);
2036fea35ca4SAlexey Kardashevskiy
2037fea35ca4SAlexey Kardashevskiy return smc->update_dt_enabled;
2038fea35ca4SAlexey Kardashevskiy }
2039fea35ca4SAlexey Kardashevskiy
spapr_dtb_pre_load(void * opaque)2040fea35ca4SAlexey Kardashevskiy static int spapr_dtb_pre_load(void *opaque)
2041fea35ca4SAlexey Kardashevskiy {
2042ce2918cbSDavid Gibson SpaprMachineState *spapr = (SpaprMachineState *)opaque;
2043fea35ca4SAlexey Kardashevskiy
2044fea35ca4SAlexey Kardashevskiy g_free(spapr->fdt_blob);
2045fea35ca4SAlexey Kardashevskiy spapr->fdt_blob = NULL;
2046fea35ca4SAlexey Kardashevskiy spapr->fdt_size = 0;
2047fea35ca4SAlexey Kardashevskiy
2048fea35ca4SAlexey Kardashevskiy return 0;
2049fea35ca4SAlexey Kardashevskiy }
2050fea35ca4SAlexey Kardashevskiy
2051fea35ca4SAlexey Kardashevskiy static const VMStateDescription vmstate_spapr_dtb = {
2052fea35ca4SAlexey Kardashevskiy .name = "spapr_dtb",
2053fea35ca4SAlexey Kardashevskiy .version_id = 1,
2054fea35ca4SAlexey Kardashevskiy .minimum_version_id = 1,
2055fea35ca4SAlexey Kardashevskiy .needed = spapr_dtb_needed,
2056fea35ca4SAlexey Kardashevskiy .pre_load = spapr_dtb_pre_load,
2057078ddbc9SRichard Henderson .fields = (const VMStateField[]) {
2058ce2918cbSDavid Gibson VMSTATE_UINT32(fdt_initial_size, SpaprMachineState),
2059ce2918cbSDavid Gibson VMSTATE_UINT32(fdt_size, SpaprMachineState),
2060ce2918cbSDavid Gibson VMSTATE_VBUFFER_ALLOC_UINT32(fdt_blob, SpaprMachineState, 0, NULL,
2061fea35ca4SAlexey Kardashevskiy fdt_size),
2062fea35ca4SAlexey Kardashevskiy VMSTATE_END_OF_LIST()
2063fea35ca4SAlexey Kardashevskiy },
2064fea35ca4SAlexey Kardashevskiy };
2065fea35ca4SAlexey Kardashevskiy
spapr_fwnmi_needed(void * opaque)20662500fb42SAravinda Prasad static bool spapr_fwnmi_needed(void *opaque)
20672500fb42SAravinda Prasad {
20682500fb42SAravinda Prasad SpaprMachineState *spapr = (SpaprMachineState *)opaque;
20692500fb42SAravinda Prasad
20708af7e1feSNicholas Piggin return spapr->fwnmi_machine_check_addr != -1;
20712500fb42SAravinda Prasad }
20722500fb42SAravinda Prasad
spapr_fwnmi_pre_save(void * opaque)20732500fb42SAravinda Prasad static int spapr_fwnmi_pre_save(void *opaque)
20742500fb42SAravinda Prasad {
20752500fb42SAravinda Prasad SpaprMachineState *spapr = (SpaprMachineState *)opaque;
20762500fb42SAravinda Prasad
20772500fb42SAravinda Prasad /*
20782500fb42SAravinda Prasad * Check if machine check handling is in progress and print a
20792500fb42SAravinda Prasad * warning message.
20802500fb42SAravinda Prasad */
20818af7e1feSNicholas Piggin if (spapr->fwnmi_machine_check_interlock != -1) {
20822500fb42SAravinda Prasad warn_report("A machine check is being handled during migration. The"
20832500fb42SAravinda Prasad "handler may run and log hardware error on the destination");
20842500fb42SAravinda Prasad }
20852500fb42SAravinda Prasad
20862500fb42SAravinda Prasad return 0;
20872500fb42SAravinda Prasad }
20882500fb42SAravinda Prasad
20898af7e1feSNicholas Piggin static const VMStateDescription vmstate_spapr_fwnmi = {
20908af7e1feSNicholas Piggin .name = "spapr_fwnmi",
20912500fb42SAravinda Prasad .version_id = 1,
20922500fb42SAravinda Prasad .minimum_version_id = 1,
20932500fb42SAravinda Prasad .needed = spapr_fwnmi_needed,
20942500fb42SAravinda Prasad .pre_save = spapr_fwnmi_pre_save,
2095078ddbc9SRichard Henderson .fields = (const VMStateField[]) {
2096edfdbf9cSNicholas Piggin VMSTATE_UINT64(fwnmi_system_reset_addr, SpaprMachineState),
20978af7e1feSNicholas Piggin VMSTATE_UINT64(fwnmi_machine_check_addr, SpaprMachineState),
20988af7e1feSNicholas Piggin VMSTATE_INT32(fwnmi_machine_check_interlock, SpaprMachineState),
20992500fb42SAravinda Prasad VMSTATE_END_OF_LIST()
21002500fb42SAravinda Prasad },
21012500fb42SAravinda Prasad };
21022500fb42SAravinda Prasad
21034be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = {
21044be21d56SDavid Gibson .name = "spapr",
2105880ae7deSDavid Gibson .version_id = 3,
21064be21d56SDavid Gibson .minimum_version_id = 1,
21074e5fe368SSuraj Jitindar Singh .pre_load = spapr_pre_load,
2108880ae7deSDavid Gibson .post_load = spapr_post_load,
21094e5fe368SSuraj Jitindar Singh .pre_save = spapr_pre_save,
2110078ddbc9SRichard Henderson .fields = (const VMStateField[]) {
2111880ae7deSDavid Gibson /* used to be @next_irq */
2112880ae7deSDavid Gibson VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4),
21134be21d56SDavid Gibson
21144be21d56SDavid Gibson /* RTC offset */
2115ce2918cbSDavid Gibson VMSTATE_UINT64_TEST(rtc_offset, SpaprMachineState, version_before_3),
2116880ae7deSDavid Gibson
2117ce2918cbSDavid Gibson VMSTATE_PPC_TIMEBASE_V(tb, SpaprMachineState, 2),
21184be21d56SDavid Gibson VMSTATE_END_OF_LIST()
21194be21d56SDavid Gibson },
2120078ddbc9SRichard Henderson .subsections = (const VMStateDescription * const []) {
212162ef3760SMichael Roth &vmstate_spapr_ov5_cas,
21229861bb3eSSuraj Jitindar Singh &vmstate_spapr_patb_entry,
2123fd38804bSDaniel Henrique Barboza &vmstate_spapr_pending_events,
21244e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_htm,
21254e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_vsx,
21264e5fe368SSuraj Jitindar Singh &vmstate_spapr_cap_dfp,
21278f38eaf8SSuraj Jitindar Singh &vmstate_spapr_cap_cfpc,
212809114fd8SSuraj Jitindar Singh &vmstate_spapr_cap_sbbc,
21294be8d4e7SSuraj Jitindar Singh &vmstate_spapr_cap_ibs,
213064d4a534SDavid Gibson &vmstate_spapr_cap_hpt_maxpagesize,
213182cffa2eSCédric Le Goater &vmstate_spapr_irq_map,
2132b9a477b7SSuraj Jitindar Singh &vmstate_spapr_cap_nested_kvm_hv,
2133fea35ca4SAlexey Kardashevskiy &vmstate_spapr_dtb,
2134c982f5cfSSuraj Jitindar Singh &vmstate_spapr_cap_large_decr,
21358ff43ee4SSuraj Jitindar Singh &vmstate_spapr_cap_ccf_assist,
21369d953ce4SAravinda Prasad &vmstate_spapr_cap_fwnmi,
21378af7e1feSNicholas Piggin &vmstate_spapr_fwnmi,
213882123b75SBharata B Rao &vmstate_spapr_cap_rpt_invalidate,
21391a7a31aeSNicholas Piggin &vmstate_spapr_cap_ail_mode_3,
2140e1617b84SHarsh Prateek Bora &vmstate_spapr_cap_nested_papr,
214162ef3760SMichael Roth NULL
214262ef3760SMichael Roth }
21434be21d56SDavid Gibson };
21444be21d56SDavid Gibson
htab_save_setup(QEMUFile * f,void * opaque,Error ** errp)214501c3ac68SCédric Le Goater static int htab_save_setup(QEMUFile *f, void *opaque, Error **errp)
21464be21d56SDavid Gibson {
2147ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque;
21484be21d56SDavid Gibson
21494be21d56SDavid Gibson /* "Iteration" header */
21503a384297SBharata B Rao if (!spapr->htab_shift) {
21513a384297SBharata B Rao qemu_put_be32(f, -1);
21523a384297SBharata B Rao } else {
21534be21d56SDavid Gibson qemu_put_be32(f, spapr->htab_shift);
21543a384297SBharata B Rao }
21554be21d56SDavid Gibson
2156e68cb8b4SAlexey Kardashevskiy if (spapr->htab) {
2157e68cb8b4SAlexey Kardashevskiy spapr->htab_save_index = 0;
2158e68cb8b4SAlexey Kardashevskiy spapr->htab_first_pass = true;
2159e68cb8b4SAlexey Kardashevskiy } else {
21603a384297SBharata B Rao if (spapr->htab_shift) {
2161e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled());
21624be21d56SDavid Gibson }
21633a384297SBharata B Rao }
21644be21d56SDavid Gibson
2165e68cb8b4SAlexey Kardashevskiy
2166e68cb8b4SAlexey Kardashevskiy return 0;
2167e68cb8b4SAlexey Kardashevskiy }
21684be21d56SDavid Gibson
htab_save_chunk(QEMUFile * f,SpaprMachineState * spapr,int chunkstart,int n_valid,int n_invalid)2169ce2918cbSDavid Gibson static void htab_save_chunk(QEMUFile *f, SpaprMachineState *spapr,
2170332f7721SGreg Kurz int chunkstart, int n_valid, int n_invalid)
2171332f7721SGreg Kurz {
2172332f7721SGreg Kurz qemu_put_be32(f, chunkstart);
2173332f7721SGreg Kurz qemu_put_be16(f, n_valid);
2174332f7721SGreg Kurz qemu_put_be16(f, n_invalid);
2175332f7721SGreg Kurz qemu_put_buffer(f, HPTE(spapr->htab, chunkstart),
2176332f7721SGreg Kurz HASH_PTE_SIZE_64 * n_valid);
2177332f7721SGreg Kurz }
2178332f7721SGreg Kurz
htab_save_end_marker(QEMUFile * f)2179332f7721SGreg Kurz static void htab_save_end_marker(QEMUFile *f)
2180332f7721SGreg Kurz {
2181332f7721SGreg Kurz qemu_put_be32(f, 0);
2182332f7721SGreg Kurz qemu_put_be16(f, 0);
2183332f7721SGreg Kurz qemu_put_be16(f, 0);
2184332f7721SGreg Kurz }
2185332f7721SGreg Kurz
htab_save_first_pass(QEMUFile * f,SpaprMachineState * spapr,int64_t max_ns)2186ce2918cbSDavid Gibson static void htab_save_first_pass(QEMUFile *f, SpaprMachineState *spapr,
21874be21d56SDavid Gibson int64_t max_ns)
21884be21d56SDavid Gibson {
2189378bc217SDavid Gibson bool has_timeout = max_ns != -1;
21904be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64;
21914be21d56SDavid Gibson int index = spapr->htab_save_index;
2192bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
21934be21d56SDavid Gibson
21944be21d56SDavid Gibson assert(spapr->htab_first_pass);
21954be21d56SDavid Gibson
21964be21d56SDavid Gibson do {
21974be21d56SDavid Gibson int chunkstart;
21984be21d56SDavid Gibson
21994be21d56SDavid Gibson /* Consume invalid HPTEs */
22004be21d56SDavid Gibson while ((index < htabslots)
22014be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) {
22024be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index));
220324ec2863SMarc-André Lureau index++;
22044be21d56SDavid Gibson }
22054be21d56SDavid Gibson
22064be21d56SDavid Gibson /* Consume valid HPTEs */
22074be21d56SDavid Gibson chunkstart = index;
2208338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX)
22094be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) {
22104be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index));
221124ec2863SMarc-André Lureau index++;
22124be21d56SDavid Gibson }
22134be21d56SDavid Gibson
22144be21d56SDavid Gibson if (index > chunkstart) {
22154be21d56SDavid Gibson int n_valid = index - chunkstart;
22164be21d56SDavid Gibson
2217332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, 0);
22184be21d56SDavid Gibson
2219378bc217SDavid Gibson if (has_timeout &&
2220378bc217SDavid Gibson (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) {
22214be21d56SDavid Gibson break;
22224be21d56SDavid Gibson }
22234be21d56SDavid Gibson }
2224e1fde0e0SJuan Quintela } while ((index < htabslots) && !migration_rate_exceeded(f));
22254be21d56SDavid Gibson
22264be21d56SDavid Gibson if (index >= htabslots) {
22274be21d56SDavid Gibson assert(index == htabslots);
22284be21d56SDavid Gibson index = 0;
22294be21d56SDavid Gibson spapr->htab_first_pass = false;
22304be21d56SDavid Gibson }
22314be21d56SDavid Gibson spapr->htab_save_index = index;
22324be21d56SDavid Gibson }
22334be21d56SDavid Gibson
htab_save_later_pass(QEMUFile * f,SpaprMachineState * spapr,int64_t max_ns)2234ce2918cbSDavid Gibson static int htab_save_later_pass(QEMUFile *f, SpaprMachineState *spapr,
22354be21d56SDavid Gibson int64_t max_ns)
22364be21d56SDavid Gibson {
22374be21d56SDavid Gibson bool final = max_ns < 0;
22384be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64;
22394be21d56SDavid Gibson int examined = 0, sent = 0;
22404be21d56SDavid Gibson int index = spapr->htab_save_index;
2241bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
22424be21d56SDavid Gibson
22434be21d56SDavid Gibson assert(!spapr->htab_first_pass);
22444be21d56SDavid Gibson
22454be21d56SDavid Gibson do {
22464be21d56SDavid Gibson int chunkstart, invalidstart;
22474be21d56SDavid Gibson
22484be21d56SDavid Gibson /* Consume non-dirty HPTEs */
22494be21d56SDavid Gibson while ((index < htabslots)
22504be21d56SDavid Gibson && !HPTE_DIRTY(HPTE(spapr->htab, index))) {
22514be21d56SDavid Gibson index++;
22524be21d56SDavid Gibson examined++;
22534be21d56SDavid Gibson }
22544be21d56SDavid Gibson
22554be21d56SDavid Gibson chunkstart = index;
22564be21d56SDavid Gibson /* Consume valid dirty HPTEs */
2257338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX)
22584be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index))
22594be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) {
22604be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index));
22614be21d56SDavid Gibson index++;
22624be21d56SDavid Gibson examined++;
22634be21d56SDavid Gibson }
22644be21d56SDavid Gibson
22654be21d56SDavid Gibson invalidstart = index;
22664be21d56SDavid Gibson /* Consume invalid dirty HPTEs */
2267338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - invalidstart < USHRT_MAX)
22684be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index))
22694be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) {
22704be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index));
22714be21d56SDavid Gibson index++;
22724be21d56SDavid Gibson examined++;
22734be21d56SDavid Gibson }
22744be21d56SDavid Gibson
22754be21d56SDavid Gibson if (index > chunkstart) {
22764be21d56SDavid Gibson int n_valid = invalidstart - chunkstart;
22774be21d56SDavid Gibson int n_invalid = index - invalidstart;
22784be21d56SDavid Gibson
2279332f7721SGreg Kurz htab_save_chunk(f, spapr, chunkstart, n_valid, n_invalid);
22804be21d56SDavid Gibson sent += index - chunkstart;
22814be21d56SDavid Gibson
2282bc72ad67SAlex Bligh if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) {
22834be21d56SDavid Gibson break;
22844be21d56SDavid Gibson }
22854be21d56SDavid Gibson }
22864be21d56SDavid Gibson
22874be21d56SDavid Gibson if (examined >= htabslots) {
22884be21d56SDavid Gibson break;
22894be21d56SDavid Gibson }
22904be21d56SDavid Gibson
22914be21d56SDavid Gibson if (index >= htabslots) {
22924be21d56SDavid Gibson assert(index == htabslots);
22934be21d56SDavid Gibson index = 0;
22944be21d56SDavid Gibson }
2295e1fde0e0SJuan Quintela } while ((examined < htabslots) && (!migration_rate_exceeded(f) || final));
22964be21d56SDavid Gibson
22974be21d56SDavid Gibson if (index >= htabslots) {
22984be21d56SDavid Gibson assert(index == htabslots);
22994be21d56SDavid Gibson index = 0;
23004be21d56SDavid Gibson }
23014be21d56SDavid Gibson
23024be21d56SDavid Gibson spapr->htab_save_index = index;
23034be21d56SDavid Gibson
2304e68cb8b4SAlexey Kardashevskiy return (examined >= htabslots) && (sent == 0) ? 1 : 0;
23054be21d56SDavid Gibson }
23064be21d56SDavid Gibson
2307e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS 5000000 /* 5 ms */
2308e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE 2048
2309e68cb8b4SAlexey Kardashevskiy
htab_save_iterate(QEMUFile * f,void * opaque)23104be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque)
23114be21d56SDavid Gibson {
2312ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque;
2313715c5407SDavid Gibson int fd;
2314e68cb8b4SAlexey Kardashevskiy int rc = 0;
23154be21d56SDavid Gibson
23164be21d56SDavid Gibson /* Iteration header */
23173a384297SBharata B Rao if (!spapr->htab_shift) {
23183a384297SBharata B Rao qemu_put_be32(f, -1);
2319e8cd4247SLaurent Vivier return 1;
23203a384297SBharata B Rao } else {
23214be21d56SDavid Gibson qemu_put_be32(f, 0);
23223a384297SBharata B Rao }
23234be21d56SDavid Gibson
2324e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) {
2325e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled());
2326e68cb8b4SAlexey Kardashevskiy
2327715c5407SDavid Gibson fd = get_htab_fd(spapr);
2328715c5407SDavid Gibson if (fd < 0) {
2329715c5407SDavid Gibson return fd;
233001a57972SSamuel Mendoza-Jonas }
233101a57972SSamuel Mendoza-Jonas
2332715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS);
2333e68cb8b4SAlexey Kardashevskiy if (rc < 0) {
2334e68cb8b4SAlexey Kardashevskiy return rc;
2335e68cb8b4SAlexey Kardashevskiy }
2336e68cb8b4SAlexey Kardashevskiy } else if (spapr->htab_first_pass) {
23374be21d56SDavid Gibson htab_save_first_pass(f, spapr, MAX_ITERATION_NS);
23384be21d56SDavid Gibson } else {
2339e68cb8b4SAlexey Kardashevskiy rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS);
23404be21d56SDavid Gibson }
23414be21d56SDavid Gibson
2342332f7721SGreg Kurz htab_save_end_marker(f);
23434be21d56SDavid Gibson
2344e68cb8b4SAlexey Kardashevskiy return rc;
23454be21d56SDavid Gibson }
23464be21d56SDavid Gibson
htab_save_complete(QEMUFile * f,void * opaque)23474be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque)
23484be21d56SDavid Gibson {
2349ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque;
2350715c5407SDavid Gibson int fd;
23514be21d56SDavid Gibson
23524be21d56SDavid Gibson /* Iteration header */
23533a384297SBharata B Rao if (!spapr->htab_shift) {
23543a384297SBharata B Rao qemu_put_be32(f, -1);
23553a384297SBharata B Rao return 0;
23563a384297SBharata B Rao } else {
23574be21d56SDavid Gibson qemu_put_be32(f, 0);
23583a384297SBharata B Rao }
23594be21d56SDavid Gibson
2360e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) {
2361e68cb8b4SAlexey Kardashevskiy int rc;
2362e68cb8b4SAlexey Kardashevskiy
2363e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled());
2364e68cb8b4SAlexey Kardashevskiy
2365715c5407SDavid Gibson fd = get_htab_fd(spapr);
2366715c5407SDavid Gibson if (fd < 0) {
2367715c5407SDavid Gibson return fd;
236801a57972SSamuel Mendoza-Jonas }
236901a57972SSamuel Mendoza-Jonas
2370715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1);
2371e68cb8b4SAlexey Kardashevskiy if (rc < 0) {
2372e68cb8b4SAlexey Kardashevskiy return rc;
2373e68cb8b4SAlexey Kardashevskiy }
2374e68cb8b4SAlexey Kardashevskiy } else {
2375378bc217SDavid Gibson if (spapr->htab_first_pass) {
2376378bc217SDavid Gibson htab_save_first_pass(f, spapr, -1);
2377378bc217SDavid Gibson }
23784be21d56SDavid Gibson htab_save_later_pass(f, spapr, -1);
2379e68cb8b4SAlexey Kardashevskiy }
23804be21d56SDavid Gibson
23814be21d56SDavid Gibson /* End marker */
2382332f7721SGreg Kurz htab_save_end_marker(f);
23834be21d56SDavid Gibson
23844be21d56SDavid Gibson return 0;
23854be21d56SDavid Gibson }
23864be21d56SDavid Gibson
htab_load(QEMUFile * f,void * opaque,int version_id)23874be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id)
23884be21d56SDavid Gibson {
2389ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque;
23904be21d56SDavid Gibson uint32_t section_hdr;
2391e68cb8b4SAlexey Kardashevskiy int fd = -1;
239214b0d748SGreg Kurz Error *local_err = NULL;
23934be21d56SDavid Gibson
23944be21d56SDavid Gibson if (version_id < 1 || version_id > 1) {
239598a5d100SDavid Gibson error_report("htab_load() bad version");
23964be21d56SDavid Gibson return -EINVAL;
23974be21d56SDavid Gibson }
23984be21d56SDavid Gibson
23994be21d56SDavid Gibson section_hdr = qemu_get_be32(f);
24004be21d56SDavid Gibson
24013a384297SBharata B Rao if (section_hdr == -1) {
24023a384297SBharata B Rao spapr_free_hpt(spapr);
24033a384297SBharata B Rao return 0;
24043a384297SBharata B Rao }
24053a384297SBharata B Rao
24064be21d56SDavid Gibson if (section_hdr) {
2407a4e3a7c0SGreg Kurz int ret;
2408a4e3a7c0SGreg Kurz
2409c5f54f3eSDavid Gibson /* First section gives the htab size */
2410a4e3a7c0SGreg Kurz ret = spapr_reallocate_hpt(spapr, section_hdr, &local_err);
2411a4e3a7c0SGreg Kurz if (ret < 0) {
2412c5f54f3eSDavid Gibson error_report_err(local_err);
2413a4e3a7c0SGreg Kurz return ret;
24144be21d56SDavid Gibson }
24154be21d56SDavid Gibson return 0;
24164be21d56SDavid Gibson }
24174be21d56SDavid Gibson
2418e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) {
2419e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled());
2420e68cb8b4SAlexey Kardashevskiy
242114b0d748SGreg Kurz fd = kvmppc_get_htab_fd(true, 0, &local_err);
2422e68cb8b4SAlexey Kardashevskiy if (fd < 0) {
242314b0d748SGreg Kurz error_report_err(local_err);
242482be8e73SGreg Kurz return fd;
2425e68cb8b4SAlexey Kardashevskiy }
2426e68cb8b4SAlexey Kardashevskiy }
2427e68cb8b4SAlexey Kardashevskiy
24284be21d56SDavid Gibson while (true) {
24294be21d56SDavid Gibson uint32_t index;
24304be21d56SDavid Gibson uint16_t n_valid, n_invalid;
24314be21d56SDavid Gibson
24324be21d56SDavid Gibson index = qemu_get_be32(f);
24334be21d56SDavid Gibson n_valid = qemu_get_be16(f);
24344be21d56SDavid Gibson n_invalid = qemu_get_be16(f);
24354be21d56SDavid Gibson
24364be21d56SDavid Gibson if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) {
24374be21d56SDavid Gibson /* End of Stream */
24384be21d56SDavid Gibson break;
24394be21d56SDavid Gibson }
24404be21d56SDavid Gibson
2441e68cb8b4SAlexey Kardashevskiy if ((index + n_valid + n_invalid) >
24424be21d56SDavid Gibson (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) {
24434be21d56SDavid Gibson /* Bad index in stream */
244498a5d100SDavid Gibson error_report(
244598a5d100SDavid Gibson "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)",
244698a5d100SDavid Gibson index, n_valid, n_invalid, spapr->htab_shift);
24474be21d56SDavid Gibson return -EINVAL;
24484be21d56SDavid Gibson }
24494be21d56SDavid Gibson
2450e68cb8b4SAlexey Kardashevskiy if (spapr->htab) {
24514be21d56SDavid Gibson if (n_valid) {
24524be21d56SDavid Gibson qemu_get_buffer(f, HPTE(spapr->htab, index),
24534be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid);
24544be21d56SDavid Gibson }
24554be21d56SDavid Gibson if (n_invalid) {
24564be21d56SDavid Gibson memset(HPTE(spapr->htab, index + n_valid), 0,
24574be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_invalid);
24584be21d56SDavid Gibson }
2459e68cb8b4SAlexey Kardashevskiy } else {
2460e68cb8b4SAlexey Kardashevskiy int rc;
2461e68cb8b4SAlexey Kardashevskiy
2462e68cb8b4SAlexey Kardashevskiy assert(fd >= 0);
2463e68cb8b4SAlexey Kardashevskiy
24640a06e4d6SGreg Kurz rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid,
24650a06e4d6SGreg Kurz &local_err);
2466e68cb8b4SAlexey Kardashevskiy if (rc < 0) {
24670a06e4d6SGreg Kurz error_report_err(local_err);
2468e68cb8b4SAlexey Kardashevskiy return rc;
2469e68cb8b4SAlexey Kardashevskiy }
2470e68cb8b4SAlexey Kardashevskiy }
2471e68cb8b4SAlexey Kardashevskiy }
2472e68cb8b4SAlexey Kardashevskiy
2473e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) {
2474e68cb8b4SAlexey Kardashevskiy assert(fd >= 0);
2475e68cb8b4SAlexey Kardashevskiy close(fd);
24764be21d56SDavid Gibson }
24774be21d56SDavid Gibson
24784be21d56SDavid Gibson return 0;
24794be21d56SDavid Gibson }
24804be21d56SDavid Gibson
htab_save_cleanup(void * opaque)248170f794fcSJuan Quintela static void htab_save_cleanup(void *opaque)
2482c573fc03SThomas Huth {
2483ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque;
2484c573fc03SThomas Huth
2485c573fc03SThomas Huth close_htab_fd(spapr);
2486c573fc03SThomas Huth }
2487c573fc03SThomas Huth
24884be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = {
24899907e842SJuan Quintela .save_setup = htab_save_setup,
24904be21d56SDavid Gibson .save_live_iterate = htab_save_iterate,
2491a3e06c3dSDr. David Alan Gilbert .save_live_complete_precopy = htab_save_complete,
249270f794fcSJuan Quintela .save_cleanup = htab_save_cleanup,
24934be21d56SDavid Gibson .load_state = htab_load,
24944be21d56SDavid Gibson };
24954be21d56SDavid Gibson
spapr_boot_set(void * opaque,const char * boot_device,Error ** errp)24965b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device,
24975b2128d2SAlexander Graf Error **errp)
24985b2128d2SAlexander Graf {
24993bf0844fSGreg Kurz SpaprMachineState *spapr = SPAPR_MACHINE(opaque);
25003bf0844fSGreg Kurz
25013bf0844fSGreg Kurz g_free(spapr->boot_device);
25023bf0844fSGreg Kurz spapr->boot_device = g_strdup(boot_device);
25035b2128d2SAlexander Graf }
25045b2128d2SAlexander Graf
spapr_create_lmb_dr_connectors(SpaprMachineState * spapr)2505ce2918cbSDavid Gibson static void spapr_create_lmb_dr_connectors(SpaprMachineState *spapr)
2506224245bfSDavid Gibson {
2507224245bfSDavid Gibson MachineState *machine = MACHINE(spapr);
2508224245bfSDavid Gibson uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
2509e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size;
2510224245bfSDavid Gibson int i;
2511224245bfSDavid Gibson
2512c0ce7b4aSDavid Hildenbrand g_assert(!nr_lmbs || machine->device_memory);
2513224245bfSDavid Gibson for (i = 0; i < nr_lmbs; i++) {
2514224245bfSDavid Gibson uint64_t addr;
2515224245bfSDavid Gibson
2516b0c14ec4SDavid Hildenbrand addr = i * lmb_size + machine->device_memory->base;
25176caf3ac6SDavid Gibson spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_LMB,
2518224245bfSDavid Gibson addr / lmb_size);
2519224245bfSDavid Gibson }
2520224245bfSDavid Gibson }
2521224245bfSDavid Gibson
2522224245bfSDavid Gibson /*
2523224245bfSDavid Gibson * If RAM size, maxmem size and individual node mem sizes aren't aligned
2524224245bfSDavid Gibson * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest
2525224245bfSDavid Gibson * since we can't support such unaligned sizes with DRCONF_MEMORY.
2526224245bfSDavid Gibson */
spapr_validate_node_memory(MachineState * machine,Error ** errp)25277c150d6fSDavid Gibson static void spapr_validate_node_memory(MachineState *machine, Error **errp)
2528224245bfSDavid Gibson {
2529224245bfSDavid Gibson int i;
2530224245bfSDavid Gibson
25317c150d6fSDavid Gibson if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) {
25327c150d6fSDavid Gibson error_setg(errp, "Memory size 0x" RAM_ADDR_FMT
2533ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB",
25347c150d6fSDavid Gibson machine->ram_size,
2535d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB);
25367c150d6fSDavid Gibson return;
25377c150d6fSDavid Gibson }
25387c150d6fSDavid Gibson
25397c150d6fSDavid Gibson if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) {
25407c150d6fSDavid Gibson error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT
2541ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB",
25427c150d6fSDavid Gibson machine->ram_size,
2543d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB);
25447c150d6fSDavid Gibson return;
2545224245bfSDavid Gibson }
2546224245bfSDavid Gibson
2547aa570207STao Xu for (i = 0; i < machine->numa_state->num_nodes; i++) {
25487e721e7bSTao Xu if (machine->numa_state->nodes[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) {
25497c150d6fSDavid Gibson error_setg(errp,
25507c150d6fSDavid Gibson "Node %d memory size 0x%" PRIx64
2551ab3dd749SPhilippe Mathieu-Daudé " is not aligned to %" PRIu64 " MiB",
25527e721e7bSTao Xu i, machine->numa_state->nodes[i].node_mem,
2553d23b6caaSPhilippe Mathieu-Daudé SPAPR_MEMORY_BLOCK_SIZE / MiB);
25547c150d6fSDavid Gibson return;
2555224245bfSDavid Gibson }
2556224245bfSDavid Gibson }
2557224245bfSDavid Gibson }
2558224245bfSDavid Gibson
2559535455fdSIgor Mammedov /* find cpu slot in machine->possible_cpus by core_id */
spapr_find_cpu_slot(MachineState * ms,uint32_t id,int * idx)2560535455fdSIgor Mammedov static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx)
2561535455fdSIgor Mammedov {
2562fe6b6346SLike Xu int index = id / ms->smp.threads;
2563535455fdSIgor Mammedov
2564535455fdSIgor Mammedov if (index >= ms->possible_cpus->len) {
2565535455fdSIgor Mammedov return NULL;
2566535455fdSIgor Mammedov }
2567535455fdSIgor Mammedov if (idx) {
2568535455fdSIgor Mammedov *idx = index;
2569535455fdSIgor Mammedov }
2570535455fdSIgor Mammedov return &ms->possible_cpus->cpus[index];
2571535455fdSIgor Mammedov }
2572535455fdSIgor Mammedov
spapr_set_vsmt_mode(SpaprMachineState * spapr,Error ** errp)2573ce2918cbSDavid Gibson static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp)
2574fa98fbfcSSam Bobroff {
2575fe6b6346SLike Xu MachineState *ms = MACHINE(spapr);
257629cb4187SGreg Kurz SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
2577fa98fbfcSSam Bobroff Error *local_err = NULL;
2578fa98fbfcSSam Bobroff bool vsmt_user = !!spapr->vsmt;
2579fa98fbfcSSam Bobroff int kvm_smt = kvmppc_smt_threads();
2580fa98fbfcSSam Bobroff int ret;
2581fe6b6346SLike Xu unsigned int smp_threads = ms->smp.threads;
2582fa98fbfcSSam Bobroff
2583dc5e0721SNicholas Piggin if (tcg_enabled()) {
2584dc5e0721SNicholas Piggin if (smp_threads > 1 &&
2585dc5e0721SNicholas Piggin !ppc_type_check_compat(ms->cpu_type, CPU_POWERPC_LOGICAL_2_07, 0,
2586dc5e0721SNicholas Piggin spapr->max_compat_pvr)) {
2587dc5e0721SNicholas Piggin error_setg(errp, "TCG only supports SMT on POWER8 or newer CPUs");
2588dc5e0721SNicholas Piggin return;
2589dc5e0721SNicholas Piggin }
2590dc5e0721SNicholas Piggin
2591dc5e0721SNicholas Piggin if (smp_threads > 8) {
2592dc5e0721SNicholas Piggin error_setg(errp, "TCG cannot support more than 8 threads/core "
2593fa98fbfcSSam Bobroff "on a pseries machine");
2594dcfe4805SMarkus Armbruster return;
2595fa98fbfcSSam Bobroff }
2596dc5e0721SNicholas Piggin }
2597fa98fbfcSSam Bobroff if (!is_power_of_2(smp_threads)) {
2598dcfe4805SMarkus Armbruster error_setg(errp, "Cannot support %d threads/core on a pseries "
2599fa98fbfcSSam Bobroff "machine because it must be a power of 2", smp_threads);
2600dcfe4805SMarkus Armbruster return;
2601fa98fbfcSSam Bobroff }
2602fa98fbfcSSam Bobroff
2603e6a19a64SMichael Tokarev /* Determine the VSMT mode to use: */
2604fa98fbfcSSam Bobroff if (vsmt_user) {
2605fa98fbfcSSam Bobroff if (spapr->vsmt < smp_threads) {
2606dcfe4805SMarkus Armbruster error_setg(errp, "Cannot support VSMT mode %d"
2607fa98fbfcSSam Bobroff " because it must be >= threads/core (%d)",
2608fa98fbfcSSam Bobroff spapr->vsmt, smp_threads);
2609dcfe4805SMarkus Armbruster return;
2610fa98fbfcSSam Bobroff }
2611fa98fbfcSSam Bobroff /* In this case, spapr->vsmt has been set by the command line */
261229cb4187SGreg Kurz } else if (!smc->smp_threads_vsmt) {
26138904e5a7SDavid Gibson /*
26148904e5a7SDavid Gibson * Default VSMT value is tricky, because we need it to be as
26158904e5a7SDavid Gibson * consistent as possible (for migration), but this requires
26168904e5a7SDavid Gibson * changing it for at least some existing cases. We pick 8 as
26178904e5a7SDavid Gibson * the value that we'd get with KVM on POWER8, the
26188904e5a7SDavid Gibson * overwhelmingly common case in production systems.
26198904e5a7SDavid Gibson */
26204ad64cbdSLaurent Vivier spapr->vsmt = MAX(8, smp_threads);
262129cb4187SGreg Kurz } else {
262229cb4187SGreg Kurz spapr->vsmt = smp_threads;
2623fa98fbfcSSam Bobroff }
2624fa98fbfcSSam Bobroff
2625fa98fbfcSSam Bobroff /* KVM: If necessary, set the SMT mode: */
2626fa98fbfcSSam Bobroff if (kvm_enabled() && (spapr->vsmt != kvm_smt)) {
2627fa98fbfcSSam Bobroff ret = kvmppc_set_smt_threads(spapr->vsmt);
2628fa98fbfcSSam Bobroff if (ret) {
26291f20f2e0SDavid Gibson /* Looks like KVM isn't able to change VSMT mode */
2630fa98fbfcSSam Bobroff error_setg(&local_err,
2631fa98fbfcSSam Bobroff "Failed to set KVM's VSMT mode to %d (errno %d)",
2632fa98fbfcSSam Bobroff spapr->vsmt, ret);
26331f20f2e0SDavid Gibson /* We can live with that if the default one is big enough
26341f20f2e0SDavid Gibson * for the number of threads, and a submultiple of the one
26351f20f2e0SDavid Gibson * we want. In this case we'll waste some vcpu ids, but
26361f20f2e0SDavid Gibson * behaviour will be correct */
26371f20f2e0SDavid Gibson if ((kvm_smt >= smp_threads) && ((spapr->vsmt % kvm_smt) == 0)) {
26381f20f2e0SDavid Gibson warn_report_err(local_err);
26391f20f2e0SDavid Gibson } else {
2640fa98fbfcSSam Bobroff if (!vsmt_user) {
26411f20f2e0SDavid Gibson error_append_hint(&local_err,
26421f20f2e0SDavid Gibson "On PPC, a VM with %d threads/core"
26431f20f2e0SDavid Gibson " on a host with %d threads/core"
26441f20f2e0SDavid Gibson " requires the use of VSMT mode %d.\n",
2645fa98fbfcSSam Bobroff smp_threads, kvm_smt, spapr->vsmt);
2646fa98fbfcSSam Bobroff }
2647cdcca22aSVladimir Sementsov-Ogievskiy kvmppc_error_append_smt_possible_hint(&local_err);
2648dcfe4805SMarkus Armbruster error_propagate(errp, local_err);
2649fa98fbfcSSam Bobroff }
2650fa98fbfcSSam Bobroff }
26511f20f2e0SDavid Gibson }
2652fa98fbfcSSam Bobroff /* else TCG: nothing to do currently */
2653fa98fbfcSSam Bobroff }
2654fa98fbfcSSam Bobroff
spapr_init_cpus(SpaprMachineState * spapr)2655ce2918cbSDavid Gibson static void spapr_init_cpus(SpaprMachineState *spapr)
26561a5008fcSGreg Kurz {
26571a5008fcSGreg Kurz MachineState *machine = MACHINE(spapr);
26581a5008fcSGreg Kurz MachineClass *mc = MACHINE_GET_CLASS(machine);
26591a5008fcSGreg Kurz const char *type = spapr_get_cpu_core_type(machine->cpu_type);
26601a5008fcSGreg Kurz const CPUArchIdList *possible_cpus;
2661fe6b6346SLike Xu unsigned int smp_cpus = machine->smp.cpus;
2662fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads;
2663fe6b6346SLike Xu unsigned int max_cpus = machine->smp.max_cpus;
26641a5008fcSGreg Kurz int boot_cores_nr = smp_cpus / smp_threads;
26651a5008fcSGreg Kurz int i;
26661a5008fcSGreg Kurz
26671a5008fcSGreg Kurz possible_cpus = mc->possible_cpu_arch_ids(machine);
26681a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) {
26691a5008fcSGreg Kurz if (smp_cpus % smp_threads) {
26701a5008fcSGreg Kurz error_report("smp_cpus (%u) must be multiple of threads (%u)",
26711a5008fcSGreg Kurz smp_cpus, smp_threads);
26721a5008fcSGreg Kurz exit(1);
26731a5008fcSGreg Kurz }
26741a5008fcSGreg Kurz if (max_cpus % smp_threads) {
26751a5008fcSGreg Kurz error_report("max_cpus (%u) must be multiple of threads (%u)",
26761a5008fcSGreg Kurz max_cpus, smp_threads);
26771a5008fcSGreg Kurz exit(1);
26781a5008fcSGreg Kurz }
26791a5008fcSGreg Kurz } else {
26801a5008fcSGreg Kurz if (max_cpus != smp_cpus) {
26811a5008fcSGreg Kurz error_report("This machine version does not support CPU hotplug");
26821a5008fcSGreg Kurz exit(1);
26831a5008fcSGreg Kurz }
26841a5008fcSGreg Kurz boot_cores_nr = possible_cpus->len;
26851a5008fcSGreg Kurz }
26861a5008fcSGreg Kurz
26871a5008fcSGreg Kurz for (i = 0; i < possible_cpus->len; i++) {
26881a5008fcSGreg Kurz int core_id = i * smp_threads;
26891a5008fcSGreg Kurz
26901a5008fcSGreg Kurz if (mc->has_hotpluggable_cpus) {
26911a5008fcSGreg Kurz spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU,
26921a5008fcSGreg Kurz spapr_vcpu_id(spapr, core_id));
26931a5008fcSGreg Kurz }
26941a5008fcSGreg Kurz
26951a5008fcSGreg Kurz if (i < boot_cores_nr) {
26961a5008fcSGreg Kurz Object *core = object_new(type);
26971a5008fcSGreg Kurz int nr_threads = smp_threads;
26981a5008fcSGreg Kurz
26991a5008fcSGreg Kurz /* Handle the partially filled core for older machine types */
27001a5008fcSGreg Kurz if ((i + 1) * smp_threads >= smp_cpus) {
27011a5008fcSGreg Kurz nr_threads = smp_cpus - i * smp_threads;
27021a5008fcSGreg Kurz }
27031a5008fcSGreg Kurz
27045325cc34SMarkus Armbruster object_property_set_int(core, "nr-threads", nr_threads,
27051a5008fcSGreg Kurz &error_fatal);
27065325cc34SMarkus Armbruster object_property_set_int(core, CPU_CORE_PROP_CORE_ID, core_id,
27071a5008fcSGreg Kurz &error_fatal);
2708ce189ab2SMarkus Armbruster qdev_realize(DEVICE(core), NULL, &error_fatal);
2709ecda255eSSam Bobroff
2710ecda255eSSam Bobroff object_unref(core);
27111a5008fcSGreg Kurz }
27121a5008fcSGreg Kurz }
27131a5008fcSGreg Kurz }
27141a5008fcSGreg Kurz
spapr_create_default_phb(void)2715999c9cafSGreg Kurz static PCIHostState *spapr_create_default_phb(void)
2716999c9cafSGreg Kurz {
2717999c9cafSGreg Kurz DeviceState *dev;
2718999c9cafSGreg Kurz
27193e80f690SMarkus Armbruster dev = qdev_new(TYPE_SPAPR_PCI_HOST_BRIDGE);
2720999c9cafSGreg Kurz qdev_prop_set_uint32(dev, "index", 0);
27213c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
2722999c9cafSGreg Kurz
2723999c9cafSGreg Kurz return PCI_HOST_BRIDGE(dev);
2724999c9cafSGreg Kurz }
2725999c9cafSGreg Kurz
spapr_rma_size(SpaprMachineState * spapr,Error ** errp)2726425f0b7aSDavid Gibson static hwaddr spapr_rma_size(SpaprMachineState *spapr, Error **errp)
2727425f0b7aSDavid Gibson {
2728425f0b7aSDavid Gibson MachineState *machine = MACHINE(spapr);
2729425f0b7aSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
2730425f0b7aSDavid Gibson hwaddr rma_size = machine->ram_size;
2731425f0b7aSDavid Gibson hwaddr node0_size = spapr_node0_size(machine);
2732425f0b7aSDavid Gibson
2733425f0b7aSDavid Gibson /* RMA has to fit in the first NUMA node */
2734425f0b7aSDavid Gibson rma_size = MIN(rma_size, node0_size);
2735425f0b7aSDavid Gibson
2736425f0b7aSDavid Gibson /*
2737425f0b7aSDavid Gibson * VRMA access is via a special 1TiB SLB mapping, so the RMA can
2738425f0b7aSDavid Gibson * never exceed that
2739425f0b7aSDavid Gibson */
2740425f0b7aSDavid Gibson rma_size = MIN(rma_size, 1 * TiB);
2741425f0b7aSDavid Gibson
2742425f0b7aSDavid Gibson /*
2743425f0b7aSDavid Gibson * Clamp the RMA size based on machine type. This is for
2744425f0b7aSDavid Gibson * migration compatibility with older qemu versions, which limited
2745425f0b7aSDavid Gibson * the RMA size for complicated and mostly bad reasons.
2746425f0b7aSDavid Gibson */
2747425f0b7aSDavid Gibson if (smc->rma_limit) {
2748425f0b7aSDavid Gibson rma_size = MIN(rma_size, smc->rma_limit);
2749425f0b7aSDavid Gibson }
2750425f0b7aSDavid Gibson
2751425f0b7aSDavid Gibson if (rma_size < MIN_RMA_SLOF) {
2752425f0b7aSDavid Gibson error_setg(errp,
2753425f0b7aSDavid Gibson "pSeries SLOF firmware requires >= %" HWADDR_PRIx
2754425f0b7aSDavid Gibson "ldMiB guest RMA (Real Mode Area memory)",
2755425f0b7aSDavid Gibson MIN_RMA_SLOF / MiB);
2756425f0b7aSDavid Gibson return 0;
2757425f0b7aSDavid Gibson }
2758425f0b7aSDavid Gibson
2759425f0b7aSDavid Gibson return rma_size;
2760425f0b7aSDavid Gibson }
2761425f0b7aSDavid Gibson
spapr_create_nvdimm_dr_connectors(SpaprMachineState * spapr)2762ce316b51SGreg Kurz static void spapr_create_nvdimm_dr_connectors(SpaprMachineState *spapr)
2763ce316b51SGreg Kurz {
2764ce316b51SGreg Kurz MachineState *machine = MACHINE(spapr);
2765ce316b51SGreg Kurz int i;
2766ce316b51SGreg Kurz
2767ce316b51SGreg Kurz for (i = 0; i < machine->ram_slots; i++) {
2768ce316b51SGreg Kurz spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_PMEM, i);
2769ce316b51SGreg Kurz }
2770ce316b51SGreg Kurz }
2771ce316b51SGreg Kurz
277253018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */
spapr_machine_init(MachineState * machine)2773bcb5ce08SDavid Gibson static void spapr_machine_init(MachineState *machine)
277453018216SPaolo Bonzini {
2775ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(machine);
2776ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
2777ee3a71e3SShivaprasad G Bhat MachineClass *mc = MACHINE_GET_CLASS(machine);
2778fc8c745dSAlexey Kardashevskiy const char *bios_default = spapr->vof ? FW_FILE_NAME_VOF : FW_FILE_NAME;
2779fc8c745dSAlexey Kardashevskiy const char *bios_name = machine->firmware ?: bios_default;
27805f2b96b3SDaniel Henrique Barboza g_autofree char *filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
27813ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename;
27823ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename;
278353018216SPaolo Bonzini PCIHostState *phb;
2784f73eb948SPaolo Bonzini bool has_vga;
278553018216SPaolo Bonzini int i;
278653018216SPaolo Bonzini MemoryRegion *sysmem = get_system_memory();
2787b7d1f77aSBenjamin Herrenschmidt long load_limit, fw_size;
278830f4b05bSDavid Gibson Error *resize_hpt_err = NULL;
27890aff8161SDavid Woodhouse NICInfo *nd;
279053018216SPaolo Bonzini
27915f2b96b3SDaniel Henrique Barboza if (!filename) {
27925f2b96b3SDaniel Henrique Barboza error_report("Could not find LPAR firmware '%s'", bios_name);
27935f2b96b3SDaniel Henrique Barboza exit(1);
27945f2b96b3SDaniel Henrique Barboza }
27955f2b96b3SDaniel Henrique Barboza fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE);
27965f2b96b3SDaniel Henrique Barboza if (fw_size <= 0) {
27975f2b96b3SDaniel Henrique Barboza error_report("Could not load LPAR firmware '%s'", filename);
27985f2b96b3SDaniel Henrique Barboza exit(1);
27995f2b96b3SDaniel Henrique Barboza }
28005f2b96b3SDaniel Henrique Barboza
28016c8ebe30SDavid Gibson /*
28026c8ebe30SDavid Gibson * if Secure VM (PEF) support is configured, then initialize it
28036c8ebe30SDavid Gibson */
280400a238b1SXiaoyao Li if (machine->cgs) {
280500a238b1SXiaoyao Li confidential_guest_kvm_init(machine->cgs, &error_fatal);
280600a238b1SXiaoyao Li }
28076c8ebe30SDavid Gibson
2808226419d6SMichael S. Tsirkin msi_nonbroken = true;
280953018216SPaolo Bonzini
281053018216SPaolo Bonzini QLIST_INIT(&spapr->phbs);
28110cffce56SDavid Gibson QTAILQ_INIT(&spapr->pending_dimm_unplugs);
281253018216SPaolo Bonzini
28139f6edd06SDavid Gibson /* Determine capabilities to run with */
28149f6edd06SDavid Gibson spapr_caps_init(spapr);
28159f6edd06SDavid Gibson
281630f4b05bSDavid Gibson kvmppc_check_papr_resize_hpt(&resize_hpt_err);
281730f4b05bSDavid Gibson if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) {
281830f4b05bSDavid Gibson /*
281930f4b05bSDavid Gibson * If the user explicitly requested a mode we should either
282030f4b05bSDavid Gibson * supply it, or fail completely (which we do below). But if
282130f4b05bSDavid Gibson * it's not set explicitly, we reset our mode to something
282230f4b05bSDavid Gibson * that works
282330f4b05bSDavid Gibson */
282430f4b05bSDavid Gibson if (resize_hpt_err) {
282530f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED;
282630f4b05bSDavid Gibson error_free(resize_hpt_err);
282730f4b05bSDavid Gibson resize_hpt_err = NULL;
282830f4b05bSDavid Gibson } else {
282930f4b05bSDavid Gibson spapr->resize_hpt = smc->resize_hpt_default;
283030f4b05bSDavid Gibson }
283130f4b05bSDavid Gibson }
283230f4b05bSDavid Gibson
283330f4b05bSDavid Gibson assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT);
283430f4b05bSDavid Gibson
283530f4b05bSDavid Gibson if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && resize_hpt_err) {
283630f4b05bSDavid Gibson /*
283730f4b05bSDavid Gibson * User requested HPT resize, but this host can't supply it. Bail out
283830f4b05bSDavid Gibson */
283930f4b05bSDavid Gibson error_report_err(resize_hpt_err);
284030f4b05bSDavid Gibson exit(1);
284130f4b05bSDavid Gibson }
284214963c34SMarkus Armbruster error_free(resize_hpt_err);
284330f4b05bSDavid Gibson
2844425f0b7aSDavid Gibson spapr->rma_size = spapr_rma_size(spapr, &error_fatal);
2845c4177479SAlexey Kardashevskiy
2846b7d1f77aSBenjamin Herrenschmidt /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */
28474b98e72dSAlexey Kardashevskiy load_limit = MIN(spapr->rma_size, FDT_MAX_ADDR) - FW_OVERHEAD;
284853018216SPaolo Bonzini
2849482969d6SCédric Le Goater /*
2850482969d6SCédric Le Goater * VSMT must be set in order to be able to compute VCPU ids, ie to
28511a518e76SCédric Le Goater * call spapr_max_server_number() or spapr_vcpu_id().
2852482969d6SCédric Le Goater */
2853482969d6SCédric Le Goater spapr_set_vsmt_mode(spapr, &error_fatal);
2854482969d6SCédric Le Goater
28557b565160SDavid Gibson /* Set up Interrupt Controller before we create the VCPUs */
2856fab397d8SCédric Le Goater spapr_irq_init(spapr, &error_fatal);
28577b565160SDavid Gibson
2858dc1b5eeeSGreg Kurz /* Set up containers for ibm,client-architecture-support negotiated options
2859dc1b5eeeSGreg Kurz */
2860facdb8b6SMichael Roth spapr->ov5 = spapr_ovec_new();
2861facdb8b6SMichael Roth spapr->ov5_cas = spapr_ovec_new();
2862facdb8b6SMichael Roth
2863facdb8b6SMichael Roth spapr_ovec_set(spapr->ov5, OV5_DRCONF_MEMORY);
28647c150d6fSDavid Gibson spapr_validate_node_memory(machine, &error_fatal);
2865224245bfSDavid Gibson
2866417ece33SMichael Roth spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY);
2867417ece33SMichael Roth
2868e0eb84d4SDaniel Henrique Barboza /* Do not advertise FORM2 NUMA support for pseries-6.1 and older */
2869e0eb84d4SDaniel Henrique Barboza if (!smc->pre_6_2_numa_affinity) {
2870e0eb84d4SDaniel Henrique Barboza spapr_ovec_set(spapr->ov5, OV5_FORM2_AFFINITY);
2871e0eb84d4SDaniel Henrique Barboza }
2872e0eb84d4SDaniel Henrique Barboza
2873ffbb1705SMichael Roth /* advertise support for dedicated HP event source to guests */
2874ffbb1705SMichael Roth if (spapr->use_hotplug_event_source) {
2875ffbb1705SMichael Roth spapr_ovec_set(spapr->ov5, OV5_HP_EVT);
2876ffbb1705SMichael Roth }
2877ffbb1705SMichael Roth
28782772cf6bSDavid Gibson /* advertise support for HPT resizing */
28792772cf6bSDavid Gibson if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) {
28802772cf6bSDavid Gibson spapr_ovec_set(spapr->ov5, OV5_HPT_RESIZE);
28812772cf6bSDavid Gibson }
28822772cf6bSDavid Gibson
2883a324d6f1SBharata B Rao /* advertise support for ibm,dyamic-memory-v2 */
2884a324d6f1SBharata B Rao spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2);
2885a324d6f1SBharata B Rao
2886db592b5bSCédric Le Goater /* advertise XIVE on POWER9 machines */
2887ca62823bSDavid Gibson if (spapr->irq->xive) {
2888db592b5bSCédric Le Goater spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT);
2889db592b5bSCédric Le Goater }
2890db592b5bSCédric Le Goater
289153018216SPaolo Bonzini /* init CPUs */
28920c86d0fdSDavid Gibson spapr_init_cpus(spapr);
289353018216SPaolo Bonzini
2894f1aa45ffSDaniel Henrique Barboza /* Init numa_assoc_array */
2895f1aa45ffSDaniel Henrique Barboza spapr_numa_associativity_init(spapr, machine);
2896f1aa45ffSDaniel Henrique Barboza
28970550b120SGreg Kurz if ((!kvm_enabled() || kvmppc_has_cap_mmu_radix()) &&
2898ad99d04cSDavid Gibson ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0,
28990550b120SGreg Kurz spapr->max_compat_pvr)) {
2900b4b83312SGreg Kurz spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_300);
29010550b120SGreg Kurz /* KVM and TCG always allow GTSE with radix... */
29020550b120SGreg Kurz spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE);
29030550b120SGreg Kurz }
29040550b120SGreg Kurz /* ... but not with hash (currently). */
29050550b120SGreg Kurz
2906026bfd89SDavid Gibson if (kvm_enabled()) {
2907026bfd89SDavid Gibson /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */
2908026bfd89SDavid Gibson kvmppc_enable_logical_ci_hcalls();
2909ef9971ddSAlexey Kardashevskiy kvmppc_enable_set_mode_hcall();
29105145ad4fSNathan Whitehorn
29115145ad4fSNathan Whitehorn /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */
29125145ad4fSNathan Whitehorn kvmppc_enable_clear_ref_mod_hcalls();
291368f9f708SSuraj Jitindar Singh
291468f9f708SSuraj Jitindar Singh /* Enable H_PAGE_INIT */
291568f9f708SSuraj Jitindar Singh kvmppc_enable_h_page_init();
2916026bfd89SDavid Gibson }
2917026bfd89SDavid Gibson
2918ab74e543SIgor Mammedov /* map RAM */
2919ab74e543SIgor Mammedov memory_region_add_subregion(sysmem, 0, machine->ram);
292053018216SPaolo Bonzini
29214a1c9cf0SBharata B Rao /* initialize hotplug memory address space */
29224a1c9cf0SBharata B Rao if (machine->ram_size < machine->maxram_size) {
29230c9269a5SDavid Hildenbrand ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size;
2924c0ce7b4aSDavid Hildenbrand hwaddr device_mem_base;
2925c0ce7b4aSDavid Hildenbrand
292671c9a3ddSBharata B Rao /*
292771c9a3ddSBharata B Rao * Limit the number of hotpluggable memory slots to half the number
292871c9a3ddSBharata B Rao * slots that KVM supports, leaving the other half for PCI and other
292971c9a3ddSBharata B Rao * devices. However ensure that number of slots doesn't drop below 32.
293071c9a3ddSBharata B Rao */
293171c9a3ddSBharata B Rao int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 :
293271c9a3ddSBharata B Rao SPAPR_MAX_RAM_SLOTS;
29334a1c9cf0SBharata B Rao
293471c9a3ddSBharata B Rao if (max_memslots < SPAPR_MAX_RAM_SLOTS) {
293571c9a3ddSBharata B Rao max_memslots = SPAPR_MAX_RAM_SLOTS;
293671c9a3ddSBharata B Rao }
293771c9a3ddSBharata B Rao if (machine->ram_slots > max_memslots) {
2938d54e4d76SDavid Gibson error_report("Specified number of memory slots %"
2939d54e4d76SDavid Gibson PRIu64" exceeds max supported %d",
294071c9a3ddSBharata B Rao machine->ram_slots, max_memslots);
2941d54e4d76SDavid Gibson exit(1);
29424a1c9cf0SBharata B Rao }
29434a1c9cf0SBharata B Rao
2944c0ce7b4aSDavid Hildenbrand device_mem_base = ROUND_UP(machine->ram_size, SPAPR_DEVICE_MEM_ALIGN);
2945c0ce7b4aSDavid Hildenbrand machine_memory_devices_init(machine, device_mem_base, device_mem_size);
29464a1c9cf0SBharata B Rao }
29474a1c9cf0SBharata B Rao
2948224245bfSDavid Gibson spapr_create_lmb_dr_connectors(spapr);
2949224245bfSDavid Gibson
2950ee3a71e3SShivaprasad G Bhat if (mc->nvdimm_supported) {
2951ee3a71e3SShivaprasad G Bhat spapr_create_nvdimm_dr_connectors(spapr);
2952ee3a71e3SShivaprasad G Bhat }
2953ee3a71e3SShivaprasad G Bhat
2954ffbb1705SMichael Roth /* Set up RTAS event infrastructure */
295553018216SPaolo Bonzini spapr_events_init(spapr);
295653018216SPaolo Bonzini
295712f42174SDavid Gibson /* Set up the RTC RTAS interfaces */
295828df36a1SDavid Gibson spapr_rtc_create(spapr);
295912f42174SDavid Gibson
296053018216SPaolo Bonzini /* Set up VIO bus */
296153018216SPaolo Bonzini spapr->vio_bus = spapr_vio_bus_init();
296253018216SPaolo Bonzini
296346ee119fSPaolo Bonzini for (i = 0; serial_hd(i); i++) {
29649bca0edbSPeter Maydell spapr_vty_create(spapr->vio_bus, serial_hd(i));
296553018216SPaolo Bonzini }
296653018216SPaolo Bonzini
296753018216SPaolo Bonzini /* We always have at least the nvram device on VIO */
296853018216SPaolo Bonzini spapr_create_nvram(spapr);
296953018216SPaolo Bonzini
2970962b6c36SMichael Roth /*
2971962b6c36SMichael Roth * Setup hotplug / dynamic-reconfiguration connectors. top-level
2972962b6c36SMichael Roth * connectors (described in root DT node's "ibm,drc-types" property)
2973962b6c36SMichael Roth * are pre-initialized here. additional child connectors (such as
2974962b6c36SMichael Roth * connectors for a PHBs PCI slots) are added as needed during their
2975962b6c36SMichael Roth * parent's realization.
2976962b6c36SMichael Roth */
2977962b6c36SMichael Roth if (smc->dr_phb_enabled) {
2978962b6c36SMichael Roth for (i = 0; i < SPAPR_MAX_PHBS; i++) {
2979962b6c36SMichael Roth spapr_dr_connector_new(OBJECT(machine), TYPE_SPAPR_DRC_PHB, i);
2980962b6c36SMichael Roth }
2981962b6c36SMichael Roth }
2982962b6c36SMichael Roth
298353018216SPaolo Bonzini /* Set up PCI */
298453018216SPaolo Bonzini spapr_pci_rtas_init();
298553018216SPaolo Bonzini
2986999c9cafSGreg Kurz phb = spapr_create_default_phb();
298753018216SPaolo Bonzini
29880aff8161SDavid Woodhouse while ((nd = qemu_find_nic_info("spapr-vlan", true, "ibmveth"))) {
298953018216SPaolo Bonzini spapr_vlan_create(spapr->vio_bus, nd);
299053018216SPaolo Bonzini }
29910aff8161SDavid Woodhouse
29920aff8161SDavid Woodhouse pci_init_nic_devices(phb->bus, NULL);
299353018216SPaolo Bonzini
299453018216SPaolo Bonzini for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) {
299553018216SPaolo Bonzini spapr_vscsi_create(spapr->vio_bus);
299653018216SPaolo Bonzini }
299753018216SPaolo Bonzini
299853018216SPaolo Bonzini /* Graphics */
2999f73eb948SPaolo Bonzini has_vga = spapr_vga_init(phb->bus, &error_fatal);
3000f73eb948SPaolo Bonzini if (has_vga) {
3001f73eb948SPaolo Bonzini spapr->want_stdout_path = !machine->enable_graphics;
3002c6e76503SPaolo Bonzini machine->usb |= defaults_enabled() && !machine->usb_disabled;
3003f73eb948SPaolo Bonzini } else {
3004f73eb948SPaolo Bonzini spapr->want_stdout_path = true;
300553018216SPaolo Bonzini }
300653018216SPaolo Bonzini
30074ee9ced9SMarcel Apfelbaum if (machine->usb) {
300857040d45SThomas Huth pci_create_simple(phb->bus, -1, "nec-usb-xhci");
3009c86580b8SMarkus Armbruster
3010f73eb948SPaolo Bonzini if (has_vga) {
3011ae1011d4SPaolo Bonzini USBBus *usb_bus;
3012c86580b8SMarkus Armbruster
3013ae1011d4SPaolo Bonzini usb_bus = USB_BUS(object_resolve_type_unambiguous(TYPE_USB_BUS,
3014ae1011d4SPaolo Bonzini &error_abort));
3015c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-kbd");
3016c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-mouse");
301753018216SPaolo Bonzini }
301853018216SPaolo Bonzini }
301953018216SPaolo Bonzini
302053018216SPaolo Bonzini if (kernel_filename) {
30215bb55f3eSAlexey Kardashevskiy uint64_t loaded_addr = 0;
30225bb55f3eSAlexey Kardashevskiy
30234366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL,
302487262806SAlexey Kardashevskiy translate_kernel_address, spapr,
30255bb55f3eSAlexey Kardashevskiy NULL, &loaded_addr, NULL, NULL, 1,
3026a19f7fb0SDavid Gibson PPC_ELF_MACHINE, 0, 0);
3027a19f7fb0SDavid Gibson if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) {
30284366e1dbSLiam Merwick spapr->kernel_size = load_elf(kernel_filename, NULL,
3029617160c9SBALATON Zoltan translate_kernel_address, spapr,
30305bb55f3eSAlexey Kardashevskiy NULL, &loaded_addr, NULL, NULL, 0,
3031617160c9SBALATON Zoltan PPC_ELF_MACHINE, 0, 0);
3032a19f7fb0SDavid Gibson spapr->kernel_le = spapr->kernel_size > 0;
303316457e7fSBenjamin Herrenschmidt }
3034a19f7fb0SDavid Gibson if (spapr->kernel_size < 0) {
3035a19f7fb0SDavid Gibson error_report("error loading %s: %s", kernel_filename,
3036a19f7fb0SDavid Gibson load_elf_strerror(spapr->kernel_size));
303753018216SPaolo Bonzini exit(1);
303853018216SPaolo Bonzini }
303953018216SPaolo Bonzini
30405bb55f3eSAlexey Kardashevskiy if (spapr->kernel_addr != loaded_addr) {
30415bb55f3eSAlexey Kardashevskiy warn_report("spapr: kernel_addr changed from 0x%"PRIx64
30425bb55f3eSAlexey Kardashevskiy " to 0x%"PRIx64,
30435bb55f3eSAlexey Kardashevskiy spapr->kernel_addr, loaded_addr);
30445bb55f3eSAlexey Kardashevskiy spapr->kernel_addr = loaded_addr;
30455bb55f3eSAlexey Kardashevskiy }
30465bb55f3eSAlexey Kardashevskiy
304753018216SPaolo Bonzini /* load initrd */
304853018216SPaolo Bonzini if (initrd_filename) {
304953018216SPaolo Bonzini /* Try to locate the initrd in the gap between the kernel
305053018216SPaolo Bonzini * and the firmware. Add a bit of space just in case
305153018216SPaolo Bonzini */
305287262806SAlexey Kardashevskiy spapr->initrd_base = (spapr->kernel_addr + spapr->kernel_size
3053a19f7fb0SDavid Gibson + 0x1ffff) & ~0xffff;
3054a19f7fb0SDavid Gibson spapr->initrd_size = load_image_targphys(initrd_filename,
3055a19f7fb0SDavid Gibson spapr->initrd_base,
3056a19f7fb0SDavid Gibson load_limit
3057a19f7fb0SDavid Gibson - spapr->initrd_base);
3058a19f7fb0SDavid Gibson if (spapr->initrd_size < 0) {
3059d54e4d76SDavid Gibson error_report("could not load initial ram disk '%s'",
306053018216SPaolo Bonzini initrd_filename);
306153018216SPaolo Bonzini exit(1);
306253018216SPaolo Bonzini }
306353018216SPaolo Bonzini }
306453018216SPaolo Bonzini }
306553018216SPaolo Bonzini
306628e02042SDavid Gibson /* FIXME: Should register things through the MachineState's qdev
306728e02042SDavid Gibson * interface, this is a legacy from the sPAPREnvironment structure
306828e02042SDavid Gibson * which predated MachineState but had a similar function */
30694be21d56SDavid Gibson vmstate_register(NULL, 0, &vmstate_spapr, spapr);
30701df2c9a2SPeter Xu register_savevm_live("spapr/htab", VMSTATE_INSTANCE_ID_ANY, 1,
30714be21d56SDavid Gibson &savevm_htab_handlers, spapr);
30724be21d56SDavid Gibson
30739bc6bfdfSMarkus Armbruster qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine));
3074bb2bdd81SGreg Kurz
30755b2128d2SAlexander Graf qemu_register_boot_set(spapr_boot_set, spapr);
307642043e4fSLaurent Vivier
307793eac7b8SNicholas Piggin /*
307893eac7b8SNicholas Piggin * Nothing needs to be done to resume a suspended guest because
307993eac7b8SNicholas Piggin * suspending does not change the machine state, so no need for
308093eac7b8SNicholas Piggin * a ->wakeup method.
308193eac7b8SNicholas Piggin */
308293eac7b8SNicholas Piggin qemu_register_wakeup_support();
308393eac7b8SNicholas Piggin
308442043e4fSLaurent Vivier if (kvm_enabled()) {
30853dc410aeSAlexey Kardashevskiy /* to stop and start vmclock */
308642043e4fSLaurent Vivier qemu_add_vm_change_state_handler(cpu_ppc_clock_vm_state_change,
308742043e4fSLaurent Vivier &spapr->tb);
30883dc410aeSAlexey Kardashevskiy
30893dc410aeSAlexey Kardashevskiy kvmppc_spapr_enable_inkernel_multitce();
309042043e4fSLaurent Vivier }
30919ac703acSAravinda Prasad
30928af7e1feSNicholas Piggin qemu_cond_init(&spapr->fwnmi_machine_check_interlock_cond);
3093fc8c745dSAlexey Kardashevskiy if (spapr->vof) {
3094fc8c745dSAlexey Kardashevskiy spapr->vof->fw_size = fw_size; /* for claim() on itself */
3095fc8c745dSAlexey Kardashevskiy spapr_register_hypercall(KVMPPC_H_VOF_CLIENT, spapr_h_vof_client);
3096fc8c745dSAlexey Kardashevskiy }
309781b205ceSAlexey Kardashevskiy
309881b205ceSAlexey Kardashevskiy spapr_watchdog_init(spapr);
309953018216SPaolo Bonzini }
310053018216SPaolo Bonzini
310107b10bc4SDaniel Henrique Barboza #define DEFAULT_KVM_TYPE "auto"
spapr_kvm_type(MachineState * machine,const char * vm_type)3102dc0ca80eSEric Auger static int spapr_kvm_type(MachineState *machine, const char *vm_type)
3103135a129aSAneesh Kumar K.V {
310407b10bc4SDaniel Henrique Barboza /*
310507b10bc4SDaniel Henrique Barboza * The use of g_ascii_strcasecmp() for 'hv' and 'pr' is to
3106e6a19a64SMichael Tokarev * accommodate the 'HV' and 'PV' formats that exists in the
310707b10bc4SDaniel Henrique Barboza * wild. The 'auto' mode is being introduced already as
310807b10bc4SDaniel Henrique Barboza * lower-case, thus we don't need to bother checking for
310907b10bc4SDaniel Henrique Barboza * "AUTO".
311007b10bc4SDaniel Henrique Barboza */
311107b10bc4SDaniel Henrique Barboza if (!vm_type || !strcmp(vm_type, DEFAULT_KVM_TYPE)) {
3112135a129aSAneesh Kumar K.V return 0;
3113135a129aSAneesh Kumar K.V }
3114135a129aSAneesh Kumar K.V
311507b10bc4SDaniel Henrique Barboza if (!g_ascii_strcasecmp(vm_type, "hv")) {
3116135a129aSAneesh Kumar K.V return 1;
3117135a129aSAneesh Kumar K.V }
3118135a129aSAneesh Kumar K.V
311907b10bc4SDaniel Henrique Barboza if (!g_ascii_strcasecmp(vm_type, "pr")) {
3120135a129aSAneesh Kumar K.V return 2;
3121135a129aSAneesh Kumar K.V }
3122135a129aSAneesh Kumar K.V
3123135a129aSAneesh Kumar K.V error_report("Unknown kvm-type specified '%s'", vm_type);
3124bc3e41a0SAkihiko Odaki return -1;
3125135a129aSAneesh Kumar K.V }
3126135a129aSAneesh Kumar K.V
312771461b0fSAlexey Kardashevskiy /*
3128627b84f4SGonglei * Implementation of an interface to adjust firmware path
312971461b0fSAlexey Kardashevskiy * for the bootindex property handling.
313071461b0fSAlexey Kardashevskiy */
spapr_get_fw_dev_path(FWPathProvider * p,BusState * bus,DeviceState * dev)313171461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus,
313271461b0fSAlexey Kardashevskiy DeviceState *dev)
313371461b0fSAlexey Kardashevskiy {
313471461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \
313571461b0fSAlexey Kardashevskiy ((type *)object_dynamic_cast(OBJECT(obj), (name)))
313671461b0fSAlexey Kardashevskiy SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE);
3137ce2918cbSDavid Gibson SpaprPhbState *phb = CAST(SpaprPhbState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE);
3138c4e13492SFelipe Franciosi VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON);
3139040bdafcSGreg Kurz PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE);
314071461b0fSAlexey Kardashevskiy
31411977434bSDaniel Henrique Barboza if (d && bus) {
314271461b0fSAlexey Kardashevskiy void *spapr = CAST(void, bus->parent, "spapr-vscsi");
314371461b0fSAlexey Kardashevskiy VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI);
314471461b0fSAlexey Kardashevskiy USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE);
314571461b0fSAlexey Kardashevskiy
314671461b0fSAlexey Kardashevskiy if (spapr) {
314771461b0fSAlexey Kardashevskiy /*
314871461b0fSAlexey Kardashevskiy * Replace "channel@0/disk@0,0" with "disk@8000000000000000":
31491ac24c91SThomas Huth * In the top 16 bits of the 64-bit LUN, we use SRP luns of the form
31501ac24c91SThomas Huth * 0x8000 | (target << 8) | (bus << 5) | lun
31511ac24c91SThomas Huth * (see the "Logical unit addressing format" table in SAM5)
315271461b0fSAlexey Kardashevskiy */
31531ac24c91SThomas Huth unsigned id = 0x8000 | (d->id << 8) | (d->channel << 5) | d->lun;
315471461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev),
315571461b0fSAlexey Kardashevskiy (uint64_t)id << 48);
315671461b0fSAlexey Kardashevskiy } else if (virtio) {
315771461b0fSAlexey Kardashevskiy /*
315871461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (target << 8) | lun
315971461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN
316071461b0fSAlexey Kardashevskiy * Note: the quote above is from SLOF and it is wrong,
316171461b0fSAlexey Kardashevskiy * the actual binding is:
316271461b0fSAlexey Kardashevskiy * swap 0100 or 10 << or 20 << ( target lun-id -- srplun )
316371461b0fSAlexey Kardashevskiy */
316471461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (d->id << 16) | d->lun;
3165bac658d1SThomas Huth if (d->lun >= 256) {
3166bac658d1SThomas Huth /* Use the LUN "flat space addressing method" */
3167bac658d1SThomas Huth id |= 0x4000;
3168bac658d1SThomas Huth }
316971461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev),
317071461b0fSAlexey Kardashevskiy (uint64_t)id << 32);
317171461b0fSAlexey Kardashevskiy } else if (usb) {
317271461b0fSAlexey Kardashevskiy /*
317371461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (usb-port << 16) | lun
317471461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN
317571461b0fSAlexey Kardashevskiy */
317671461b0fSAlexey Kardashevskiy unsigned usb_port = atoi(usb->port->path);
317771461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (usb_port << 16) | d->lun;
317871461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev),
317971461b0fSAlexey Kardashevskiy (uint64_t)id << 32);
318071461b0fSAlexey Kardashevskiy }
318171461b0fSAlexey Kardashevskiy }
318271461b0fSAlexey Kardashevskiy
3183b99260ebSThomas Huth /*
3184b99260ebSThomas Huth * SLOF probes the USB devices, and if it recognizes that the device is a
3185b99260ebSThomas Huth * storage device, it changes its name to "storage" instead of "usb-host",
3186b99260ebSThomas Huth * and additionally adds a child node for the SCSI LUN, so the correct
3187b99260ebSThomas Huth * boot path in SLOF is something like .../storage@1/disk@xxx" instead.
3188b99260ebSThomas Huth */
3189b99260ebSThomas Huth if (strcmp("usb-host", qdev_fw_name(dev)) == 0) {
3190b99260ebSThomas Huth USBDevice *usbdev = CAST(USBDevice, dev, TYPE_USB_DEVICE);
3191b7b2a60bSGerd Hoffmann if (usb_device_is_scsi_storage(usbdev)) {
3192b99260ebSThomas Huth return g_strdup_printf("storage@%s/disk", usbdev->port->path);
3193b99260ebSThomas Huth }
3194b99260ebSThomas Huth }
3195b99260ebSThomas Huth
319671461b0fSAlexey Kardashevskiy if (phb) {
319771461b0fSAlexey Kardashevskiy /* Replace "pci" with "pci@800000020000000" */
319871461b0fSAlexey Kardashevskiy return g_strdup_printf("pci@%"PRIX64, phb->buid);
319971461b0fSAlexey Kardashevskiy }
320071461b0fSAlexey Kardashevskiy
3201c4e13492SFelipe Franciosi if (vsc) {
3202c4e13492SFelipe Franciosi /* Same logic as virtio above */
3203c4e13492SFelipe Franciosi unsigned id = 0x1000000 | (vsc->target << 16) | vsc->lun;
3204c4e13492SFelipe Franciosi return g_strdup_printf("disk@%"PRIX64, (uint64_t)id << 32);
3205c4e13492SFelipe Franciosi }
3206c4e13492SFelipe Franciosi
32074871dd4cSThomas Huth if (g_str_equal("pci-bridge", qdev_fw_name(dev))) {
32084871dd4cSThomas Huth /* SLOF uses "pci" instead of "pci-bridge" for PCI bridges */
320901a78f23SCédric Le Goater PCIDevice *pdev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE);
321001a78f23SCédric Le Goater return g_strdup_printf("pci@%x", PCI_SLOT(pdev->devfn));
32114871dd4cSThomas Huth }
32124871dd4cSThomas Huth
3213040bdafcSGreg Kurz if (pcidev) {
3214040bdafcSGreg Kurz return spapr_pci_fw_dev_name(pcidev);
3215040bdafcSGreg Kurz }
3216040bdafcSGreg Kurz
321771461b0fSAlexey Kardashevskiy return NULL;
321871461b0fSAlexey Kardashevskiy }
321971461b0fSAlexey Kardashevskiy
spapr_get_kvm_type(Object * obj,Error ** errp)322023825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp)
322123825581SEduardo Habkost {
3222ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj);
322323825581SEduardo Habkost
322428e02042SDavid Gibson return g_strdup(spapr->kvm_type);
322523825581SEduardo Habkost }
322623825581SEduardo Habkost
spapr_set_kvm_type(Object * obj,const char * value,Error ** errp)322723825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp)
322823825581SEduardo Habkost {
3229ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj);
323023825581SEduardo Habkost
323128e02042SDavid Gibson g_free(spapr->kvm_type);
323228e02042SDavid Gibson spapr->kvm_type = g_strdup(value);
323323825581SEduardo Habkost }
323423825581SEduardo Habkost
spapr_get_modern_hotplug_events(Object * obj,Error ** errp)3235f6229214SMichael Roth static bool spapr_get_modern_hotplug_events(Object *obj, Error **errp)
3236f6229214SMichael Roth {
3237ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj);
3238f6229214SMichael Roth
3239f6229214SMichael Roth return spapr->use_hotplug_event_source;
3240f6229214SMichael Roth }
3241f6229214SMichael Roth
spapr_set_modern_hotplug_events(Object * obj,bool value,Error ** errp)3242f6229214SMichael Roth static void spapr_set_modern_hotplug_events(Object *obj, bool value,
3243f6229214SMichael Roth Error **errp)
3244f6229214SMichael Roth {
3245ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj);
3246f6229214SMichael Roth
3247f6229214SMichael Roth spapr->use_hotplug_event_source = value;
3248f6229214SMichael Roth }
3249f6229214SMichael Roth
spapr_get_msix_emulation(Object * obj,Error ** errp)3250fcad0d21SAlexey Kardashevskiy static bool spapr_get_msix_emulation(Object *obj, Error **errp)
3251fcad0d21SAlexey Kardashevskiy {
3252fcad0d21SAlexey Kardashevskiy return true;
3253fcad0d21SAlexey Kardashevskiy }
3254fcad0d21SAlexey Kardashevskiy
spapr_get_resize_hpt(Object * obj,Error ** errp)325530f4b05bSDavid Gibson static char *spapr_get_resize_hpt(Object *obj, Error **errp)
325630f4b05bSDavid Gibson {
3257ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj);
325830f4b05bSDavid Gibson
325930f4b05bSDavid Gibson switch (spapr->resize_hpt) {
326030f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DEFAULT:
326130f4b05bSDavid Gibson return g_strdup("default");
326230f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_DISABLED:
326330f4b05bSDavid Gibson return g_strdup("disabled");
326430f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_ENABLED:
326530f4b05bSDavid Gibson return g_strdup("enabled");
326630f4b05bSDavid Gibson case SPAPR_RESIZE_HPT_REQUIRED:
326730f4b05bSDavid Gibson return g_strdup("required");
326830f4b05bSDavid Gibson }
326930f4b05bSDavid Gibson g_assert_not_reached();
327030f4b05bSDavid Gibson }
327130f4b05bSDavid Gibson
spapr_set_resize_hpt(Object * obj,const char * value,Error ** errp)327230f4b05bSDavid Gibson static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp)
327330f4b05bSDavid Gibson {
3274ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj);
327530f4b05bSDavid Gibson
327630f4b05bSDavid Gibson if (strcmp(value, "default") == 0) {
327730f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DEFAULT;
327830f4b05bSDavid Gibson } else if (strcmp(value, "disabled") == 0) {
327930f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED;
328030f4b05bSDavid Gibson } else if (strcmp(value, "enabled") == 0) {
328130f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_ENABLED;
328230f4b05bSDavid Gibson } else if (strcmp(value, "required") == 0) {
328330f4b05bSDavid Gibson spapr->resize_hpt = SPAPR_RESIZE_HPT_REQUIRED;
328430f4b05bSDavid Gibson } else {
328530f4b05bSDavid Gibson error_setg(errp, "Bad value for \"resize-hpt\" property");
328630f4b05bSDavid Gibson }
328730f4b05bSDavid Gibson }
328830f4b05bSDavid Gibson
spapr_get_vof(Object * obj,Error ** errp)3289fc8c745dSAlexey Kardashevskiy static bool spapr_get_vof(Object *obj, Error **errp)
3290fc8c745dSAlexey Kardashevskiy {
3291fc8c745dSAlexey Kardashevskiy SpaprMachineState *spapr = SPAPR_MACHINE(obj);
3292fc8c745dSAlexey Kardashevskiy
3293fc8c745dSAlexey Kardashevskiy return spapr->vof != NULL;
3294fc8c745dSAlexey Kardashevskiy }
3295fc8c745dSAlexey Kardashevskiy
spapr_set_vof(Object * obj,bool value,Error ** errp)3296fc8c745dSAlexey Kardashevskiy static void spapr_set_vof(Object *obj, bool value, Error **errp)
3297fc8c745dSAlexey Kardashevskiy {
3298fc8c745dSAlexey Kardashevskiy SpaprMachineState *spapr = SPAPR_MACHINE(obj);
3299fc8c745dSAlexey Kardashevskiy
3300fc8c745dSAlexey Kardashevskiy if (spapr->vof) {
3301fc8c745dSAlexey Kardashevskiy vof_cleanup(spapr->vof);
3302fc8c745dSAlexey Kardashevskiy g_free(spapr->vof);
3303fc8c745dSAlexey Kardashevskiy spapr->vof = NULL;
3304fc8c745dSAlexey Kardashevskiy }
3305fc8c745dSAlexey Kardashevskiy if (!value) {
3306fc8c745dSAlexey Kardashevskiy return;
3307fc8c745dSAlexey Kardashevskiy }
3308fc8c745dSAlexey Kardashevskiy spapr->vof = g_malloc0(sizeof(*spapr->vof));
3309fc8c745dSAlexey Kardashevskiy }
3310fc8c745dSAlexey Kardashevskiy
spapr_get_ic_mode(Object * obj,Error ** errp)33113ba3d0bcSCédric Le Goater static char *spapr_get_ic_mode(Object *obj, Error **errp)
33123ba3d0bcSCédric Le Goater {
3313ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj);
33143ba3d0bcSCédric Le Goater
33153ba3d0bcSCédric Le Goater if (spapr->irq == &spapr_irq_xics_legacy) {
33163ba3d0bcSCédric Le Goater return g_strdup("legacy");
33173ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xics) {
33183ba3d0bcSCédric Le Goater return g_strdup("xics");
33193ba3d0bcSCédric Le Goater } else if (spapr->irq == &spapr_irq_xive) {
33203ba3d0bcSCédric Le Goater return g_strdup("xive");
332113db0cd9SCédric Le Goater } else if (spapr->irq == &spapr_irq_dual) {
332213db0cd9SCédric Le Goater return g_strdup("dual");
33233ba3d0bcSCédric Le Goater }
33243ba3d0bcSCédric Le Goater g_assert_not_reached();
33253ba3d0bcSCédric Le Goater }
33263ba3d0bcSCédric Le Goater
spapr_set_ic_mode(Object * obj,const char * value,Error ** errp)33273ba3d0bcSCédric Le Goater static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp)
33283ba3d0bcSCédric Le Goater {
3329ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj);
33303ba3d0bcSCédric Le Goater
333121df5e4fSGreg Kurz if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
333221df5e4fSGreg Kurz error_setg(errp, "This machine only uses the legacy XICS backend, don't pass ic-mode");
333321df5e4fSGreg Kurz return;
333421df5e4fSGreg Kurz }
333521df5e4fSGreg Kurz
33363ba3d0bcSCédric Le Goater /* The legacy IRQ backend can not be set */
33373ba3d0bcSCédric Le Goater if (strcmp(value, "xics") == 0) {
33383ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xics;
33393ba3d0bcSCédric Le Goater } else if (strcmp(value, "xive") == 0) {
33403ba3d0bcSCédric Le Goater spapr->irq = &spapr_irq_xive;
334113db0cd9SCédric Le Goater } else if (strcmp(value, "dual") == 0) {
334213db0cd9SCédric Le Goater spapr->irq = &spapr_irq_dual;
33433ba3d0bcSCédric Le Goater } else {
33443ba3d0bcSCédric Le Goater error_setg(errp, "Bad value for \"ic-mode\" property");
33453ba3d0bcSCédric Le Goater }
33463ba3d0bcSCédric Le Goater }
33473ba3d0bcSCédric Le Goater
spapr_get_host_model(Object * obj,Error ** errp)334827461d69SPrasad J Pandit static char *spapr_get_host_model(Object *obj, Error **errp)
334927461d69SPrasad J Pandit {
3350ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj);
335127461d69SPrasad J Pandit
335227461d69SPrasad J Pandit return g_strdup(spapr->host_model);
335327461d69SPrasad J Pandit }
335427461d69SPrasad J Pandit
spapr_set_host_model(Object * obj,const char * value,Error ** errp)335527461d69SPrasad J Pandit static void spapr_set_host_model(Object *obj, const char *value, Error **errp)
335627461d69SPrasad J Pandit {
3357ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj);
335827461d69SPrasad J Pandit
335927461d69SPrasad J Pandit g_free(spapr->host_model);
336027461d69SPrasad J Pandit spapr->host_model = g_strdup(value);
336127461d69SPrasad J Pandit }
336227461d69SPrasad J Pandit
spapr_get_host_serial(Object * obj,Error ** errp)336327461d69SPrasad J Pandit static char *spapr_get_host_serial(Object *obj, Error **errp)
336427461d69SPrasad J Pandit {
3365ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj);
336627461d69SPrasad J Pandit
336727461d69SPrasad J Pandit return g_strdup(spapr->host_serial);
336827461d69SPrasad J Pandit }
336927461d69SPrasad J Pandit
spapr_set_host_serial(Object * obj,const char * value,Error ** errp)337027461d69SPrasad J Pandit static void spapr_set_host_serial(Object *obj, const char *value, Error **errp)
337127461d69SPrasad J Pandit {
3372ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj);
337327461d69SPrasad J Pandit
337427461d69SPrasad J Pandit g_free(spapr->host_serial);
337527461d69SPrasad J Pandit spapr->host_serial = g_strdup(value);
337627461d69SPrasad J Pandit }
337727461d69SPrasad J Pandit
spapr_instance_init(Object * obj)3378bcb5ce08SDavid Gibson static void spapr_instance_init(Object *obj)
337923825581SEduardo Habkost {
3380ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj);
3381ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
338255810e90SIgor Mammedov MachineState *ms = MACHINE(spapr);
338355810e90SIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(ms);
338455810e90SIgor Mammedov
338555810e90SIgor Mammedov /*
338655810e90SIgor Mammedov * NVDIMM support went live in 5.1 without considering that, in
338755810e90SIgor Mammedov * other archs, the user needs to enable NVDIMM support with the
338855810e90SIgor Mammedov * 'nvdimm' machine option and the default behavior is NVDIMM
338955810e90SIgor Mammedov * support disabled. It is too late to roll back to the standard
339055810e90SIgor Mammedov * behavior without breaking 5.1 guests.
339155810e90SIgor Mammedov */
339255810e90SIgor Mammedov if (mc->nvdimm_supported) {
339355810e90SIgor Mammedov ms->nvdimms_state->is_enabled = true;
339455810e90SIgor Mammedov }
3395715c5407SDavid Gibson
3396715c5407SDavid Gibson spapr->htab_fd = -1;
3397f6229214SMichael Roth spapr->use_hotplug_event_source = true;
339807b10bc4SDaniel Henrique Barboza spapr->kvm_type = g_strdup(DEFAULT_KVM_TYPE);
339923825581SEduardo Habkost object_property_add_str(obj, "kvm-type",
3400d2623129SMarkus Armbruster spapr_get_kvm_type, spapr_set_kvm_type);
340149d2e648SMarcel Apfelbaum object_property_set_description(obj, "kvm-type",
340207b10bc4SDaniel Henrique Barboza "Specifies the KVM virtualization mode (auto,"
340307b10bc4SDaniel Henrique Barboza " hv, pr). Defaults to 'auto'. This mode will use"
340407b10bc4SDaniel Henrique Barboza " any available KVM module loaded in the host,"
340507b10bc4SDaniel Henrique Barboza " where kvm_hv takes precedence if both kvm_hv and"
340607b10bc4SDaniel Henrique Barboza " kvm_pr are loaded.");
3407f6229214SMichael Roth object_property_add_bool(obj, "modern-hotplug-events",
3408f6229214SMichael Roth spapr_get_modern_hotplug_events,
3409d2623129SMarkus Armbruster spapr_set_modern_hotplug_events);
3410f6229214SMichael Roth object_property_set_description(obj, "modern-hotplug-events",
3411f6229214SMichael Roth "Use dedicated hotplug event mechanism in"
3412f6229214SMichael Roth " place of standard EPOW events when possible"
34137eecec7dSMarkus Armbruster " (required for memory hot-unplug support)");
34147843c0d6SDavid Gibson ppc_compat_add_property(obj, "max-cpu-compat", &spapr->max_compat_pvr,
341540c2281cSMarkus Armbruster "Maximum permitted CPU compatibility mode");
341630f4b05bSDavid Gibson
341730f4b05bSDavid Gibson object_property_add_str(obj, "resize-hpt",
3418d2623129SMarkus Armbruster spapr_get_resize_hpt, spapr_set_resize_hpt);
341930f4b05bSDavid Gibson object_property_set_description(obj, "resize-hpt",
34207eecec7dSMarkus Armbruster "Resizing of the Hash Page Table (enabled, disabled, required)");
342164a7b8deSFelipe Franciosi object_property_add_uint32_ptr(obj, "vsmt",
3422d2623129SMarkus Armbruster &spapr->vsmt, OBJ_PROP_FLAG_READWRITE);
3423fa98fbfcSSam Bobroff object_property_set_description(obj, "vsmt",
3424fa98fbfcSSam Bobroff "Virtual SMT: KVM behaves as if this were"
34257eecec7dSMarkus Armbruster " the host's SMT mode");
342664a7b8deSFelipe Franciosi
3427fcad0d21SAlexey Kardashevskiy object_property_add_bool(obj, "vfio-no-msix-emulation",
3428d2623129SMarkus Armbruster spapr_get_msix_emulation, NULL);
34293ba3d0bcSCédric Le Goater
343064a7b8deSFelipe Franciosi object_property_add_uint64_ptr(obj, "kernel-addr",
3431d2623129SMarkus Armbruster &spapr->kernel_addr, OBJ_PROP_FLAG_READWRITE);
343287262806SAlexey Kardashevskiy object_property_set_description(obj, "kernel-addr",
343387262806SAlexey Kardashevskiy stringify(KERNEL_LOAD_ADDR)
34347eecec7dSMarkus Armbruster " for -kernel is the default");
343587262806SAlexey Kardashevskiy spapr->kernel_addr = KERNEL_LOAD_ADDR;
3436fc8c745dSAlexey Kardashevskiy
3437fc8c745dSAlexey Kardashevskiy object_property_add_bool(obj, "x-vof", spapr_get_vof, spapr_set_vof);
3438fc8c745dSAlexey Kardashevskiy object_property_set_description(obj, "x-vof",
3439fc8c745dSAlexey Kardashevskiy "Enable Virtual Open Firmware (experimental)");
3440fc8c745dSAlexey Kardashevskiy
34413ba3d0bcSCédric Le Goater /* The machine class defines the default interrupt controller mode */
34423ba3d0bcSCédric Le Goater spapr->irq = smc->irq;
34433ba3d0bcSCédric Le Goater object_property_add_str(obj, "ic-mode", spapr_get_ic_mode,
3444d2623129SMarkus Armbruster spapr_set_ic_mode);
34453ba3d0bcSCédric Le Goater object_property_set_description(obj, "ic-mode",
34467eecec7dSMarkus Armbruster "Specifies the interrupt controller mode (xics, xive, dual)");
344727461d69SPrasad J Pandit
344827461d69SPrasad J Pandit object_property_add_str(obj, "host-model",
3449d2623129SMarkus Armbruster spapr_get_host_model, spapr_set_host_model);
345027461d69SPrasad J Pandit object_property_set_description(obj, "host-model",
34517eecec7dSMarkus Armbruster "Host model to advertise in guest device tree");
345227461d69SPrasad J Pandit object_property_add_str(obj, "host-serial",
3453d2623129SMarkus Armbruster spapr_get_host_serial, spapr_set_host_serial);
345427461d69SPrasad J Pandit object_property_set_description(obj, "host-serial",
34557eecec7dSMarkus Armbruster "Host serial number to advertise in guest device tree");
345623825581SEduardo Habkost }
345723825581SEduardo Habkost
spapr_machine_finalizefn(Object * obj)345887bbdd9cSDavid Gibson static void spapr_machine_finalizefn(Object *obj)
345987bbdd9cSDavid Gibson {
3460ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj);
346187bbdd9cSDavid Gibson
346287bbdd9cSDavid Gibson g_free(spapr->kvm_type);
346387bbdd9cSDavid Gibson }
346487bbdd9cSDavid Gibson
spapr_do_system_reset_on_cpu(CPUState * cs,run_on_cpu_data arg)34651c7ad77eSNicholas Piggin void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg)
346634316482SAlexey Kardashevskiy {
34670e236d34SNicholas Piggin SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
3468794511bcSPhilippe Mathieu-Daudé CPUPPCState *env = cpu_env(cs);
34690e236d34SNicholas Piggin
347034316482SAlexey Kardashevskiy cpu_synchronize_state(cs);
34710e236d34SNicholas Piggin /* If FWNMI is inactive, addr will be -1, which will deliver to 0x100 */
34720e236d34SNicholas Piggin if (spapr->fwnmi_system_reset_addr != -1) {
34730e236d34SNicholas Piggin uint64_t rtas_addr, addr;
34740e236d34SNicholas Piggin
34750e236d34SNicholas Piggin /* get rtas addr from fdt */
34760e236d34SNicholas Piggin rtas_addr = spapr_get_rtas_addr();
34770e236d34SNicholas Piggin if (!rtas_addr) {
34780e236d34SNicholas Piggin qemu_system_guest_panicked(NULL);
34790e236d34SNicholas Piggin return;
34800e236d34SNicholas Piggin }
34810e236d34SNicholas Piggin
34820e236d34SNicholas Piggin addr = rtas_addr + RTAS_ERROR_LOG_MAX + cs->cpu_index * sizeof(uint64_t)*2;
34830e236d34SNicholas Piggin stq_be_phys(&address_space_memory, addr, env->gpr[3]);
34840e236d34SNicholas Piggin stq_be_phys(&address_space_memory, addr + sizeof(uint64_t), 0);
34850e236d34SNicholas Piggin env->gpr[3] = addr;
34860e236d34SNicholas Piggin }
3487b5b7f391SNicholas Piggin ppc_cpu_do_system_reset(cs);
3488b5b7f391SNicholas Piggin if (spapr->fwnmi_system_reset_addr != -1) {
3489b5b7f391SNicholas Piggin env->nip = spapr->fwnmi_system_reset_addr;
3490b5b7f391SNicholas Piggin }
349134316482SAlexey Kardashevskiy }
349234316482SAlexey Kardashevskiy
spapr_nmi(NMIState * n,int cpu_index,Error ** errp)349334316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp)
349434316482SAlexey Kardashevskiy {
349534316482SAlexey Kardashevskiy CPUState *cs;
349634316482SAlexey Kardashevskiy
349734316482SAlexey Kardashevskiy CPU_FOREACH(cs) {
34981c7ad77eSNicholas Piggin async_run_on_cpu(cs, spapr_do_system_reset_on_cpu, RUN_ON_CPU_NULL);
349934316482SAlexey Kardashevskiy }
350034316482SAlexey Kardashevskiy }
350134316482SAlexey Kardashevskiy
spapr_lmb_dt_populate(SpaprDrc * drc,SpaprMachineState * spapr,void * fdt,int * fdt_start_offset,Error ** errp)3502ce2918cbSDavid Gibson int spapr_lmb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
350362d38c9bSGreg Kurz void *fdt, int *fdt_start_offset, Error **errp)
350462d38c9bSGreg Kurz {
350562d38c9bSGreg Kurz uint64_t addr;
350662d38c9bSGreg Kurz uint32_t node;
350762d38c9bSGreg Kurz
350862d38c9bSGreg Kurz addr = spapr_drc_index(drc) * SPAPR_MEMORY_BLOCK_SIZE;
350962d38c9bSGreg Kurz node = object_property_get_uint(OBJECT(drc->dev), PC_DIMM_NODE_PROP,
351062d38c9bSGreg Kurz &error_abort);
3511f1aa45ffSDaniel Henrique Barboza *fdt_start_offset = spapr_dt_memory_node(spapr, fdt, node, addr,
351262d38c9bSGreg Kurz SPAPR_MEMORY_BLOCK_SIZE);
351362d38c9bSGreg Kurz return 0;
351462d38c9bSGreg Kurz }
351562d38c9bSGreg Kurz
spapr_add_lmbs(DeviceState * dev,uint64_t addr_start,uint64_t size,bool dedicated_hp_event_source)3516ea042c53SGreg Kurz static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
3517ea042c53SGreg Kurz bool dedicated_hp_event_source)
3518c20d332aSBharata B Rao {
3519ce2918cbSDavid Gibson SpaprDrc *drc;
3520c20d332aSBharata B Rao uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE;
352162d38c9bSGreg Kurz int i;
352279b78a6bSMichael Roth uint64_t addr = addr_start;
352394fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev);
3524c20d332aSBharata B Rao
3525c20d332aSBharata B Rao for (i = 0; i < nr_lmbs; i++) {
3526fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
3527c20d332aSBharata B Rao addr / SPAPR_MEMORY_BLOCK_SIZE);
3528c20d332aSBharata B Rao g_assert(drc);
3529c20d332aSBharata B Rao
3530ea042c53SGreg Kurz /*
3531ea042c53SGreg Kurz * memory_device_get_free_addr() provided a range of free addresses
3532ea042c53SGreg Kurz * that doesn't overlap with any existing mapping at pre-plug. The
3533ea042c53SGreg Kurz * corresponding LMB DRCs are thus assumed to be all attachable.
3534ea042c53SGreg Kurz */
3535bc370a65SGreg Kurz spapr_drc_attach(drc, dev);
353694fd9cbaSLaurent Vivier if (!hotplugged) {
353794fd9cbaSLaurent Vivier spapr_drc_reset(drc);
353894fd9cbaSLaurent Vivier }
3539c20d332aSBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE;
3540c20d332aSBharata B Rao }
35415dd5238cSJianjun Duan /* send hotplug notification to the
35425dd5238cSJianjun Duan * guest only in case of hotplugged memory
35435dd5238cSJianjun Duan */
354494fd9cbaSLaurent Vivier if (hotplugged) {
354579b78a6bSMichael Roth if (dedicated_hp_event_source) {
3546fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
354779b78a6bSMichael Roth addr_start / SPAPR_MEMORY_BLOCK_SIZE);
354873231f7cSGreg Kurz g_assert(drc);
354979b78a6bSMichael Roth spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB,
355079b78a6bSMichael Roth nr_lmbs,
35510b55aa91SDavid Gibson spapr_drc_index(drc));
355279b78a6bSMichael Roth } else {
355379b78a6bSMichael Roth spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB,
355479b78a6bSMichael Roth nr_lmbs);
355579b78a6bSMichael Roth }
3556c20d332aSBharata B Rao }
35575dd5238cSJianjun Duan }
3558c20d332aSBharata B Rao
spapr_memory_plug(HotplugHandler * hotplug_dev,DeviceState * dev)3559ea042c53SGreg Kurz static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
3560c20d332aSBharata B Rao {
3561ce2918cbSDavid Gibson SpaprMachineState *ms = SPAPR_MACHINE(hotplug_dev);
3562c20d332aSBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev);
3563581778ddSGreg Kurz uint64_t size, addr;
3564581778ddSGreg Kurz int64_t slot;
3565ee3a71e3SShivaprasad G Bhat bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
356604790978SThomas Huth
3567946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dev), &error_abort);
3568df587133SThomas Huth
356984fd5496SGreg Kurz pc_dimm_plug(dimm, MACHINE(ms));
3570c20d332aSBharata B Rao
3571ee3a71e3SShivaprasad G Bhat if (!is_nvdimm) {
35729ed442b8SMarc-André Lureau addr = object_property_get_uint(OBJECT(dimm),
3573271ced1dSGreg Kurz PC_DIMM_ADDR_PROP, &error_abort);
3574ea042c53SGreg Kurz spapr_add_lmbs(dev, addr, size,
3575ea042c53SGreg Kurz spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT));
3576ee3a71e3SShivaprasad G Bhat } else {
3577581778ddSGreg Kurz slot = object_property_get_int(OBJECT(dimm),
3578271ced1dSGreg Kurz PC_DIMM_SLOT_PROP, &error_abort);
3579581778ddSGreg Kurz /* We should have valid slot number at this point */
3580581778ddSGreg Kurz g_assert(slot >= 0);
3581ea042c53SGreg Kurz spapr_add_nvdimm(dev, slot);
3582160bb678SGreg Kurz }
35836e837f98SGreg Kurz }
3584c20d332aSBharata B Rao
spapr_memory_pre_plug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)3585c871bc70SLaurent Vivier static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
3586c871bc70SLaurent Vivier Error **errp)
3587c871bc70SLaurent Vivier {
3588ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
3589ee3a71e3SShivaprasad G Bhat bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
3590c871bc70SLaurent Vivier PCDIMMDevice *dimm = PC_DIMM(dev);
35918f1ffe5bSDavid Hildenbrand Error *local_err = NULL;
359204790978SThomas Huth uint64_t size;
3593123eec65SDavid Gibson Object *memdev;
3594123eec65SDavid Gibson hwaddr pagesize;
3595c871bc70SLaurent Vivier
3596946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &local_err);
3597946d6154SDavid Hildenbrand if (local_err) {
3598946d6154SDavid Hildenbrand error_propagate(errp, local_err);
359904790978SThomas Huth return;
360004790978SThomas Huth }
360104790978SThomas Huth
3602beb6073fSDaniel Henrique Barboza if (is_nvdimm) {
3603451c6905SGreg Kurz if (!spapr_nvdimm_validate(hotplug_dev, NVDIMM(dev), size, errp)) {
3604ee3a71e3SShivaprasad G Bhat return;
3605ee3a71e3SShivaprasad G Bhat }
3606beb6073fSDaniel Henrique Barboza } else if (size % SPAPR_MEMORY_BLOCK_SIZE) {
3607beb6073fSDaniel Henrique Barboza error_setg(errp, "Hotplugged memory size must be a multiple of "
3608beb6073fSDaniel Henrique Barboza "%" PRIu64 " MB", SPAPR_MEMORY_BLOCK_SIZE / MiB);
3609beb6073fSDaniel Henrique Barboza return;
3610c871bc70SLaurent Vivier }
3611c871bc70SLaurent Vivier
3612123eec65SDavid Gibson memdev = object_property_get_link(OBJECT(dimm), PC_DIMM_MEMDEV_PROP,
3613123eec65SDavid Gibson &error_abort);
3614123eec65SDavid Gibson pagesize = host_memory_backend_pagesize(MEMORY_BACKEND(memdev));
361535dce34fSGreg Kurz if (!spapr_check_pagesize(spapr, pagesize, errp)) {
36168f1ffe5bSDavid Hildenbrand return;
36178f1ffe5bSDavid Hildenbrand }
36188f1ffe5bSDavid Hildenbrand
3619d4fdb05bSPhilippe Mathieu-Daudé pc_dimm_pre_plug(dimm, MACHINE(hotplug_dev), errp);
3620c871bc70SLaurent Vivier }
3621c871bc70SLaurent Vivier
3622ce2918cbSDavid Gibson struct SpaprDimmState {
36230cffce56SDavid Gibson PCDIMMDevice *dimm;
3624cf632463SBharata B Rao uint32_t nr_lmbs;
3625ce2918cbSDavid Gibson QTAILQ_ENTRY(SpaprDimmState) next;
36260cffce56SDavid Gibson };
36270cffce56SDavid Gibson
spapr_pending_dimm_unplugs_find(SpaprMachineState * s,PCDIMMDevice * dimm)3628ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_find(SpaprMachineState *s,
36290cffce56SDavid Gibson PCDIMMDevice *dimm)
36300cffce56SDavid Gibson {
3631ce2918cbSDavid Gibson SpaprDimmState *dimm_state = NULL;
36320cffce56SDavid Gibson
36330cffce56SDavid Gibson QTAILQ_FOREACH(dimm_state, &s->pending_dimm_unplugs, next) {
36340cffce56SDavid Gibson if (dimm_state->dimm == dimm) {
36350cffce56SDavid Gibson break;
36360cffce56SDavid Gibson }
36370cffce56SDavid Gibson }
36380cffce56SDavid Gibson return dimm_state;
36390cffce56SDavid Gibson }
36400cffce56SDavid Gibson
spapr_pending_dimm_unplugs_add(SpaprMachineState * spapr,uint32_t nr_lmbs,PCDIMMDevice * dimm)3641ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_add(SpaprMachineState *spapr,
36428d5981c4SBharata B Rao uint32_t nr_lmbs,
36438d5981c4SBharata B Rao PCDIMMDevice *dimm)
36440cffce56SDavid Gibson {
3645ce2918cbSDavid Gibson SpaprDimmState *ds = NULL;
36468d5981c4SBharata B Rao
36478d5981c4SBharata B Rao /*
36488d5981c4SBharata B Rao * If this request is for a DIMM whose removal had failed earlier
36498d5981c4SBharata B Rao * (due to guest's refusal to remove the LMBs), we would have this
36508d5981c4SBharata B Rao * dimm already in the pending_dimm_unplugs list. In that
36518d5981c4SBharata B Rao * case don't add again.
36528d5981c4SBharata B Rao */
36538d5981c4SBharata B Rao ds = spapr_pending_dimm_unplugs_find(spapr, dimm);
36548d5981c4SBharata B Rao if (!ds) {
3655b21e2380SMarkus Armbruster ds = g_new0(SpaprDimmState, 1);
36568d5981c4SBharata B Rao ds->nr_lmbs = nr_lmbs;
36578d5981c4SBharata B Rao ds->dimm = dimm;
36588d5981c4SBharata B Rao QTAILQ_INSERT_HEAD(&spapr->pending_dimm_unplugs, ds, next);
36598d5981c4SBharata B Rao }
36608d5981c4SBharata B Rao return ds;
36610cffce56SDavid Gibson }
36620cffce56SDavid Gibson
spapr_pending_dimm_unplugs_remove(SpaprMachineState * spapr,SpaprDimmState * dimm_state)3663ce2918cbSDavid Gibson static void spapr_pending_dimm_unplugs_remove(SpaprMachineState *spapr,
3664ce2918cbSDavid Gibson SpaprDimmState *dimm_state)
36650cffce56SDavid Gibson {
36660cffce56SDavid Gibson QTAILQ_REMOVE(&spapr->pending_dimm_unplugs, dimm_state, next);
36670cffce56SDavid Gibson g_free(dimm_state);
36680cffce56SDavid Gibson }
3669cf632463SBharata B Rao
spapr_recover_pending_dimm_state(SpaprMachineState * ms,PCDIMMDevice * dimm)3670ce2918cbSDavid Gibson static SpaprDimmState *spapr_recover_pending_dimm_state(SpaprMachineState *ms,
367116ee9980SDaniel Henrique Barboza PCDIMMDevice *dimm)
367216ee9980SDaniel Henrique Barboza {
3673ce2918cbSDavid Gibson SpaprDrc *drc;
3674946d6154SDavid Hildenbrand uint64_t size = memory_device_get_region_size(MEMORY_DEVICE(dimm),
3675946d6154SDavid Hildenbrand &error_abort);
367616ee9980SDaniel Henrique Barboza uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE;
367716ee9980SDaniel Henrique Barboza uint32_t avail_lmbs = 0;
367816ee9980SDaniel Henrique Barboza uint64_t addr_start, addr;
367916ee9980SDaniel Henrique Barboza int i;
368016ee9980SDaniel Henrique Barboza
368165226afdSGreg Kurz addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP,
368216ee9980SDaniel Henrique Barboza &error_abort);
368316ee9980SDaniel Henrique Barboza
368416ee9980SDaniel Henrique Barboza addr = addr_start;
368516ee9980SDaniel Henrique Barboza for (i = 0; i < nr_lmbs; i++) {
3686fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
368716ee9980SDaniel Henrique Barboza addr / SPAPR_MEMORY_BLOCK_SIZE);
368816ee9980SDaniel Henrique Barboza g_assert(drc);
3689454b580aSDavid Gibson if (drc->dev) {
369016ee9980SDaniel Henrique Barboza avail_lmbs++;
369116ee9980SDaniel Henrique Barboza }
369216ee9980SDaniel Henrique Barboza addr += SPAPR_MEMORY_BLOCK_SIZE;
369316ee9980SDaniel Henrique Barboza }
369416ee9980SDaniel Henrique Barboza
36958d5981c4SBharata B Rao return spapr_pending_dimm_unplugs_add(ms, avail_lmbs, dimm);
369616ee9980SDaniel Henrique Barboza }
369716ee9980SDaniel Henrique Barboza
spapr_memory_unplug_rollback(SpaprMachineState * spapr,DeviceState * dev)3698eb7f80fdSDaniel Henrique Barboza void spapr_memory_unplug_rollback(SpaprMachineState *spapr, DeviceState *dev)
3699fe1831efSDaniel Henrique Barboza {
3700fe1831efSDaniel Henrique Barboza SpaprDimmState *ds;
3701fe1831efSDaniel Henrique Barboza PCDIMMDevice *dimm;
3702fe1831efSDaniel Henrique Barboza SpaprDrc *drc;
3703fe1831efSDaniel Henrique Barboza uint32_t nr_lmbs;
3704fe1831efSDaniel Henrique Barboza uint64_t size, addr_start, addr;
3705fe1831efSDaniel Henrique Barboza int i;
3706fe1831efSDaniel Henrique Barboza
3707fe1831efSDaniel Henrique Barboza if (!dev) {
3708fe1831efSDaniel Henrique Barboza return;
3709fe1831efSDaniel Henrique Barboza }
3710fe1831efSDaniel Henrique Barboza
3711fe1831efSDaniel Henrique Barboza dimm = PC_DIMM(dev);
3712fe1831efSDaniel Henrique Barboza ds = spapr_pending_dimm_unplugs_find(spapr, dimm);
3713fe1831efSDaniel Henrique Barboza
3714fe1831efSDaniel Henrique Barboza /*
3715fe1831efSDaniel Henrique Barboza * 'ds == NULL' would mean that the DIMM doesn't have a pending
3716fe1831efSDaniel Henrique Barboza * unplug state, but one of its DRC is marked as unplug_requested.
3717fe1831efSDaniel Henrique Barboza * This is bad and weird enough to g_assert() out.
3718fe1831efSDaniel Henrique Barboza */
3719fe1831efSDaniel Henrique Barboza g_assert(ds);
3720fe1831efSDaniel Henrique Barboza
3721fe1831efSDaniel Henrique Barboza spapr_pending_dimm_unplugs_remove(spapr, ds);
3722fe1831efSDaniel Henrique Barboza
3723fe1831efSDaniel Henrique Barboza size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &error_abort);
3724fe1831efSDaniel Henrique Barboza nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE;
3725fe1831efSDaniel Henrique Barboza
3726fe1831efSDaniel Henrique Barboza addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP,
3727fe1831efSDaniel Henrique Barboza &error_abort);
3728fe1831efSDaniel Henrique Barboza
3729fe1831efSDaniel Henrique Barboza addr = addr_start;
3730fe1831efSDaniel Henrique Barboza for (i = 0; i < nr_lmbs; i++) {
3731fe1831efSDaniel Henrique Barboza drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
3732fe1831efSDaniel Henrique Barboza addr / SPAPR_MEMORY_BLOCK_SIZE);
3733fe1831efSDaniel Henrique Barboza g_assert(drc);
3734fe1831efSDaniel Henrique Barboza
3735fe1831efSDaniel Henrique Barboza drc->unplug_requested = false;
3736fe1831efSDaniel Henrique Barboza addr += SPAPR_MEMORY_BLOCK_SIZE;
3737fe1831efSDaniel Henrique Barboza }
3738eb7f80fdSDaniel Henrique Barboza
3739eb7f80fdSDaniel Henrique Barboza /*
3740eb7f80fdSDaniel Henrique Barboza * Tell QAPI that something happened and the memory
37410f910b87SPhilippe Mathieu-Daudé * hotunplug wasn't successful.
3742eb7f80fdSDaniel Henrique Barboza */
3743047f2ca1SMarkus Armbruster qapi_event_send_device_unplug_guest_error(dev->id,
37444b08cd56SDaniel Henrique Barboza dev->canonical_path);
3745fe1831efSDaniel Henrique Barboza }
3746fe1831efSDaniel Henrique Barboza
374731834723SDaniel Henrique Barboza /* Callback to be called during DRC release. */
spapr_lmb_release(DeviceState * dev)374831834723SDaniel Henrique Barboza void spapr_lmb_release(DeviceState *dev)
3749cf632463SBharata B Rao {
37503ec71474SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
3751ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl);
3752ce2918cbSDavid Gibson SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
3753cf632463SBharata B Rao
375416ee9980SDaniel Henrique Barboza /* This information will get lost if a migration occurs
375516ee9980SDaniel Henrique Barboza * during the unplug process. In this case recover it. */
375616ee9980SDaniel Henrique Barboza if (ds == NULL) {
375716ee9980SDaniel Henrique Barboza ds = spapr_recover_pending_dimm_state(spapr, PC_DIMM(dev));
37588d5981c4SBharata B Rao g_assert(ds);
3759454b580aSDavid Gibson /* The DRC being examined by the caller at least must be counted */
3760454b580aSDavid Gibson g_assert(ds->nr_lmbs);
376116ee9980SDaniel Henrique Barboza }
3762454b580aSDavid Gibson
3763454b580aSDavid Gibson if (--ds->nr_lmbs) {
3764cf632463SBharata B Rao return;
3765cf632463SBharata B Rao }
3766cf632463SBharata B Rao
3767cf632463SBharata B Rao /*
3768cf632463SBharata B Rao * Now that all the LMBs have been removed by the guest, call the
37693ec71474SDavid Hildenbrand * unplug handler chain. This can never fail.
3770cf632463SBharata B Rao */
37713ec71474SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
377207578b0aSDavid Hildenbrand object_unparent(OBJECT(dev));
37733ec71474SDavid Hildenbrand }
37743ec71474SDavid Hildenbrand
spapr_memory_unplug(HotplugHandler * hotplug_dev,DeviceState * dev)37753ec71474SDavid Hildenbrand static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
37763ec71474SDavid Hildenbrand {
3777ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
3778ce2918cbSDavid Gibson SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
37793ec71474SDavid Hildenbrand
3780df2d7ca7SGreg Kurz /* We really shouldn't get this far without anything to unplug */
3781df2d7ca7SGreg Kurz g_assert(ds);
3782df2d7ca7SGreg Kurz
3783fd3416f5SDavid Hildenbrand pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev));
3784981c3dcdSMarkus Armbruster qdev_unrealize(dev);
37852a129767SDaniel Henrique Barboza spapr_pending_dimm_unplugs_remove(spapr, ds);
3786cf632463SBharata B Rao }
3787cf632463SBharata B Rao
spapr_memory_unplug_request(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)3788cf632463SBharata B Rao static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
3789cf632463SBharata B Rao DeviceState *dev, Error **errp)
3790cf632463SBharata B Rao {
3791ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
3792cf632463SBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev);
379304790978SThomas Huth uint32_t nr_lmbs;
379404790978SThomas Huth uint64_t size, addr_start, addr;
37950cffce56SDavid Gibson int i;
3796ce2918cbSDavid Gibson SpaprDrc *drc;
379704790978SThomas Huth
3798ee3a71e3SShivaprasad G Bhat if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
3799dcfe4805SMarkus Armbruster error_setg(errp, "nvdimm device hot unplug is not supported yet.");
3800dcfe4805SMarkus Armbruster return;
3801ee3a71e3SShivaprasad G Bhat }
3802ee3a71e3SShivaprasad G Bhat
3803946d6154SDavid Hildenbrand size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &error_abort);
380404790978SThomas Huth nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE;
380504790978SThomas Huth
38069ed442b8SMarc-André Lureau addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP,
3807271ced1dSGreg Kurz &error_abort);
3808cf632463SBharata B Rao
38092a129767SDaniel Henrique Barboza /*
38102a129767SDaniel Henrique Barboza * An existing pending dimm state for this DIMM means that there is an
38112a129767SDaniel Henrique Barboza * unplug operation in progress, waiting for the spapr_lmb_release
38122a129767SDaniel Henrique Barboza * callback to complete the job (BQL can't cover that far). In this case,
38132a129767SDaniel Henrique Barboza * bail out to avoid detaching DRCs that were already released.
38142a129767SDaniel Henrique Barboza */
38152a129767SDaniel Henrique Barboza if (spapr_pending_dimm_unplugs_find(spapr, dimm)) {
3816dcfe4805SMarkus Armbruster error_setg(errp, "Memory unplug already in progress for device %s",
38172a129767SDaniel Henrique Barboza dev->id);
3818dcfe4805SMarkus Armbruster return;
38192a129767SDaniel Henrique Barboza }
38202a129767SDaniel Henrique Barboza
38218d5981c4SBharata B Rao spapr_pending_dimm_unplugs_add(spapr, nr_lmbs, dimm);
38220cffce56SDavid Gibson
38230cffce56SDavid Gibson addr = addr_start;
38240cffce56SDavid Gibson for (i = 0; i < nr_lmbs; i++) {
3825fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
38260cffce56SDavid Gibson addr / SPAPR_MEMORY_BLOCK_SIZE);
38270cffce56SDavid Gibson g_assert(drc);
38280cffce56SDavid Gibson
3829a03509cdSDaniel Henrique Barboza spapr_drc_unplug_request(drc);
38300cffce56SDavid Gibson addr += SPAPR_MEMORY_BLOCK_SIZE;
38310cffce56SDavid Gibson }
38320cffce56SDavid Gibson
3833fbf55397SDavid Gibson drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
38340cffce56SDavid Gibson addr_start / SPAPR_MEMORY_BLOCK_SIZE);
38350cffce56SDavid Gibson spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB,
38360b55aa91SDavid Gibson nr_lmbs, spapr_drc_index(drc));
3837cf632463SBharata B Rao }
3838cf632463SBharata B Rao
3839765d1bddSDavid Gibson /* Callback to be called during DRC release. */
spapr_core_release(DeviceState * dev)3840765d1bddSDavid Gibson void spapr_core_release(DeviceState *dev)
3841ff9006ddSIgor Mammedov {
3842a4261be1SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
3843a4261be1SDavid Hildenbrand
3844a4261be1SDavid Hildenbrand /* Call the unplug handler chain. This can never fail. */
3845a4261be1SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
384607578b0aSDavid Hildenbrand object_unparent(OBJECT(dev));
3847a4261be1SDavid Hildenbrand }
3848a4261be1SDavid Hildenbrand
spapr_core_unplug(HotplugHandler * hotplug_dev,DeviceState * dev)3849a4261be1SDavid Hildenbrand static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
3850a4261be1SDavid Hildenbrand {
3851a4261be1SDavid Hildenbrand MachineState *ms = MACHINE(hotplug_dev);
3852ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev);
3853535455fdSIgor Mammedov CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL);
3854ff9006ddSIgor Mammedov
385507572c06SGreg Kurz assert(core_slot);
3856535455fdSIgor Mammedov core_slot->cpu = NULL;
3857981c3dcdSMarkus Armbruster qdev_unrealize(dev);
3858ff9006ddSIgor Mammedov }
3859ff9006ddSIgor Mammedov
3860115debf2SIgor Mammedov static
spapr_core_unplug_request(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)3861115debf2SIgor Mammedov void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev,
3862ff9006ddSIgor Mammedov Error **errp)
3863ff9006ddSIgor Mammedov {
3864ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
3865535455fdSIgor Mammedov int index;
3866ce2918cbSDavid Gibson SpaprDrc *drc;
3867535455fdSIgor Mammedov CPUCore *cc = CPU_CORE(dev);
3868ff9006ddSIgor Mammedov
3869535455fdSIgor Mammedov if (!spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index)) {
3870535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d",
3871535455fdSIgor Mammedov cc->core_id);
3872535455fdSIgor Mammedov return;
3873535455fdSIgor Mammedov }
3874ff9006ddSIgor Mammedov if (index == 0) {
3875ff9006ddSIgor Mammedov error_setg(errp, "Boot CPU core may not be unplugged");
3876ff9006ddSIgor Mammedov return;
3877ff9006ddSIgor Mammedov }
3878ff9006ddSIgor Mammedov
38795d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU,
38805d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id));
3881ff9006ddSIgor Mammedov g_assert(drc);
3882ff9006ddSIgor Mammedov
388347c8c915SGreg Kurz if (!spapr_drc_unplug_requested(drc)) {
3884a03509cdSDaniel Henrique Barboza spapr_drc_unplug_request(drc);
3885ff9006ddSIgor Mammedov }
38862b18fc79SDaniel Henrique Barboza
38872b18fc79SDaniel Henrique Barboza /*
38882b18fc79SDaniel Henrique Barboza * spapr_hotplug_req_remove_by_index is left unguarded, out of the
38892b18fc79SDaniel Henrique Barboza * "!spapr_drc_unplug_requested" check, to allow for multiple IRQ
38902b18fc79SDaniel Henrique Barboza * pulses removing the same CPU. Otherwise, in an failed hotunplug
38912b18fc79SDaniel Henrique Barboza * attempt (e.g. the kernel will refuse to remove the last online
38922b18fc79SDaniel Henrique Barboza * CPU), we will never attempt it again because unplug_requested
38932b18fc79SDaniel Henrique Barboza * will still be 'true' in that case.
38942b18fc79SDaniel Henrique Barboza */
38952b18fc79SDaniel Henrique Barboza spapr_hotplug_req_remove_by_index(drc);
389647c8c915SGreg Kurz }
3897ff9006ddSIgor Mammedov
spapr_core_dt_populate(SpaprDrc * drc,SpaprMachineState * spapr,void * fdt,int * fdt_start_offset,Error ** errp)3898ce2918cbSDavid Gibson int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
3899345b12b9SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp)
3900345b12b9SGreg Kurz {
3901ce2918cbSDavid Gibson SpaprCpuCore *core = SPAPR_CPU_CORE(drc->dev);
3902345b12b9SGreg Kurz CPUState *cs = CPU(core->threads[0]);
3903345b12b9SGreg Kurz PowerPCCPU *cpu = POWERPC_CPU(cs);
3904345b12b9SGreg Kurz DeviceClass *dc = DEVICE_GET_CLASS(cs);
3905345b12b9SGreg Kurz int id = spapr_get_vcpu_id(cpu);
39067265bc3eSDaniel Henrique Barboza g_autofree char *nodename = NULL;
3907345b12b9SGreg Kurz int offset;
3908345b12b9SGreg Kurz
3909345b12b9SGreg Kurz nodename = g_strdup_printf("%s@%x", dc->fw_name, id);
3910345b12b9SGreg Kurz offset = fdt_add_subnode(fdt, 0, nodename);
3911345b12b9SGreg Kurz
391291335a5eSDavid Gibson spapr_dt_cpu(cs, fdt, offset, spapr);
3913345b12b9SGreg Kurz
3914a85bb34eSDaniel Henrique Barboza /*
3915a85bb34eSDaniel Henrique Barboza * spapr_dt_cpu() does not fill the 'name' property in the
3916a85bb34eSDaniel Henrique Barboza * CPU node. The function is called during boot process, before
3917a85bb34eSDaniel Henrique Barboza * and after CAS, and overwriting the 'name' property written
3918a85bb34eSDaniel Henrique Barboza * by SLOF is not allowed.
3919a85bb34eSDaniel Henrique Barboza *
3920a85bb34eSDaniel Henrique Barboza * Write it manually after spapr_dt_cpu(). This makes the hotplug
3921a85bb34eSDaniel Henrique Barboza * CPUs more compatible with the coldplugged ones, which have
3922a85bb34eSDaniel Henrique Barboza * the 'name' property. Linux Kernel also relies on this
3923a85bb34eSDaniel Henrique Barboza * property to identify CPU nodes.
3924a85bb34eSDaniel Henrique Barboza */
3925a85bb34eSDaniel Henrique Barboza _FDT((fdt_setprop_string(fdt, offset, "name", nodename)));
3926a85bb34eSDaniel Henrique Barboza
3927345b12b9SGreg Kurz *fdt_start_offset = offset;
3928345b12b9SGreg Kurz return 0;
3929345b12b9SGreg Kurz }
3930345b12b9SGreg Kurz
spapr_core_plug(HotplugHandler * hotplug_dev,DeviceState * dev)3931f9b43958SGreg Kurz static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
3932ff9006ddSIgor Mammedov {
3933ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
3934ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(spapr);
3935ce2918cbSDavid Gibson SpaprCpuCore *core = SPAPR_CPU_CORE(OBJECT(dev));
3936ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev);
3937ce2918cbSDavid Gibson SpaprDrc *drc;
3938535455fdSIgor Mammedov CPUArchId *core_slot;
3939535455fdSIgor Mammedov int index;
394094fd9cbaSLaurent Vivier bool hotplugged = spapr_drc_hotplugged(dev);
3941b1e81567SGreg Kurz int i;
3942ff9006ddSIgor Mammedov
3943535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index);
3944f9b43958SGreg Kurz g_assert(core_slot); /* Already checked in spapr_core_pre_plug() */
3945f9b43958SGreg Kurz
39465d0fb150SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU,
39475d0fb150SGreg Kurz spapr_vcpu_id(spapr, cc->core_id));
3948ff9006ddSIgor Mammedov
3949c5514d0eSIgor Mammedov g_assert(drc || !mc->has_hotpluggable_cpus);
3950ff9006ddSIgor Mammedov
3951e49c63d5SGreg Kurz if (drc) {
3952f9b43958SGreg Kurz /*
3953f9b43958SGreg Kurz * spapr_core_pre_plug() already buys us this is a brand new
3954f9b43958SGreg Kurz * core being plugged into a free slot. Nothing should already
3955f9b43958SGreg Kurz * be attached to the corresponding DRC.
3956f9b43958SGreg Kurz */
3957bc370a65SGreg Kurz spapr_drc_attach(drc, dev);
3958ff9006ddSIgor Mammedov
395994fd9cbaSLaurent Vivier if (hotplugged) {
3960ff9006ddSIgor Mammedov /*
396194fd9cbaSLaurent Vivier * Send hotplug notification interrupt to the guest only
396294fd9cbaSLaurent Vivier * in case of hotplugged CPUs.
3963ff9006ddSIgor Mammedov */
3964ff9006ddSIgor Mammedov spapr_hotplug_req_add_by_index(drc);
396594fd9cbaSLaurent Vivier } else {
396694fd9cbaSLaurent Vivier spapr_drc_reset(drc);
3967ff9006ddSIgor Mammedov }
396894fd9cbaSLaurent Vivier }
396994fd9cbaSLaurent Vivier
397097e03106SPhilippe Mathieu-Daudé core_slot->cpu = CPU(dev);
397146f7afa3SGreg Kurz
3972b1e81567SGreg Kurz /*
3973b1e81567SGreg Kurz * Set compatibility mode to match the boot CPU, which was either set
397437641213SGreg Kurz * by the machine reset code or by CAS. This really shouldn't fail at
397537641213SGreg Kurz * this point.
3976b1e81567SGreg Kurz */
3977b1e81567SGreg Kurz if (hotplugged) {
3978b1e81567SGreg Kurz for (i = 0; i < cc->nr_threads; i++) {
397937641213SGreg Kurz ppc_set_compat(core->threads[i], POWERPC_CPU(first_cpu)->compat_pvr,
398037641213SGreg Kurz &error_abort);
3981b1e81567SGreg Kurz }
3982b1e81567SGreg Kurz }
39831b4ab514SGreg Kurz
3984ff9006ddSIgor Mammedov }
3985ff9006ddSIgor Mammedov
spapr_core_pre_plug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)3986ff9006ddSIgor Mammedov static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
3987ff9006ddSIgor Mammedov Error **errp)
3988ff9006ddSIgor Mammedov {
3989ff9006ddSIgor Mammedov MachineState *machine = MACHINE(OBJECT(hotplug_dev));
3990ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev);
3991ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev);
39922e9c10ebSIgor Mammedov const char *base_core_type = spapr_get_cpu_core_type(machine->cpu_type);
3993ff9006ddSIgor Mammedov const char *type = object_get_typename(OBJECT(dev));
3994535455fdSIgor Mammedov CPUArchId *core_slot;
3995535455fdSIgor Mammedov int index;
3996fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads;
3997ff9006ddSIgor Mammedov
3998c5514d0eSIgor Mammedov if (dev->hotplugged && !mc->has_hotpluggable_cpus) {
3999dcfe4805SMarkus Armbruster error_setg(errp, "CPU hotplug not supported for this machine");
4000dcfe4805SMarkus Armbruster return;
4001ff9006ddSIgor Mammedov }
4002ff9006ddSIgor Mammedov
4003ff9006ddSIgor Mammedov if (strcmp(base_core_type, type)) {
4004dcfe4805SMarkus Armbruster error_setg(errp, "CPU core type should be %s", base_core_type);
4005dcfe4805SMarkus Armbruster return;
4006ff9006ddSIgor Mammedov }
4007ff9006ddSIgor Mammedov
4008ff9006ddSIgor Mammedov if (cc->core_id % smp_threads) {
4009dcfe4805SMarkus Armbruster error_setg(errp, "invalid core id %d", cc->core_id);
4010dcfe4805SMarkus Armbruster return;
4011ff9006ddSIgor Mammedov }
4012ff9006ddSIgor Mammedov
4013459264efSDavid Gibson /*
4014459264efSDavid Gibson * In general we should have homogeneous threads-per-core, but old
4015459264efSDavid Gibson * (pre hotplug support) machine types allow the last core to have
4016459264efSDavid Gibson * reduced threads as a compatibility hack for when we allowed
4017459264efSDavid Gibson * total vcpus not a multiple of threads-per-core.
4018459264efSDavid Gibson */
4019459264efSDavid Gibson if (mc->has_hotpluggable_cpus && (cc->nr_threads != smp_threads)) {
4020dcfe4805SMarkus Armbruster error_setg(errp, "invalid nr-threads %d, must be %d", cc->nr_threads,
4021dcfe4805SMarkus Armbruster smp_threads);
4022dcfe4805SMarkus Armbruster return;
40238149e299SDavid Gibson }
40248149e299SDavid Gibson
4025535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index);
4026535455fdSIgor Mammedov if (!core_slot) {
4027dcfe4805SMarkus Armbruster error_setg(errp, "core id %d out of range", cc->core_id);
4028dcfe4805SMarkus Armbruster return;
4029ff9006ddSIgor Mammedov }
4030ff9006ddSIgor Mammedov
4031535455fdSIgor Mammedov if (core_slot->cpu) {
4032dcfe4805SMarkus Armbruster error_setg(errp, "core %d already populated", cc->core_id);
4033dcfe4805SMarkus Armbruster return;
4034ff9006ddSIgor Mammedov }
4035ff9006ddSIgor Mammedov
4036dcfe4805SMarkus Armbruster numa_cpu_pre_plug(core_slot, dev, errp);
4037ff9006ddSIgor Mammedov }
4038ff9006ddSIgor Mammedov
spapr_phb_dt_populate(SpaprDrc * drc,SpaprMachineState * spapr,void * fdt,int * fdt_start_offset,Error ** errp)4039ce2918cbSDavid Gibson int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
4040bb2bdd81SGreg Kurz void *fdt, int *fdt_start_offset, Error **errp)
4041bb2bdd81SGreg Kurz {
4042ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(drc->dev);
4043bb2bdd81SGreg Kurz int intc_phandle;
4044bb2bdd81SGreg Kurz
4045bb2bdd81SGreg Kurz intc_phandle = spapr_irq_get_phandle(spapr, spapr->fdt_blob, errp);
4046bb2bdd81SGreg Kurz if (intc_phandle <= 0) {
4047bb2bdd81SGreg Kurz return -1;
4048bb2bdd81SGreg Kurz }
4049bb2bdd81SGreg Kurz
40508cbe71ecSDavid Gibson if (spapr_dt_phb(spapr, sphb, intc_phandle, fdt, fdt_start_offset)) {
4051bb2bdd81SGreg Kurz error_setg(errp, "unable to create FDT node for PHB %d", sphb->index);
4052bb2bdd81SGreg Kurz return -1;
4053bb2bdd81SGreg Kurz }
4054bb2bdd81SGreg Kurz
4055bb2bdd81SGreg Kurz /* generally SLOF creates these, for hotplug it's up to QEMU */
4056bb2bdd81SGreg Kurz _FDT(fdt_setprop_string(fdt, *fdt_start_offset, "name", "pci"));
4057bb2bdd81SGreg Kurz
4058bb2bdd81SGreg Kurz return 0;
4059bb2bdd81SGreg Kurz }
4060bb2bdd81SGreg Kurz
spapr_phb_pre_plug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)4061f5598c92SGreg Kurz static bool spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
4062bb2bdd81SGreg Kurz Error **errp)
4063bb2bdd81SGreg Kurz {
4064ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
4065ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
4066ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
4067bb2bdd81SGreg Kurz const unsigned windows_supported = spapr_phb_windows_supported(sphb);
40689a070699SGreg Kurz SpaprDrc *drc;
4069bb2bdd81SGreg Kurz
4070bb2bdd81SGreg Kurz if (dev->hotplugged && !smc->dr_phb_enabled) {
4071bb2bdd81SGreg Kurz error_setg(errp, "PHB hotplug not supported for this machine");
4072f5598c92SGreg Kurz return false;
4073bb2bdd81SGreg Kurz }
4074bb2bdd81SGreg Kurz
4075bb2bdd81SGreg Kurz if (sphb->index == (uint32_t)-1) {
4076bb2bdd81SGreg Kurz error_setg(errp, "\"index\" for PAPR PHB is mandatory");
4077f5598c92SGreg Kurz return false;
4078bb2bdd81SGreg Kurz }
4079bb2bdd81SGreg Kurz
40809a070699SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index);
40819a070699SGreg Kurz if (drc && drc->dev) {
40829a070699SGreg Kurz error_setg(errp, "PHB %d already attached", sphb->index);
40839a070699SGreg Kurz return false;
40849a070699SGreg Kurz }
40859a070699SGreg Kurz
4086bb2bdd81SGreg Kurz /*
4087bb2bdd81SGreg Kurz * This will check that sphb->index doesn't exceed the maximum number of
4088bb2bdd81SGreg Kurz * PHBs for the current machine type.
4089bb2bdd81SGreg Kurz */
4090f5598c92SGreg Kurz return
4091bb2bdd81SGreg Kurz smc->phb_placement(spapr, sphb->index,
4092bb2bdd81SGreg Kurz &sphb->buid, &sphb->io_win_addr,
4093bb2bdd81SGreg Kurz &sphb->mem_win_addr, &sphb->mem64_win_addr,
4094ec132efaSAlexey Kardashevskiy windows_supported, sphb->dma_liobn,
4095ec132efaSAlexey Kardashevskiy errp);
4096bb2bdd81SGreg Kurz }
4097bb2bdd81SGreg Kurz
spapr_phb_plug(HotplugHandler * hotplug_dev,DeviceState * dev)40989a070699SGreg Kurz static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
4099bb2bdd81SGreg Kurz {
4100ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
4101ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
4102ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
4103ce2918cbSDavid Gibson SpaprDrc *drc;
4104bb2bdd81SGreg Kurz bool hotplugged = spapr_drc_hotplugged(dev);
4105bb2bdd81SGreg Kurz
4106bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) {
4107bb2bdd81SGreg Kurz return;
4108bb2bdd81SGreg Kurz }
4109bb2bdd81SGreg Kurz
4110bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index);
4111bb2bdd81SGreg Kurz /* hotplug hooks should check it's enabled before getting this far */
4112bb2bdd81SGreg Kurz assert(drc);
4113bb2bdd81SGreg Kurz
41149a070699SGreg Kurz /* spapr_phb_pre_plug() already checked the DRC is attachable */
4115bc370a65SGreg Kurz spapr_drc_attach(drc, dev);
4116bb2bdd81SGreg Kurz
4117bb2bdd81SGreg Kurz if (hotplugged) {
4118bb2bdd81SGreg Kurz spapr_hotplug_req_add_by_index(drc);
4119bb2bdd81SGreg Kurz } else {
4120bb2bdd81SGreg Kurz spapr_drc_reset(drc);
4121bb2bdd81SGreg Kurz }
4122bb2bdd81SGreg Kurz }
4123bb2bdd81SGreg Kurz
spapr_phb_release(DeviceState * dev)4124bb2bdd81SGreg Kurz void spapr_phb_release(DeviceState *dev)
4125bb2bdd81SGreg Kurz {
4126bb2bdd81SGreg Kurz HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
4127bb2bdd81SGreg Kurz
4128bb2bdd81SGreg Kurz hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
412907578b0aSDavid Hildenbrand object_unparent(OBJECT(dev));
4130bb2bdd81SGreg Kurz }
4131bb2bdd81SGreg Kurz
spapr_phb_unplug(HotplugHandler * hotplug_dev,DeviceState * dev)4132bb2bdd81SGreg Kurz static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
4133bb2bdd81SGreg Kurz {
4134981c3dcdSMarkus Armbruster qdev_unrealize(dev);
4135bb2bdd81SGreg Kurz }
4136bb2bdd81SGreg Kurz
spapr_phb_unplug_request(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)4137bb2bdd81SGreg Kurz static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev,
4138bb2bdd81SGreg Kurz DeviceState *dev, Error **errp)
4139bb2bdd81SGreg Kurz {
4140ce2918cbSDavid Gibson SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
4141ce2918cbSDavid Gibson SpaprDrc *drc;
4142bb2bdd81SGreg Kurz
4143bb2bdd81SGreg Kurz drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index);
4144bb2bdd81SGreg Kurz assert(drc);
4145bb2bdd81SGreg Kurz
4146bb2bdd81SGreg Kurz if (!spapr_drc_unplug_requested(drc)) {
4147a03509cdSDaniel Henrique Barboza spapr_drc_unplug_request(drc);
4148bb2bdd81SGreg Kurz spapr_hotplug_req_remove_by_index(drc);
41497420033eSDaniel Henrique Barboza } else {
41507420033eSDaniel Henrique Barboza error_setg(errp,
41517420033eSDaniel Henrique Barboza "PCI Host Bridge unplug already in progress for device %s",
41527420033eSDaniel Henrique Barboza dev->id);
4153bb2bdd81SGreg Kurz }
4154bb2bdd81SGreg Kurz }
4155bb2bdd81SGreg Kurz
4156ac96807bSGreg Kurz static
spapr_tpm_proxy_pre_plug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)4157ac96807bSGreg Kurz bool spapr_tpm_proxy_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
41580fb6bd07SMichael Roth Error **errp)
41590fb6bd07SMichael Roth {
41600fb6bd07SMichael Roth SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
4161ac96807bSGreg Kurz
4162ac96807bSGreg Kurz if (spapr->tpm_proxy != NULL) {
4163ac96807bSGreg Kurz error_setg(errp, "Only one TPM proxy can be specified for this machine");
4164ac96807bSGreg Kurz return false;
4165ac96807bSGreg Kurz }
4166ac96807bSGreg Kurz
4167ac96807bSGreg Kurz return true;
4168ac96807bSGreg Kurz }
4169ac96807bSGreg Kurz
spapr_tpm_proxy_plug(HotplugHandler * hotplug_dev,DeviceState * dev)4170ac96807bSGreg Kurz static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
4171ac96807bSGreg Kurz {
4172ac96807bSGreg Kurz SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
41730fb6bd07SMichael Roth SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(dev);
41740fb6bd07SMichael Roth
4175ac96807bSGreg Kurz /* Already checked in spapr_tpm_proxy_pre_plug() */
4176ac96807bSGreg Kurz g_assert(spapr->tpm_proxy == NULL);
41770fb6bd07SMichael Roth
41780fb6bd07SMichael Roth spapr->tpm_proxy = tpm_proxy;
41790fb6bd07SMichael Roth }
41800fb6bd07SMichael Roth
spapr_tpm_proxy_unplug(HotplugHandler * hotplug_dev,DeviceState * dev)41810fb6bd07SMichael Roth static void spapr_tpm_proxy_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
41820fb6bd07SMichael Roth {
41830fb6bd07SMichael Roth SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
41840fb6bd07SMichael Roth
4185981c3dcdSMarkus Armbruster qdev_unrealize(dev);
41860fb6bd07SMichael Roth object_unparent(OBJECT(dev));
41870fb6bd07SMichael Roth spapr->tpm_proxy = NULL;
41880fb6bd07SMichael Roth }
41890fb6bd07SMichael Roth
spapr_machine_device_plug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)4190c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
4191c20d332aSBharata B Rao DeviceState *dev, Error **errp)
4192c20d332aSBharata B Rao {
4193c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
4194ea042c53SGreg Kurz spapr_memory_plug(hotplug_dev, dev);
4195af81cf32SBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
4196f9b43958SGreg Kurz spapr_core_plug(hotplug_dev, dev);
4197bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
41989a070699SGreg Kurz spapr_phb_plug(hotplug_dev, dev);
41990fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) {
4200ac96807bSGreg Kurz spapr_tpm_proxy_plug(hotplug_dev, dev);
4201c20d332aSBharata B Rao }
4202c20d332aSBharata B Rao }
4203c20d332aSBharata B Rao
spapr_machine_device_unplug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)420488432f44SDavid Hildenbrand static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev,
420588432f44SDavid Hildenbrand DeviceState *dev, Error **errp)
420688432f44SDavid Hildenbrand {
42073ec71474SDavid Hildenbrand if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
42083ec71474SDavid Hildenbrand spapr_memory_unplug(hotplug_dev, dev);
4209a4261be1SDavid Hildenbrand } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
4210a4261be1SDavid Hildenbrand spapr_core_unplug(hotplug_dev, dev);
4211bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
4212bb2bdd81SGreg Kurz spapr_phb_unplug(hotplug_dev, dev);
42130fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) {
42140fb6bd07SMichael Roth spapr_tpm_proxy_unplug(hotplug_dev, dev);
42153ec71474SDavid Hildenbrand }
421688432f44SDavid Hildenbrand }
421788432f44SDavid Hildenbrand
spapr_memory_hot_unplug_supported(SpaprMachineState * spapr)421873598c75SGreg Kurz bool spapr_memory_hot_unplug_supported(SpaprMachineState *spapr)
421973598c75SGreg Kurz {
422073598c75SGreg Kurz return spapr_ovec_test(spapr->ov5_cas, OV5_HP_EVT) ||
422173598c75SGreg Kurz /*
422273598c75SGreg Kurz * CAS will process all pending unplug requests.
422373598c75SGreg Kurz *
422473598c75SGreg Kurz * HACK: a guest could theoretically have cleared all bits in OV5,
422573598c75SGreg Kurz * but none of the guests we care for do.
422673598c75SGreg Kurz */
422773598c75SGreg Kurz spapr_ovec_empty(spapr->ov5_cas);
422873598c75SGreg Kurz }
422973598c75SGreg Kurz
spapr_machine_device_unplug_request(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)4230cf632463SBharata B Rao static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev,
4231cf632463SBharata B Rao DeviceState *dev, Error **errp)
4232cf632463SBharata B Rao {
4233ce2918cbSDavid Gibson SpaprMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev));
4234c86c1affSDaniel Henrique Barboza MachineClass *mc = MACHINE_GET_CLASS(sms);
4235ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
4236cf632463SBharata B Rao
4237cf632463SBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
423873598c75SGreg Kurz if (spapr_memory_hot_unplug_supported(sms)) {
4239cf632463SBharata B Rao spapr_memory_unplug_request(hotplug_dev, dev, errp);
4240cf632463SBharata B Rao } else {
4241cf632463SBharata B Rao error_setg(errp, "Memory hot unplug not supported for this guest");
4242cf632463SBharata B Rao }
42436f4b5c3eSBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
4244c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) {
42456f4b5c3eSBharata B Rao error_setg(errp, "CPU hot unplug not supported on this machine");
42466f4b5c3eSBharata B Rao return;
42476f4b5c3eSBharata B Rao }
4248115debf2SIgor Mammedov spapr_core_unplug_request(hotplug_dev, dev, errp);
4249bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
4250bb2bdd81SGreg Kurz if (!smc->dr_phb_enabled) {
4251bb2bdd81SGreg Kurz error_setg(errp, "PHB hot unplug not supported on this machine");
4252bb2bdd81SGreg Kurz return;
4253bb2bdd81SGreg Kurz }
4254bb2bdd81SGreg Kurz spapr_phb_unplug_request(hotplug_dev, dev, errp);
42550fb6bd07SMichael Roth } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) {
42560fb6bd07SMichael Roth spapr_tpm_proxy_unplug(hotplug_dev, dev);
4257c20d332aSBharata B Rao }
4258c20d332aSBharata B Rao }
4259c20d332aSBharata B Rao
spapr_machine_device_pre_plug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)426094a94e4cSBharata B Rao static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev,
426194a94e4cSBharata B Rao DeviceState *dev, Error **errp)
426294a94e4cSBharata B Rao {
4263c871bc70SLaurent Vivier if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
4264c871bc70SLaurent Vivier spapr_memory_pre_plug(hotplug_dev, dev, errp);
4265c871bc70SLaurent Vivier } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
426694a94e4cSBharata B Rao spapr_core_pre_plug(hotplug_dev, dev, errp);
4267bb2bdd81SGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
4268bb2bdd81SGreg Kurz spapr_phb_pre_plug(hotplug_dev, dev, errp);
4269ac96807bSGreg Kurz } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) {
4270ac96807bSGreg Kurz spapr_tpm_proxy_pre_plug(hotplug_dev, dev, errp);
427194a94e4cSBharata B Rao }
427294a94e4cSBharata B Rao }
427394a94e4cSBharata B Rao
spapr_get_hotplug_handler(MachineState * machine,DeviceState * dev)42747ebaf795SBharata B Rao static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine,
4275c20d332aSBharata B Rao DeviceState *dev)
4276c20d332aSBharata B Rao {
427794a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
4278bb2bdd81SGreg Kurz object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE) ||
42790fb6bd07SMichael Roth object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE) ||
42800fb6bd07SMichael Roth object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) {
4281c20d332aSBharata B Rao return HOTPLUG_HANDLER(machine);
4282c20d332aSBharata B Rao }
4283cb600087SDavid Gibson if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
4284cb600087SDavid Gibson PCIDevice *pcidev = PCI_DEVICE(dev);
4285cb600087SDavid Gibson PCIBus *root = pci_device_root_bus(pcidev);
4286cb600087SDavid Gibson SpaprPhbState *phb =
4287cb600087SDavid Gibson (SpaprPhbState *)object_dynamic_cast(OBJECT(BUS(root)->parent),
4288cb600087SDavid Gibson TYPE_SPAPR_PCI_HOST_BRIDGE);
4289cb600087SDavid Gibson
4290cb600087SDavid Gibson if (phb) {
4291cb600087SDavid Gibson return HOTPLUG_HANDLER(phb);
4292cb600087SDavid Gibson }
4293cb600087SDavid Gibson }
4294c20d332aSBharata B Rao return NULL;
4295c20d332aSBharata B Rao }
4296c20d332aSBharata B Rao
4297ea089eebSIgor Mammedov static CpuInstanceProperties
spapr_cpu_index_to_props(MachineState * machine,unsigned cpu_index)4298ea089eebSIgor Mammedov spapr_cpu_index_to_props(MachineState *machine, unsigned cpu_index)
429920bb648dSDavid Gibson {
4300ea089eebSIgor Mammedov CPUArchId *core_slot;
4301ea089eebSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine);
4302ea089eebSIgor Mammedov
4303e6a19a64SMichael Tokarev /* make sure possible_cpu are initialized */
4304ea089eebSIgor Mammedov mc->possible_cpu_arch_ids(machine);
4305ea089eebSIgor Mammedov /* get CPU core slot containing thread that matches cpu_index */
4306ea089eebSIgor Mammedov core_slot = spapr_find_cpu_slot(machine, cpu_index, NULL);
4307ea089eebSIgor Mammedov assert(core_slot);
4308ea089eebSIgor Mammedov return core_slot->props;
430920bb648dSDavid Gibson }
431020bb648dSDavid Gibson
spapr_get_default_cpu_node_id(const MachineState * ms,int idx)431179e07936SIgor Mammedov static int64_t spapr_get_default_cpu_node_id(const MachineState *ms, int idx)
431279e07936SIgor Mammedov {
4313aa570207STao Xu return idx / ms->smp.cores % ms->numa_state->num_nodes;
431479e07936SIgor Mammedov }
431579e07936SIgor Mammedov
spapr_possible_cpu_arch_ids(MachineState * machine)4316535455fdSIgor Mammedov static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine)
4317535455fdSIgor Mammedov {
4318535455fdSIgor Mammedov int i;
4319fe6b6346SLike Xu unsigned int smp_threads = machine->smp.threads;
4320fe6b6346SLike Xu unsigned int smp_cpus = machine->smp.cpus;
4321d342eb76SIgor Mammedov const char *core_type;
4322fe6b6346SLike Xu int spapr_max_cores = machine->smp.max_cpus / smp_threads;
4323535455fdSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine);
4324535455fdSIgor Mammedov
4325c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) {
4326535455fdSIgor Mammedov spapr_max_cores = QEMU_ALIGN_UP(smp_cpus, smp_threads) / smp_threads;
4327535455fdSIgor Mammedov }
4328535455fdSIgor Mammedov if (machine->possible_cpus) {
4329535455fdSIgor Mammedov assert(machine->possible_cpus->len == spapr_max_cores);
4330535455fdSIgor Mammedov return machine->possible_cpus;
4331535455fdSIgor Mammedov }
4332535455fdSIgor Mammedov
4333d342eb76SIgor Mammedov core_type = spapr_get_cpu_core_type(machine->cpu_type);
4334d342eb76SIgor Mammedov if (!core_type) {
4335d342eb76SIgor Mammedov error_report("Unable to find sPAPR CPU Core definition");
4336d342eb76SIgor Mammedov exit(1);
4337d342eb76SIgor Mammedov }
4338d342eb76SIgor Mammedov
4339535455fdSIgor Mammedov machine->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
4340535455fdSIgor Mammedov sizeof(CPUArchId) * spapr_max_cores);
4341535455fdSIgor Mammedov machine->possible_cpus->len = spapr_max_cores;
4342535455fdSIgor Mammedov for (i = 0; i < machine->possible_cpus->len; i++) {
4343535455fdSIgor Mammedov int core_id = i * smp_threads;
4344535455fdSIgor Mammedov
4345d342eb76SIgor Mammedov machine->possible_cpus->cpus[i].type = core_type;
4346f2d672c2SIgor Mammedov machine->possible_cpus->cpus[i].vcpus_count = smp_threads;
4347535455fdSIgor Mammedov machine->possible_cpus->cpus[i].arch_id = core_id;
4348535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.has_core_id = true;
4349535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.core_id = core_id;
4350535455fdSIgor Mammedov }
4351535455fdSIgor Mammedov return machine->possible_cpus;
4352535455fdSIgor Mammedov }
4353535455fdSIgor Mammedov
spapr_phb_placement(SpaprMachineState * spapr,uint32_t index,uint64_t * buid,hwaddr * pio,hwaddr * mmio32,hwaddr * mmio64,unsigned n_dma,uint32_t * liobns,Error ** errp)4354f5598c92SGreg Kurz static bool spapr_phb_placement(SpaprMachineState *spapr, uint32_t index,
4355daa23699SDavid Gibson uint64_t *buid, hwaddr *pio,
4356daa23699SDavid Gibson hwaddr *mmio32, hwaddr *mmio64,
435744fa20c9SCédric Le Goater unsigned n_dma, uint32_t *liobns, Error **errp)
43586737d9adSDavid Gibson {
4359357d1e3bSDavid Gibson /*
4360357d1e3bSDavid Gibson * New-style PHB window placement.
4361357d1e3bSDavid Gibson *
4362357d1e3bSDavid Gibson * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window
4363357d1e3bSDavid Gibson * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO
4364357d1e3bSDavid Gibson * windows.
4365357d1e3bSDavid Gibson *
4366357d1e3bSDavid Gibson * Some guest kernels can't work with MMIO windows above 1<<46
4367357d1e3bSDavid Gibson * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB
4368357d1e3bSDavid Gibson *
4369357d1e3bSDavid Gibson * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each
4370357d1e3bSDavid Gibson * PHB stacked together. (32TiB+2GiB)..(32TiB+64GiB) contains the
4371357d1e3bSDavid Gibson * 2GiB 32-bit MMIO windows for each PHB. Then 33..64TiB has the
4372357d1e3bSDavid Gibson * 1TiB 64-bit MMIO windows for each PHB.
4373357d1e3bSDavid Gibson */
43746737d9adSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL;
43756737d9adSDavid Gibson int i;
43766737d9adSDavid Gibson
4377357d1e3bSDavid Gibson /* Sanity check natural alignments */
4378357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0);
4379357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0);
4380357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0);
4381357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0);
4382357d1e3bSDavid Gibson /* Sanity check bounds */
438325e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_IO_WIN_SIZE) >
438425e6a118SMichael S. Tsirkin SPAPR_PCI_MEM32_WIN_SIZE);
438525e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_MEM32_WIN_SIZE) >
438625e6a118SMichael S. Tsirkin SPAPR_PCI_MEM64_WIN_SIZE);
43872efff1c0SDavid Gibson
438825e6a118SMichael S. Tsirkin if (index >= SPAPR_MAX_PHBS) {
438925e6a118SMichael S. Tsirkin error_setg(errp, "\"index\" for PAPR PHB is too large (max %llu)",
439025e6a118SMichael S. Tsirkin SPAPR_MAX_PHBS - 1);
4391f5598c92SGreg Kurz return false;
43926737d9adSDavid Gibson }
43936737d9adSDavid Gibson
43946737d9adSDavid Gibson *buid = base_buid + index;
43956737d9adSDavid Gibson for (i = 0; i < n_dma; ++i) {
43966737d9adSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i);
43976737d9adSDavid Gibson }
43986737d9adSDavid Gibson
4399357d1e3bSDavid Gibson *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE;
4400357d1e3bSDavid Gibson *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE;
4401357d1e3bSDavid Gibson *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE;
4402f5598c92SGreg Kurz return true;
44036737d9adSDavid Gibson }
44046737d9adSDavid Gibson
spapr_ics_get(XICSFabric * dev,int irq)44057844e12bSCédric Le Goater static ICSState *spapr_ics_get(XICSFabric *dev, int irq)
44067844e12bSCédric Le Goater {
4407ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(dev);
44087844e12bSCédric Le Goater
44097844e12bSCédric Le Goater return ics_valid_irq(spapr->ics, irq) ? spapr->ics : NULL;
44107844e12bSCédric Le Goater }
44117844e12bSCédric Le Goater
spapr_ics_resend(XICSFabric * dev)44127844e12bSCédric Le Goater static void spapr_ics_resend(XICSFabric *dev)
44137844e12bSCédric Le Goater {
4414ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(dev);
44157844e12bSCédric Le Goater
44167844e12bSCédric Le Goater ics_resend(spapr->ics);
44177844e12bSCédric Le Goater }
44187844e12bSCédric Le Goater
spapr_icp_get(XICSFabric * xi,int vcpu_id)441981210c20SSam Bobroff static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id)
4420b2fc59aaSCédric Le Goater {
44212e886fb3SSam Bobroff PowerPCCPU *cpu = spapr_find_cpu(vcpu_id);
4422b2fc59aaSCédric Le Goater
4423a28b9a5aSCédric Le Goater return cpu ? spapr_cpu_state(cpu)->icp : NULL;
4424b2fc59aaSCédric Le Goater }
4425b2fc59aaSCédric Le Goater
spapr_pic_print_info(InterruptStatsProvider * obj,GString * buf)4426b2580720SPhilippe Mathieu-Daudé static void spapr_pic_print_info(InterruptStatsProvider *obj, GString *buf)
44276449da45SCédric Le Goater {
4428ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(obj);
44296449da45SCédric Le Goater
4430f50bb2a2SPhilippe Mathieu-Daudé spapr_irq_print_info(spapr, buf);
4431f50bb2a2SPhilippe Mathieu-Daudé g_string_append_printf(buf, "irqchip: %s\n",
4432f041d6afSGreg Kurz kvm_irqchip_in_kernel() ? "in-kernel" : "emulated");
44336449da45SCédric Le Goater }
44346449da45SCédric Le Goater
4435baa45b17SCédric Le Goater /*
4436baa45b17SCédric Le Goater * This is a XIVE only operation
4437baa45b17SCédric Le Goater */
spapr_match_nvt(XiveFabric * xfb,uint8_t format,uint8_t nvt_blk,uint32_t nvt_idx,bool cam_ignore,uint8_t priority,uint32_t logic_serv,XiveTCTXMatch * match)4438932de7aeSCédric Le Goater static int spapr_match_nvt(XiveFabric *xfb, uint8_t format,
4439932de7aeSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx,
4440932de7aeSCédric Le Goater bool cam_ignore, uint8_t priority,
4441932de7aeSCédric Le Goater uint32_t logic_serv, XiveTCTXMatch *match)
4442932de7aeSCédric Le Goater {
4443932de7aeSCédric Le Goater SpaprMachineState *spapr = SPAPR_MACHINE(xfb);
4444baa45b17SCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(spapr->active_intc);
4445932de7aeSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
4446932de7aeSCédric Le Goater int count;
4447932de7aeSCédric Le Goater
4448932de7aeSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
4449932de7aeSCédric Le Goater priority, logic_serv, match);
4450932de7aeSCédric Le Goater if (count < 0) {
4451932de7aeSCédric Le Goater return count;
4452932de7aeSCédric Le Goater }
4453932de7aeSCédric Le Goater
4454932de7aeSCédric Le Goater /*
4455932de7aeSCédric Le Goater * When we implement the save and restore of the thread interrupt
4456932de7aeSCédric Le Goater * contexts in the enter/exit CPU handlers of the machine and the
4457932de7aeSCédric Le Goater * escalations in QEMU, we should be able to handle non dispatched
4458932de7aeSCédric Le Goater * vCPUs.
4459932de7aeSCédric Le Goater *
4460932de7aeSCédric Le Goater * Until this is done, the sPAPR machine should find at least one
4461932de7aeSCédric Le Goater * matching context always.
4462932de7aeSCédric Le Goater */
4463932de7aeSCédric Le Goater if (count == 0) {
4464932de7aeSCédric Le Goater qemu_log_mask(LOG_GUEST_ERROR, "XIVE: NVT %x/%x is not dispatched\n",
4465932de7aeSCédric Le Goater nvt_blk, nvt_idx);
4466932de7aeSCédric Le Goater }
4467932de7aeSCédric Le Goater
4468932de7aeSCédric Le Goater return count;
4469932de7aeSCédric Le Goater }
4470932de7aeSCédric Le Goater
spapr_get_vcpu_id(PowerPCCPU * cpu)447114bb4486SGreg Kurz int spapr_get_vcpu_id(PowerPCCPU *cpu)
44722e886fb3SSam Bobroff {
4473b1a568c1SGreg Kurz return cpu->vcpu_id;
44742e886fb3SSam Bobroff }
44752e886fb3SSam Bobroff
spapr_set_vcpu_id(PowerPCCPU * cpu,int cpu_index,Error ** errp)4476cfdc5274SGreg Kurz bool spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp)
4477648edb64SGreg Kurz {
4478ce2918cbSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
4479fe6b6346SLike Xu MachineState *ms = MACHINE(spapr);
4480648edb64SGreg Kurz int vcpu_id;
4481648edb64SGreg Kurz
44825d0fb150SGreg Kurz vcpu_id = spapr_vcpu_id(spapr, cpu_index);
4483648edb64SGreg Kurz
4484648edb64SGreg Kurz if (kvm_enabled() && !kvm_vcpu_id_is_valid(vcpu_id)) {
4485648edb64SGreg Kurz error_setg(errp, "Can't create CPU with id %d in KVM", vcpu_id);
4486648edb64SGreg Kurz error_append_hint(errp, "Adjust the number of cpus to %d "
4487648edb64SGreg Kurz "or try to raise the number of threads per core\n",
4488fe6b6346SLike Xu vcpu_id * ms->smp.threads / spapr->vsmt);
4489cfdc5274SGreg Kurz return false;
4490648edb64SGreg Kurz }
4491648edb64SGreg Kurz
4492648edb64SGreg Kurz cpu->vcpu_id = vcpu_id;
4493cfdc5274SGreg Kurz return true;
4494648edb64SGreg Kurz }
4495648edb64SGreg Kurz
spapr_find_cpu(int vcpu_id)44962e886fb3SSam Bobroff PowerPCCPU *spapr_find_cpu(int vcpu_id)
44972e886fb3SSam Bobroff {
44982e886fb3SSam Bobroff CPUState *cs;
44992e886fb3SSam Bobroff
45002e886fb3SSam Bobroff CPU_FOREACH(cs) {
45012e886fb3SSam Bobroff PowerPCCPU *cpu = POWERPC_CPU(cs);
45022e886fb3SSam Bobroff
450314bb4486SGreg Kurz if (spapr_get_vcpu_id(cpu) == vcpu_id) {
45042e886fb3SSam Bobroff return cpu;
45052e886fb3SSam Bobroff }
45062e886fb3SSam Bobroff }
45072e886fb3SSam Bobroff
45082e886fb3SSam Bobroff return NULL;
45092e886fb3SSam Bobroff }
45102e886fb3SSam Bobroff
spapr_cpu_in_nested(PowerPCCPU * cpu)45117cebc5dbSNicholas Piggin static bool spapr_cpu_in_nested(PowerPCCPU *cpu)
45127cebc5dbSNicholas Piggin {
4513120f738aSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
4514120f738aSNicholas Piggin
4515120f738aSNicholas Piggin return spapr_cpu->in_nested;
45167cebc5dbSNicholas Piggin }
45177cebc5dbSNicholas Piggin
spapr_cpu_exec_enter(PPCVirtualHypervisor * vhyp,PowerPCCPU * cpu)451803ef074cSNicholas Piggin static void spapr_cpu_exec_enter(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu)
451903ef074cSNicholas Piggin {
452003ef074cSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
452103ef074cSNicholas Piggin
452203ef074cSNicholas Piggin /* These are only called by TCG, KVM maintains dispatch state */
452303ef074cSNicholas Piggin
45243a6e6224SNicholas Piggin spapr_cpu->prod = false;
452503ef074cSNicholas Piggin if (spapr_cpu->vpa_addr) {
452603ef074cSNicholas Piggin CPUState *cs = CPU(cpu);
452703ef074cSNicholas Piggin uint32_t dispatch;
452803ef074cSNicholas Piggin
452903ef074cSNicholas Piggin dispatch = ldl_be_phys(cs->as,
453003ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER);
453103ef074cSNicholas Piggin dispatch++;
453203ef074cSNicholas Piggin if ((dispatch & 1) != 0) {
453303ef074cSNicholas Piggin qemu_log_mask(LOG_GUEST_ERROR,
453403ef074cSNicholas Piggin "VPA: incorrect dispatch counter value for "
453503ef074cSNicholas Piggin "dispatched partition %u, correcting.\n", dispatch);
453603ef074cSNicholas Piggin dispatch++;
453703ef074cSNicholas Piggin }
453803ef074cSNicholas Piggin stl_be_phys(cs->as,
453903ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch);
454003ef074cSNicholas Piggin }
454103ef074cSNicholas Piggin }
454203ef074cSNicholas Piggin
spapr_cpu_exec_exit(PPCVirtualHypervisor * vhyp,PowerPCCPU * cpu)454303ef074cSNicholas Piggin static void spapr_cpu_exec_exit(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu)
454403ef074cSNicholas Piggin {
454503ef074cSNicholas Piggin SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
454603ef074cSNicholas Piggin
454703ef074cSNicholas Piggin if (spapr_cpu->vpa_addr) {
454803ef074cSNicholas Piggin CPUState *cs = CPU(cpu);
454903ef074cSNicholas Piggin uint32_t dispatch;
455003ef074cSNicholas Piggin
455103ef074cSNicholas Piggin dispatch = ldl_be_phys(cs->as,
455203ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER);
455303ef074cSNicholas Piggin dispatch++;
455403ef074cSNicholas Piggin if ((dispatch & 1) != 1) {
455503ef074cSNicholas Piggin qemu_log_mask(LOG_GUEST_ERROR,
455603ef074cSNicholas Piggin "VPA: incorrect dispatch counter value for "
455703ef074cSNicholas Piggin "preempted partition %u, correcting.\n", dispatch);
455803ef074cSNicholas Piggin dispatch++;
455903ef074cSNicholas Piggin }
456003ef074cSNicholas Piggin stl_be_phys(cs->as,
456103ef074cSNicholas Piggin spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch);
456203ef074cSNicholas Piggin }
456303ef074cSNicholas Piggin }
456403ef074cSNicholas Piggin
spapr_machine_class_init(ObjectClass * oc,void * data)456529ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data)
456653018216SPaolo Bonzini {
456729ee3247SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc);
4568ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(oc);
456971461b0fSAlexey Kardashevskiy FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc);
457034316482SAlexey Kardashevskiy NMIClass *nc = NMI_CLASS(oc);
4571c20d332aSBharata B Rao HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
45721d1be34dSDavid Gibson PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc);
45737844e12bSCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
45746449da45SCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
4575932de7aeSCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
4576fc8c745dSAlexey Kardashevskiy VofMachineIfClass *vmc = VOF_MACHINE_CLASS(oc);
457729ee3247SAlexey Kardashevskiy
45780eb9054cSDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant)";
4579907aac2fSMark Cave-Ayland mc->ignore_boot_device_suffixes = true;
4580fc9f38c3SDavid Gibson
4581fc9f38c3SDavid Gibson /*
4582fc9f38c3SDavid Gibson * We set up the default / latest behaviour here. The class_init
4583fc9f38c3SDavid Gibson * functions for the specific versioned machine types can override
4584fc9f38c3SDavid Gibson * these details for backwards compatibility
4585fc9f38c3SDavid Gibson */
4586bcb5ce08SDavid Gibson mc->init = spapr_machine_init;
4587bcb5ce08SDavid Gibson mc->reset = spapr_machine_reset;
4588958db90cSMarcel Apfelbaum mc->block_default_type = IF_SCSI;
45895642e451SDaniel Henrique Barboza
45905642e451SDaniel Henrique Barboza /*
4591c4f91d7bSHarsh Prateek Bora * While KVM determines max cpus in kvm_init() using kvm_max_vcpus(),
4592c4f91d7bSHarsh Prateek Bora * In TCG the limit is restricted by the range of CPU IPIs available.
45935642e451SDaniel Henrique Barboza */
4594c4f91d7bSHarsh Prateek Bora mc->max_cpus = SPAPR_IRQ_NR_IPIS;
45955642e451SDaniel Henrique Barboza
4596958db90cSMarcel Apfelbaum mc->no_parallel = 1;
45975b2128d2SAlexander Graf mc->default_boot_order = "";
4598d23b6caaSPhilippe Mathieu-Daudé mc->default_ram_size = 512 * MiB;
4599ab74e543SIgor Mammedov mc->default_ram_id = "ppc_spapr.ram";
460029f9cef3SSebastian Bauer mc->default_display = "std";
4601958db90cSMarcel Apfelbaum mc->kvm_type = spapr_kvm_type;
46027da79a16SEduardo Habkost machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SPAPR_PCI_HOST_BRIDGE);
4603e4024630SLaurent Vivier mc->pci_allow_0_address = true;
4604debbdc00SIgor Mammedov assert(!mc->get_hotplug_handler);
46057ebaf795SBharata B Rao mc->get_hotplug_handler = spapr_get_hotplug_handler;
460694a94e4cSBharata B Rao hc->pre_plug = spapr_machine_device_pre_plug;
4607c20d332aSBharata B Rao hc->plug = spapr_machine_device_plug;
4608ea089eebSIgor Mammedov mc->cpu_index_to_instance_props = spapr_cpu_index_to_props;
460979e07936SIgor Mammedov mc->get_default_cpu_node_id = spapr_get_default_cpu_node_id;
4610535455fdSIgor Mammedov mc->possible_cpu_arch_ids = spapr_possible_cpu_arch_ids;
4611cf632463SBharata B Rao hc->unplug_request = spapr_machine_device_unplug_request;
461288432f44SDavid Hildenbrand hc->unplug = spapr_machine_device_unplug;
461300b4fbe2SMarcel Apfelbaum
4614fea35ca4SAlexey Kardashevskiy smc->update_dt_enabled = true;
461551113013SNicholas Piggin mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
4616c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = true;
4617ee3a71e3SShivaprasad G Bhat mc->nvdimm_supported = true;
461852b81ab5SDavid Gibson smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED;
461971461b0fSAlexey Kardashevskiy fwc->get_dev_path = spapr_get_fw_dev_path;
462034316482SAlexey Kardashevskiy nc->nmi_monitor_handler = spapr_nmi;
46216737d9adSDavid Gibson smc->phb_placement = spapr_phb_placement;
46227cebc5dbSNicholas Piggin vhc->cpu_in_nested = spapr_cpu_in_nested;
4623120f738aSNicholas Piggin vhc->deliver_hv_excp = spapr_exit_nested;
46241d1be34dSDavid Gibson vhc->hypercall = emulate_spapr_hypercall;
4625e57ca75cSDavid Gibson vhc->hpt_mask = spapr_hpt_mask;
4626e57ca75cSDavid Gibson vhc->map_hptes = spapr_map_hptes;
4627e57ca75cSDavid Gibson vhc->unmap_hptes = spapr_unmap_hptes;
4628a2dd4e83SBenjamin Herrenschmidt vhc->hpte_set_c = spapr_hpte_set_c;
4629a2dd4e83SBenjamin Herrenschmidt vhc->hpte_set_r = spapr_hpte_set_r;
463079825f4dSBenjamin Herrenschmidt vhc->get_pate = spapr_get_pate;
46311ec26c75SGreg Kurz vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr;
463203ef074cSNicholas Piggin vhc->cpu_exec_enter = spapr_cpu_exec_enter;
463303ef074cSNicholas Piggin vhc->cpu_exec_exit = spapr_cpu_exec_exit;
46347844e12bSCédric Le Goater xic->ics_get = spapr_ics_get;
46357844e12bSCédric Le Goater xic->ics_resend = spapr_ics_resend;
4636b2fc59aaSCédric Le Goater xic->icp_get = spapr_icp_get;
46376449da45SCédric Le Goater ispc->print_info = spapr_pic_print_info;
463855641213SLaurent Vivier /* Force NUMA node memory size to be a multiple of
463955641213SLaurent Vivier * SPAPR_MEMORY_BLOCK_SIZE (256M) since that's the granularity
464055641213SLaurent Vivier * in which LMBs are represented and hot-added
464155641213SLaurent Vivier */
464255641213SLaurent Vivier mc->numa_mem_align_shift = 28;
46430533ef5fSTao Xu mc->auto_enable_numa = true;
464433face6bSDavid Gibson
46454e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
46464e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON;
46474e5fe368SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON;
46482782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND;
46492782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND;
46502782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_WORKAROUND;
46512309832aSDavid Gibson smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
4652b9a477b7SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
4653e1617b84SHarsh Prateek Bora smc->default_caps.caps[SPAPR_CAP_NESTED_PAPR] = SPAPR_CAP_OFF;
4654edaa7995SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON;
465537965dfeSDavid Gibson smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_ON;
46568af7e1feSNicholas Piggin smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_ON;
465782123b75SBharata B Rao smc->default_caps.caps[SPAPR_CAP_RPT_INVALIDATE] = SPAPR_CAP_OFF;
4658ccc5a4c5SNicholas Piggin
4659ccc5a4c5SNicholas Piggin /*
4660ccc5a4c5SNicholas Piggin * This cap specifies whether the AIL 3 mode for
4661ccc5a4c5SNicholas Piggin * H_SET_RESOURCE is supported. The default is modified
4662ccc5a4c5SNicholas Piggin * by default_caps_with_cpu().
4663ccc5a4c5SNicholas Piggin */
4664ccc5a4c5SNicholas Piggin smc->default_caps.caps[SPAPR_CAP_AIL_MODE_3] = SPAPR_CAP_ON;
466540c2281cSMarkus Armbruster spapr_caps_add_properties(smc);
4666bd94bc06SCédric Le Goater smc->irq = &spapr_irq_dual;
4667dae5e39aSMichael Roth smc->dr_phb_enabled = true;
46686c3829a2SAlexey Kardashevskiy smc->linux_pci_probe = true;
466929cb4187SGreg Kurz smc->smp_threads_vsmt = true;
467054255c1fSDavid Gibson smc->nr_xirqs = SPAPR_NR_XIRQS;
4671932de7aeSCédric Le Goater xfc->match_nvt = spapr_match_nvt;
4672fc8c745dSAlexey Kardashevskiy vmc->client_architecture_support = spapr_vof_client_architecture_support;
4673fc8c745dSAlexey Kardashevskiy vmc->quiesce = spapr_vof_quiesce;
4674fc8c745dSAlexey Kardashevskiy vmc->setprop = spapr_vof_setprop;
467553018216SPaolo Bonzini }
467653018216SPaolo Bonzini
467729ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = {
467829ee3247SAlexey Kardashevskiy .name = TYPE_SPAPR_MACHINE,
467929ee3247SAlexey Kardashevskiy .parent = TYPE_MACHINE,
46804aee7362SDavid Gibson .abstract = true,
4681ce2918cbSDavid Gibson .instance_size = sizeof(SpaprMachineState),
4682bcb5ce08SDavid Gibson .instance_init = spapr_instance_init,
468387bbdd9cSDavid Gibson .instance_finalize = spapr_machine_finalizefn,
4684ce2918cbSDavid Gibson .class_size = sizeof(SpaprMachineClass),
468529ee3247SAlexey Kardashevskiy .class_init = spapr_machine_class_init,
468671461b0fSAlexey Kardashevskiy .interfaces = (InterfaceInfo[]) {
468771461b0fSAlexey Kardashevskiy { TYPE_FW_PATH_PROVIDER },
468834316482SAlexey Kardashevskiy { TYPE_NMI },
4689c20d332aSBharata B Rao { TYPE_HOTPLUG_HANDLER },
46901d1be34dSDavid Gibson { TYPE_PPC_VIRTUAL_HYPERVISOR },
46917844e12bSCédric Le Goater { TYPE_XICS_FABRIC },
46926449da45SCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER },
4693932de7aeSCédric Le Goater { TYPE_XIVE_FABRIC },
4694fc8c745dSAlexey Kardashevskiy { TYPE_VOF_MACHINE_IF },
469571461b0fSAlexey Kardashevskiy { }
469671461b0fSAlexey Kardashevskiy },
469729ee3247SAlexey Kardashevskiy };
469829ee3247SAlexey Kardashevskiy
spapr_machine_latest_class_options(MachineClass * mc)4699a7849268SMichael S. Tsirkin static void spapr_machine_latest_class_options(MachineClass *mc)
4700a7849268SMichael S. Tsirkin {
4701a7849268SMichael S. Tsirkin mc->alias = "pseries";
4702ea0ac7f6SPhilippe Mathieu-Daudé mc->is_default = true;
4703a7849268SMichael S. Tsirkin }
4704a7849268SMichael S. Tsirkin
47058d40cc14SDaniel P. Berrangé #define DEFINE_SPAPR_MACHINE_IMPL(latest, ...) \
47068d40cc14SDaniel P. Berrangé static void MACHINE_VER_SYM(class_init, spapr, __VA_ARGS__)( \
47078d40cc14SDaniel P. Berrangé ObjectClass *oc, \
47085013c547SDavid Gibson void *data) \
47095013c547SDavid Gibson { \
47105013c547SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); \
47118d40cc14SDaniel P. Berrangé MACHINE_VER_SYM(class_options, spapr, __VA_ARGS__)(mc); \
47128d3122a8SDaniel P. Berrangé MACHINE_VER_DEPRECATION(__VA_ARGS__); \
4713fccbc785SDavid Gibson if (latest) { \
4714a7849268SMichael S. Tsirkin spapr_machine_latest_class_options(mc); \
4715fccbc785SDavid Gibson } \
47165013c547SDavid Gibson } \
47178d40cc14SDaniel P. Berrangé static const TypeInfo MACHINE_VER_SYM(info, spapr, __VA_ARGS__) = \
47185013c547SDavid Gibson { \
47198d40cc14SDaniel P. Berrangé .name = MACHINE_VER_TYPE_NAME("pseries", __VA_ARGS__), \
47208d40cc14SDaniel P. Berrangé .parent = TYPE_SPAPR_MACHINE, \
47218d40cc14SDaniel P. Berrangé .class_init = MACHINE_VER_SYM(class_init, spapr, __VA_ARGS__), \
47228d40cc14SDaniel P. Berrangé }; \
47238d40cc14SDaniel P. Berrangé static void MACHINE_VER_SYM(register, spapr, __VA_ARGS__)(void) \
47248d40cc14SDaniel P. Berrangé { \
4725a391eeb1SDaniel P. Berrangé MACHINE_VER_DELETION(__VA_ARGS__); \
47268d40cc14SDaniel P. Berrangé type_register(&MACHINE_VER_SYM(info, spapr, __VA_ARGS__)); \
47275013c547SDavid Gibson } \
47288d40cc14SDaniel P. Berrangé type_init(MACHINE_VER_SYM(register, spapr, __VA_ARGS__))
47298d40cc14SDaniel P. Berrangé
47308d40cc14SDaniel P. Berrangé #define DEFINE_SPAPR_MACHINE_AS_LATEST(major, minor) \
47318d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE_IMPL(true, major, minor)
47328d40cc14SDaniel P. Berrangé #define DEFINE_SPAPR_MACHINE(major, minor) \
47338d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE_IMPL(false, major, minor)
47345013c547SDavid Gibson
47351c5f29bbSDavid Gibson /*
4736fb6051e7SCornelia Huck * pseries-9.2
47373eb74d20SCornelia Huck */
spapr_machine_9_2_class_options(MachineClass * mc)4738fb6051e7SCornelia Huck static void spapr_machine_9_2_class_options(MachineClass *mc)
47393eb74d20SCornelia Huck {
47403eb74d20SCornelia Huck /* Defaults for the latest behaviour inherited from the base class */
47413eb74d20SCornelia Huck }
47423eb74d20SCornelia Huck
4743fb6051e7SCornelia Huck DEFINE_SPAPR_MACHINE_AS_LATEST(9, 2);
4744fb6051e7SCornelia Huck
4745fb6051e7SCornelia Huck /*
4746fb6051e7SCornelia Huck * pseries-9.1
4747fb6051e7SCornelia Huck */
spapr_machine_9_1_class_options(MachineClass * mc)4748fb6051e7SCornelia Huck static void spapr_machine_9_1_class_options(MachineClass *mc)
4749fb6051e7SCornelia Huck {
4750fb6051e7SCornelia Huck spapr_machine_9_2_class_options(mc);
4751fb6051e7SCornelia Huck compat_props_add(mc->compat_props, hw_compat_9_1, hw_compat_9_1_len);
4752fb6051e7SCornelia Huck }
4753fb6051e7SCornelia Huck
4754fb6051e7SCornelia Huck DEFINE_SPAPR_MACHINE(9, 1);
475585fa9acdSPaolo Bonzini
475685fa9acdSPaolo Bonzini /*
475785fa9acdSPaolo Bonzini * pseries-9.0
475885fa9acdSPaolo Bonzini */
spapr_machine_9_0_class_options(MachineClass * mc)475985fa9acdSPaolo Bonzini static void spapr_machine_9_0_class_options(MachineClass *mc)
476085fa9acdSPaolo Bonzini {
476185fa9acdSPaolo Bonzini spapr_machine_9_1_class_options(mc);
476285fa9acdSPaolo Bonzini compat_props_add(mc->compat_props, hw_compat_9_0, hw_compat_9_0_len);
476385fa9acdSPaolo Bonzini }
476485fa9acdSPaolo Bonzini
47658d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(9, 0);
47662b10a676SCornelia Huck
47672b10a676SCornelia Huck /*
47682b10a676SCornelia Huck * pseries-8.2
47692b10a676SCornelia Huck */
spapr_machine_8_2_class_options(MachineClass * mc)47702b10a676SCornelia Huck static void spapr_machine_8_2_class_options(MachineClass *mc)
47712b10a676SCornelia Huck {
47722b10a676SCornelia Huck spapr_machine_9_0_class_options(mc);
47732b10a676SCornelia Huck compat_props_add(mc->compat_props, hw_compat_8_2, hw_compat_8_2_len);
47742b10a676SCornelia Huck }
47752b10a676SCornelia Huck
47768d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(8, 2);
477795f5c89eSCornelia Huck
477895f5c89eSCornelia Huck /*
477995f5c89eSCornelia Huck * pseries-8.1
478095f5c89eSCornelia Huck */
spapr_machine_8_1_class_options(MachineClass * mc)478195f5c89eSCornelia Huck static void spapr_machine_8_1_class_options(MachineClass *mc)
478295f5c89eSCornelia Huck {
478395f5c89eSCornelia Huck spapr_machine_8_2_class_options(mc);
478495f5c89eSCornelia Huck compat_props_add(mc->compat_props, hw_compat_8_1, hw_compat_8_1_len);
478595f5c89eSCornelia Huck }
478695f5c89eSCornelia Huck
47878d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(8, 1);
4788f9be4771SCornelia Huck
4789f9be4771SCornelia Huck /*
4790f9be4771SCornelia Huck * pseries-8.0
4791f9be4771SCornelia Huck */
spapr_machine_8_0_class_options(MachineClass * mc)4792f9be4771SCornelia Huck static void spapr_machine_8_0_class_options(MachineClass *mc)
4793f9be4771SCornelia Huck {
4794f9be4771SCornelia Huck spapr_machine_8_1_class_options(mc);
4795f9be4771SCornelia Huck compat_props_add(mc->compat_props, hw_compat_8_0, hw_compat_8_0_len);
4796f9be4771SCornelia Huck }
4797f9be4771SCornelia Huck
47988d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(8, 0);
4799db723c80SCornelia Huck
4800db723c80SCornelia Huck /*
4801db723c80SCornelia Huck * pseries-7.2
4802db723c80SCornelia Huck */
spapr_machine_7_2_class_options(MachineClass * mc)4803db723c80SCornelia Huck static void spapr_machine_7_2_class_options(MachineClass *mc)
4804db723c80SCornelia Huck {
4805db723c80SCornelia Huck spapr_machine_8_0_class_options(mc);
4806db723c80SCornelia Huck compat_props_add(mc->compat_props, hw_compat_7_2, hw_compat_7_2_len);
4807db723c80SCornelia Huck }
4808db723c80SCornelia Huck
48098d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(7, 2);
4810f514e147SCornelia Huck
4811f514e147SCornelia Huck /*
4812f514e147SCornelia Huck * pseries-7.1
4813f514e147SCornelia Huck */
spapr_machine_7_1_class_options(MachineClass * mc)4814f514e147SCornelia Huck static void spapr_machine_7_1_class_options(MachineClass *mc)
4815f514e147SCornelia Huck {
4816f514e147SCornelia Huck spapr_machine_7_2_class_options(mc);
4817f514e147SCornelia Huck compat_props_add(mc->compat_props, hw_compat_7_1, hw_compat_7_1_len);
4818f514e147SCornelia Huck }
4819f514e147SCornelia Huck
48208d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(7, 1);
48210ca70366SCornelia Huck
48220ca70366SCornelia Huck /*
48230ca70366SCornelia Huck * pseries-7.0
48240ca70366SCornelia Huck */
spapr_machine_7_0_class_options(MachineClass * mc)48250ca70366SCornelia Huck static void spapr_machine_7_0_class_options(MachineClass *mc)
48260ca70366SCornelia Huck {
48270ca70366SCornelia Huck spapr_machine_7_1_class_options(mc);
48280ca70366SCornelia Huck compat_props_add(mc->compat_props, hw_compat_7_0, hw_compat_7_0_len);
48290ca70366SCornelia Huck }
48300ca70366SCornelia Huck
48318d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(7, 0);
483201854af2SCornelia Huck
483301854af2SCornelia Huck /*
483401854af2SCornelia Huck * pseries-6.2
483501854af2SCornelia Huck */
spapr_machine_6_2_class_options(MachineClass * mc)483601854af2SCornelia Huck static void spapr_machine_6_2_class_options(MachineClass *mc)
483701854af2SCornelia Huck {
483801854af2SCornelia Huck spapr_machine_7_0_class_options(mc);
483901854af2SCornelia Huck compat_props_add(mc->compat_props, hw_compat_6_2, hw_compat_6_2_len);
484001854af2SCornelia Huck }
484101854af2SCornelia Huck
48428d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(6, 2);
484352e64f5bSYanan Wang
484452e64f5bSYanan Wang /*
484552e64f5bSYanan Wang * pseries-6.1
484652e64f5bSYanan Wang */
spapr_machine_6_1_class_options(MachineClass * mc)484752e64f5bSYanan Wang static void spapr_machine_6_1_class_options(MachineClass *mc)
484852e64f5bSYanan Wang {
4849e0eb84d4SDaniel Henrique Barboza SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
4850e0eb84d4SDaniel Henrique Barboza
485152e64f5bSYanan Wang spapr_machine_6_2_class_options(mc);
485252e64f5bSYanan Wang compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
4853e0eb84d4SDaniel Henrique Barboza smc->pre_6_2_numa_affinity = true;
48542b526199SYanan Wang mc->smp_props.prefer_sockets = true;
485552e64f5bSYanan Wang }
485652e64f5bSYanan Wang
48578d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(6, 1);
4858da7e13c0SCornelia Huck
4859da7e13c0SCornelia Huck /*
4860da7e13c0SCornelia Huck * pseries-6.0
4861da7e13c0SCornelia Huck */
spapr_machine_6_0_class_options(MachineClass * mc)4862da7e13c0SCornelia Huck static void spapr_machine_6_0_class_options(MachineClass *mc)
4863da7e13c0SCornelia Huck {
4864da7e13c0SCornelia Huck spapr_machine_6_1_class_options(mc);
4865da7e13c0SCornelia Huck compat_props_add(mc->compat_props, hw_compat_6_0, hw_compat_6_0_len);
4866da7e13c0SCornelia Huck }
4867da7e13c0SCornelia Huck
48688d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(6, 0);
4869576a00bdSCornelia Huck
4870576a00bdSCornelia Huck /*
4871576a00bdSCornelia Huck * pseries-5.2
4872576a00bdSCornelia Huck */
spapr_machine_5_2_class_options(MachineClass * mc)4873576a00bdSCornelia Huck static void spapr_machine_5_2_class_options(MachineClass *mc)
4874576a00bdSCornelia Huck {
4875576a00bdSCornelia Huck spapr_machine_6_0_class_options(mc);
4876576a00bdSCornelia Huck compat_props_add(mc->compat_props, hw_compat_5_2, hw_compat_5_2_len);
4877576a00bdSCornelia Huck }
4878576a00bdSCornelia Huck
48798d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(5, 2);
48803ff3c5d3SCornelia Huck
48813ff3c5d3SCornelia Huck /*
48823ff3c5d3SCornelia Huck * pseries-5.1
48833ff3c5d3SCornelia Huck */
spapr_machine_5_1_class_options(MachineClass * mc)48843ff3c5d3SCornelia Huck static void spapr_machine_5_1_class_options(MachineClass *mc)
48853ff3c5d3SCornelia Huck {
488629bfe52aSDaniel Henrique Barboza SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
488729bfe52aSDaniel Henrique Barboza
48883ff3c5d3SCornelia Huck spapr_machine_5_2_class_options(mc);
48893ff3c5d3SCornelia Huck compat_props_add(mc->compat_props, hw_compat_5_1, hw_compat_5_1_len);
489029bfe52aSDaniel Henrique Barboza smc->pre_5_2_numa_associativity = true;
48913ff3c5d3SCornelia Huck }
48923ff3c5d3SCornelia Huck
48938d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(5, 1);
4894541aaa1dSCornelia Huck
4895541aaa1dSCornelia Huck /*
4896541aaa1dSCornelia Huck * pseries-5.0
4897541aaa1dSCornelia Huck */
spapr_machine_5_0_class_options(MachineClass * mc)4898541aaa1dSCornelia Huck static void spapr_machine_5_0_class_options(MachineClass *mc)
4899541aaa1dSCornelia Huck {
4900a6030d7eSReza Arbab SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
4901a6030d7eSReza Arbab static GlobalProperty compat[] = {
4902a6030d7eSReza Arbab { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-5.1-associativity", "on" },
4903a6030d7eSReza Arbab };
4904a6030d7eSReza Arbab
4905541aaa1dSCornelia Huck spapr_machine_5_1_class_options(mc);
4906541aaa1dSCornelia Huck compat_props_add(mc->compat_props, hw_compat_5_0, hw_compat_5_0_len);
4907a6030d7eSReza Arbab compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
490832a354dcSIgor Mammedov mc->numa_mem_supported = true;
4909a6030d7eSReza Arbab smc->pre_5_1_assoc_refpoints = true;
4910541aaa1dSCornelia Huck }
4911541aaa1dSCornelia Huck
49128d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(5, 0);
49133eb74d20SCornelia Huck
49143eb74d20SCornelia Huck /*
49159aec2e52SCornelia Huck * pseries-4.2
4916e2676b16SGreg Kurz */
spapr_machine_4_2_class_options(MachineClass * mc)49179aec2e52SCornelia Huck static void spapr_machine_4_2_class_options(MachineClass *mc)
4918e2676b16SGreg Kurz {
491937965dfeSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
492037965dfeSDavid Gibson
49213eb74d20SCornelia Huck spapr_machine_5_0_class_options(mc);
49225f258577SEvgeny Yakovlev compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len);
492337965dfeSDavid Gibson smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF;
49248af7e1feSNicholas Piggin smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_OFF;
49251052ab67SDavid Gibson smc->rma_limit = 16 * GiB;
4926ee3a71e3SShivaprasad G Bhat mc->nvdimm_supported = false;
4927e2676b16SGreg Kurz }
4928e2676b16SGreg Kurz
49298d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(4, 2);
49309aec2e52SCornelia Huck
49319aec2e52SCornelia Huck /*
49329aec2e52SCornelia Huck * pseries-4.1
49339aec2e52SCornelia Huck */
spapr_machine_4_1_class_options(MachineClass * mc)49349aec2e52SCornelia Huck static void spapr_machine_4_1_class_options(MachineClass *mc)
49359aec2e52SCornelia Huck {
49366c3829a2SAlexey Kardashevskiy SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
4937d15d4ad6SDavid Gibson static GlobalProperty compat[] = {
4938d15d4ad6SDavid Gibson /* Only allow 4kiB and 64kiB IOMMU pagesizes */
4939d15d4ad6SDavid Gibson { TYPE_SPAPR_PCI_HOST_BRIDGE, "pgsz", "0x11000" },
4940d15d4ad6SDavid Gibson };
4941d15d4ad6SDavid Gibson
49429aec2e52SCornelia Huck spapr_machine_4_2_class_options(mc);
49436c3829a2SAlexey Kardashevskiy smc->linux_pci_probe = false;
494429cb4187SGreg Kurz smc->smp_threads_vsmt = false;
49459aec2e52SCornelia Huck compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len);
4946d15d4ad6SDavid Gibson compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
49479aec2e52SCornelia Huck }
49489aec2e52SCornelia Huck
49498d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(4, 1);
49509bf2650bSCornelia Huck
49519bf2650bSCornelia Huck /*
49529bf2650bSCornelia Huck * pseries-4.0
49539bf2650bSCornelia Huck */
phb_placement_4_0(SpaprMachineState * spapr,uint32_t index,uint64_t * buid,hwaddr * pio,hwaddr * mmio32,hwaddr * mmio64,unsigned n_dma,uint32_t * liobns,Error ** errp)4954f5598c92SGreg Kurz static bool phb_placement_4_0(SpaprMachineState *spapr, uint32_t index,
4955ec132efaSAlexey Kardashevskiy uint64_t *buid, hwaddr *pio,
4956ec132efaSAlexey Kardashevskiy hwaddr *mmio32, hwaddr *mmio64,
495744fa20c9SCédric Le Goater unsigned n_dma, uint32_t *liobns, Error **errp)
4958ec132efaSAlexey Kardashevskiy {
4959f5598c92SGreg Kurz if (!spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma,
496044fa20c9SCédric Le Goater liobns, errp)) {
4961f5598c92SGreg Kurz return false;
4962ec132efaSAlexey Kardashevskiy }
4963f5598c92SGreg Kurz return true;
4964f5598c92SGreg Kurz }
spapr_machine_4_0_class_options(MachineClass * mc)4965eb3cba82SDavid Gibson static void spapr_machine_4_0_class_options(MachineClass *mc)
4966eb3cba82SDavid Gibson {
4967eb3cba82SDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
4968eb3cba82SDavid Gibson
4969eb3cba82SDavid Gibson spapr_machine_4_1_class_options(mc);
4970eb3cba82SDavid Gibson compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
4971eb3cba82SDavid Gibson smc->phb_placement = phb_placement_4_0;
4972bd94bc06SCédric Le Goater smc->irq = &spapr_irq_xics;
49733725ef1aSGreg Kurz smc->pre_4_1_migration = true;
4974eb3cba82SDavid Gibson }
4975eb3cba82SDavid Gibson
49768d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(4, 0);
4977eb3cba82SDavid Gibson
4978eb3cba82SDavid Gibson /*
4979eb3cba82SDavid Gibson * pseries-3.1
4980eb3cba82SDavid Gibson */
spapr_machine_3_1_class_options(MachineClass * mc)498188cbe073SMarc-André Lureau static void spapr_machine_3_1_class_options(MachineClass *mc)
498288cbe073SMarc-André Lureau {
4983ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
4984fea35ca4SAlexey Kardashevskiy
498584e060bfSAlex Williamson spapr_machine_4_0_class_options(mc);
4986abd93cc7SMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len);
498727461d69SPrasad J Pandit
498834a6b015SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
4989fea35ca4SAlexey Kardashevskiy smc->update_dt_enabled = false;
4990dae5e39aSMichael Roth smc->dr_phb_enabled = false;
49910a794529SDavid Gibson smc->broken_host_serial_model = true;
49922782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
49932782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
49942782ad4cSSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
4995edaa7995SSuraj Jitindar Singh smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF;
499684e060bfSAlex Williamson }
499784e060bfSAlex Williamson
49988d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(3, 1);
4999d45360d9SCédric Le Goater
5000d45360d9SCédric Le Goater /*
5001d45360d9SCédric Le Goater * pseries-3.0
5002d45360d9SCédric Le Goater */
5003d45360d9SCédric Le Goater
spapr_machine_3_0_class_options(MachineClass * mc)5004d45360d9SCédric Le Goater static void spapr_machine_3_0_class_options(MachineClass *mc)
5005d45360d9SCédric Le Goater {
5006ce2918cbSDavid Gibson SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
500782cffa2eSCédric Le Goater
5008d45360d9SCédric Le Goater spapr_machine_3_1_class_options(mc);
5009ddb3235dSMarc-André Lureau compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len);
501082cffa2eSCédric Le Goater
501182cffa2eSCédric Le Goater smc->legacy_irq_allocation = true;
501254255c1fSDavid Gibson smc->nr_xirqs = 0x400;
5013ae837402SCédric Le Goater smc->irq = &spapr_irq_xics_legacy;
5014d45360d9SCédric Le Goater }
5015d45360d9SCédric Le Goater
50168d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(3, 0);
50178a4fd427SDavid Gibson
spapr_machine_register_types(void)501829ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void)
501929ee3247SAlexey Kardashevskiy {
502029ee3247SAlexey Kardashevskiy type_register_static(&spapr_machine_info);
502129ee3247SAlexey Kardashevskiy }
502229ee3247SAlexey Kardashevskiy
502329ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types)
5024