xref: /openbmc/qemu/hw/ppc/spapr.c (revision 1a7a31ae)
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 
pre_2_10_vmstate_dummy_icp_needed(void * opaque)13546f7afa3SGreg Kurz static bool pre_2_10_vmstate_dummy_icp_needed(void *opaque)
13646f7afa3SGreg Kurz {
13746f7afa3SGreg Kurz     /* Dummy entries correspond to unused ICPState objects in older QEMUs,
13846f7afa3SGreg Kurz      * and newer QEMUs don't even have them. In both cases, we don't want
13946f7afa3SGreg Kurz      * to send anything on the wire.
14046f7afa3SGreg Kurz      */
14146f7afa3SGreg Kurz     return false;
14246f7afa3SGreg Kurz }
14346f7afa3SGreg Kurz 
14446f7afa3SGreg Kurz static const VMStateDescription pre_2_10_vmstate_dummy_icp = {
145485fb955SJuan Quintela     /*
146485fb955SJuan Quintela      * Hack ahead.  We can't have two devices with the same name and
147485fb955SJuan Quintela      * instance id.  So I rename this to pass make check.
148485fb955SJuan Quintela      * Real help from people who knows the hardware is needed.
149485fb955SJuan Quintela      */
15046f7afa3SGreg Kurz     .name = "icp/server",
15146f7afa3SGreg Kurz     .version_id = 1,
15246f7afa3SGreg Kurz     .minimum_version_id = 1,
15346f7afa3SGreg Kurz     .needed = pre_2_10_vmstate_dummy_icp_needed,
154078ddbc9SRichard Henderson     .fields = (const VMStateField[]) {
15546f7afa3SGreg Kurz         VMSTATE_UNUSED(4), /* uint32_t xirr */
15646f7afa3SGreg Kurz         VMSTATE_UNUSED(1), /* uint8_t pending_priority */
15746f7afa3SGreg Kurz         VMSTATE_UNUSED(1), /* uint8_t mfrr */
15846f7afa3SGreg Kurz         VMSTATE_END_OF_LIST()
15946f7afa3SGreg Kurz     },
16046f7afa3SGreg Kurz };
16146f7afa3SGreg Kurz 
162485fb955SJuan Quintela /*
163485fb955SJuan Quintela  * See comment in hw/intc/xics.c:icp_realize()
164485fb955SJuan Quintela  *
165485fb955SJuan Quintela  * You have to remove vmstate_replace_hack_for_ppc() when you remove
166485fb955SJuan Quintela  * the machine types that need the following function.
167485fb955SJuan Quintela  */
pre_2_10_vmstate_register_dummy_icp(int i)16846f7afa3SGreg Kurz static void pre_2_10_vmstate_register_dummy_icp(int i)
16946f7afa3SGreg Kurz {
17046f7afa3SGreg Kurz     vmstate_register(NULL, i, &pre_2_10_vmstate_dummy_icp,
17146f7afa3SGreg Kurz                      (void *)(uintptr_t) i);
17246f7afa3SGreg Kurz }
17346f7afa3SGreg Kurz 
174485fb955SJuan Quintela /*
175485fb955SJuan Quintela  * See comment in hw/intc/xics.c:icp_realize()
176485fb955SJuan Quintela  *
177485fb955SJuan Quintela  * You have to remove vmstate_replace_hack_for_ppc() when you remove
178485fb955SJuan Quintela  * the machine types that need the following function.
179485fb955SJuan Quintela  */
pre_2_10_vmstate_unregister_dummy_icp(int i)18046f7afa3SGreg Kurz static void pre_2_10_vmstate_unregister_dummy_icp(int i)
18146f7afa3SGreg Kurz {
182485fb955SJuan Quintela     /*
183485fb955SJuan Quintela      * This used to be:
184485fb955SJuan Quintela      *
185485fb955SJuan Quintela      *    vmstate_unregister(NULL, &pre_2_10_vmstate_dummy_icp,
186485fb955SJuan Quintela      *                      (void *)(uintptr_t) i);
187485fb955SJuan Quintela      */
18846f7afa3SGreg Kurz }
18946f7afa3SGreg Kurz 
spapr_max_server_number(SpaprMachineState * spapr)190ce2918cbSDavid Gibson int spapr_max_server_number(SpaprMachineState *spapr)
19146f7afa3SGreg Kurz {
192fe6b6346SLike Xu     MachineState *ms = MACHINE(spapr);
193fe6b6346SLike Xu 
1941a5008fcSGreg Kurz     assert(spapr->vsmt);
195fe6b6346SLike Xu     return DIV_ROUND_UP(ms->smp.max_cpus * spapr->vsmt, ms->smp.threads);
19646f7afa3SGreg Kurz }
19746f7afa3SGreg Kurz 
spapr_fixup_cpu_smt_dt(void * fdt,int offset,PowerPCCPU * cpu,int smt_threads)198833d4668SAlexey Kardashevskiy static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu,
199833d4668SAlexey Kardashevskiy                                   int smt_threads)
200833d4668SAlexey Kardashevskiy {
201833d4668SAlexey Kardashevskiy     int i, ret = 0;
202a580fdcdSPhilippe Mathieu-Daudé     g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads);
203a580fdcdSPhilippe Mathieu-Daudé     g_autofree uint32_t *gservers_prop = g_new(uint32_t, smt_threads * 2);
20414bb4486SGreg Kurz     int index = spapr_get_vcpu_id(cpu);
205833d4668SAlexey Kardashevskiy 
206d6e166c0SDavid Gibson     if (cpu->compat_pvr) {
207d6e166c0SDavid Gibson         ret = fdt_setprop_cell(fdt, offset, "cpu-version", cpu->compat_pvr);
2086d9412eaSAlexey Kardashevskiy         if (ret < 0) {
2096d9412eaSAlexey Kardashevskiy             return ret;
2106d9412eaSAlexey Kardashevskiy         }
2116d9412eaSAlexey Kardashevskiy     }
2126d9412eaSAlexey Kardashevskiy 
213833d4668SAlexey Kardashevskiy     /* Build interrupt servers and gservers properties */
214833d4668SAlexey Kardashevskiy     for (i = 0; i < smt_threads; i++) {
215833d4668SAlexey Kardashevskiy         servers_prop[i] = cpu_to_be32(index + i);
216833d4668SAlexey Kardashevskiy         /* Hack, direct the group queues back to cpu 0 */
217833d4668SAlexey Kardashevskiy         gservers_prop[i*2] = cpu_to_be32(index + i);
218833d4668SAlexey Kardashevskiy         gservers_prop[i*2 + 1] = 0;
219833d4668SAlexey Kardashevskiy     }
220833d4668SAlexey Kardashevskiy     ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
221a580fdcdSPhilippe Mathieu-Daudé                       servers_prop, sizeof(*servers_prop) * smt_threads);
222833d4668SAlexey Kardashevskiy     if (ret < 0) {
223833d4668SAlexey Kardashevskiy         return ret;
224833d4668SAlexey Kardashevskiy     }
225833d4668SAlexey Kardashevskiy     ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-gserver#s",
226a580fdcdSPhilippe Mathieu-Daudé                       gservers_prop, sizeof(*gservers_prop) * smt_threads * 2);
227833d4668SAlexey Kardashevskiy 
228833d4668SAlexey Kardashevskiy     return ret;
229833d4668SAlexey Kardashevskiy }
230833d4668SAlexey Kardashevskiy 
spapr_dt_pa_features(SpaprMachineState * spapr,PowerPCCPU * cpu,void * fdt,int offset)23191335a5eSDavid Gibson static void spapr_dt_pa_features(SpaprMachineState *spapr,
232ee76a09fSDavid Gibson                                  PowerPCCPU *cpu,
233daa36379SDavid Gibson                                  void *fdt, int offset)
23486d5771aSSam Bobroff {
235a5a57786SNicholas Piggin     /*
236a5a57786SNicholas Piggin      * SSO (SAO) ordering is supported on KVM and thread=single hosts,
237a5a57786SNicholas Piggin      * but not MTTCG, so disable it. To advertise it, a cap would have
238a5a57786SNicholas Piggin      * to be added, or support implemented for MTTCG.
23917aa684fSNicholas Piggin      *
24017aa684fSNicholas Piggin      * Copy/paste is not supported by TCG, so it is not advertised. KVM
24117aa684fSNicholas Piggin      * can execute them but it has no accelerator drivers which are usable,
24217aa684fSNicholas Piggin      * so there isn't much need for it anyway.
243a5a57786SNicholas Piggin      */
244a5a57786SNicholas Piggin 
24524a9d20cSNicholas Piggin     /* These should be kept in sync with pnv */
24686d5771aSSam Bobroff     uint8_t pa_features_206[] = { 6, 0,
247a5a57786SNicholas Piggin         0xf6, 0x1f, 0xc7, 0x00, 0x00, 0xc0 };
24886d5771aSSam Bobroff     uint8_t pa_features_207[] = { 24, 0,
249a5a57786SNicholas Piggin         0xf6, 0x1f, 0xc7, 0xc0, 0x00, 0xf0,
25086d5771aSSam Bobroff         0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
25186d5771aSSam Bobroff         0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
25286d5771aSSam Bobroff         0x80, 0x00, 0x80, 0x00, 0x00, 0x00 };
2539fb4541fSSam Bobroff     uint8_t pa_features_300[] = { 66, 0,
2549fb4541fSSam Bobroff         /* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */
255a5a57786SNicholas Piggin         /* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, 5: LE|CFAR|EB|LSQ */
256a5a57786SNicholas Piggin         0xf6, 0x1f, 0xc7, 0xc0, 0x00, 0xf0, /* 0 - 5 */
2579fb4541fSSam Bobroff         /* 6: DS207 */
25886d5771aSSam Bobroff         0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */
2599fb4541fSSam Bobroff         /* 16: Vector */
26086d5771aSSam Bobroff         0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */
2618b0e3fb8SNicholas Piggin         /* 18: Vec. Scalar, 20: Vec. XOR */
2629bf502feSDavid Gibson         0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */
2639fb4541fSSam Bobroff         /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */
2649fb4541fSSam Bobroff         0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */
2658b0e3fb8SNicholas Piggin         /* 32: LE atomic, 34: EBB + ext EBB */
2668b0e3fb8SNicholas Piggin         0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */
2678b0e3fb8SNicholas Piggin         /* 40: Radix MMU */
2688b0e3fb8SNicholas Piggin         0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 36 - 41 */
2699fb4541fSSam Bobroff         /* 42: PM, 44: PC RA, 46: SC vec'd */
2709fb4541fSSam Bobroff         0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */
2719fb4541fSSam Bobroff         /* 48: SIMD, 50: QP BFP, 52: String */
2729fb4541fSSam Bobroff         0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */
2739fb4541fSSam Bobroff         /* 54: DecFP, 56: DecI, 58: SHA */
2749fb4541fSSam Bobroff         0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */
2759fb4541fSSam Bobroff         /* 60: NM atomic, 62: RNG */
2769fb4541fSSam Bobroff         0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */
2779fb4541fSSam Bobroff     };
278d83d350cSBenjamin Gray     /* 3.1 removes SAO, HTM support */
279d83d350cSBenjamin Gray     uint8_t pa_features_31[] = { 74, 0,
280d83d350cSBenjamin Gray         /* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */
281d83d350cSBenjamin Gray         /* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, 5: LE|CFAR|EB|LSQ */
282d83d350cSBenjamin Gray         0xf6, 0x1f, 0xc7, 0xc0, 0x00, 0xf0, /* 0 - 5 */
283d83d350cSBenjamin Gray         /* 6: DS207 */
284d83d350cSBenjamin Gray         0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */
285d83d350cSBenjamin Gray         /* 16: Vector */
286d83d350cSBenjamin Gray         0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */
287d83d350cSBenjamin Gray         /* 18: Vec. Scalar, 20: Vec. XOR */
288d83d350cSBenjamin Gray         0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */
289d83d350cSBenjamin Gray         /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */
290d83d350cSBenjamin Gray         0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */
291d83d350cSBenjamin Gray         /* 32: LE atomic, 34: EBB + ext EBB */
292d83d350cSBenjamin Gray         0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */
293d83d350cSBenjamin Gray         /* 40: Radix MMU */
294d83d350cSBenjamin Gray         0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 36 - 41 */
295d83d350cSBenjamin Gray         /* 42: PM, 44: PC RA, 46: SC vec'd */
296d83d350cSBenjamin Gray         0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */
297d83d350cSBenjamin Gray         /* 48: SIMD, 50: QP BFP, 52: String */
298d83d350cSBenjamin Gray         0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */
299d83d350cSBenjamin Gray         /* 54: DecFP, 56: DecI, 58: SHA */
300d83d350cSBenjamin Gray         0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */
301d83d350cSBenjamin Gray         /* 60: NM atomic, 62: RNG */
302d83d350cSBenjamin Gray         0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */
303d83d350cSBenjamin Gray         /* 68: DEXCR[SBHE|IBRTPDUS|SRAPD|NPHIE|PHIE] */
304d83d350cSBenjamin Gray         0x00, 0x00, 0xce, 0x00, 0x00, 0x00, /* 66 - 71 */
305d83d350cSBenjamin Gray         /* 72: [P]HASHST/[P]HASHCHK */
306d83d350cSBenjamin Gray         0x80, 0x00,                         /* 72 - 73 */
307d83d350cSBenjamin Gray     };
3087abd43baSSuraj Jitindar Singh     uint8_t *pa_features = NULL;
30986d5771aSSam Bobroff     size_t pa_size;
31086d5771aSSam Bobroff 
3117abd43baSSuraj Jitindar Singh     if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06, 0, cpu->compat_pvr)) {
31286d5771aSSam Bobroff         pa_features = pa_features_206;
31386d5771aSSam Bobroff         pa_size = sizeof(pa_features_206);
3147abd43baSSuraj Jitindar Singh     }
3157abd43baSSuraj Jitindar Singh     if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07, 0, cpu->compat_pvr)) {
31686d5771aSSam Bobroff         pa_features = pa_features_207;
31786d5771aSSam Bobroff         pa_size = sizeof(pa_features_207);
3187abd43baSSuraj Jitindar Singh     }
3197abd43baSSuraj Jitindar Singh     if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0, cpu->compat_pvr)) {
32086d5771aSSam Bobroff         pa_features = pa_features_300;
32186d5771aSSam Bobroff         pa_size = sizeof(pa_features_300);
3227abd43baSSuraj Jitindar Singh     }
323d83d350cSBenjamin Gray     if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_10, 0, cpu->compat_pvr)) {
324d83d350cSBenjamin Gray         pa_features = pa_features_31;
325d83d350cSBenjamin Gray         pa_size = sizeof(pa_features_31);
326d83d350cSBenjamin Gray     }
3277abd43baSSuraj Jitindar Singh     if (!pa_features) {
32886d5771aSSam Bobroff         return;
32986d5771aSSam Bobroff     }
33086d5771aSSam Bobroff 
33126cd35b8SDavid Gibson     if (ppc_hash64_has(cpu, PPC_HASH64_CI_LARGEPAGE)) {
33286d5771aSSam Bobroff         /*
33386d5771aSSam Bobroff          * Note: we keep CI large pages off by default because a 64K capable
33486d5771aSSam Bobroff          * guest provisioned with large pages might otherwise try to map a qemu
33586d5771aSSam Bobroff          * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages
33686d5771aSSam Bobroff          * even if that qemu runs on a 4k host.
33786d5771aSSam Bobroff          * We dd this bit back here if we are confident this is not an issue
33886d5771aSSam Bobroff          */
33986d5771aSSam Bobroff         pa_features[3] |= 0x20;
34086d5771aSSam Bobroff     }
3414e5fe368SSuraj Jitindar Singh     if ((spapr_get_cap(spapr, SPAPR_CAP_HTM) != 0) && pa_size > 24) {
34286d5771aSSam Bobroff         pa_features[24] |= 0x80;    /* Transactional memory support */
34386d5771aSSam Bobroff     }
344daa36379SDavid Gibson     if (spapr->cas_pre_isa3_guest && pa_size > 40) {
345e957f6a9SSam Bobroff         /* Workaround for broken kernels that attempt (guest) radix
346e957f6a9SSam Bobroff          * mode when they can't handle it, if they see the radix bit set
347e957f6a9SSam Bobroff          * in pa-features. So hide it from them. */
348e957f6a9SSam Bobroff         pa_features[40 + 2] &= ~0x80; /* Radix MMU */
349e957f6a9SSam Bobroff     }
35086d5771aSSam Bobroff 
35186d5771aSSam Bobroff     _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size)));
35286d5771aSSam Bobroff }
35386d5771aSSam Bobroff 
spapr_dt_pi_features(SpaprMachineState * spapr,PowerPCCPU * cpu,void * fdt,int offset)35495912ce1SNicholas Piggin static void spapr_dt_pi_features(SpaprMachineState *spapr,
35595912ce1SNicholas Piggin                                  PowerPCCPU *cpu,
35695912ce1SNicholas Piggin                                  void *fdt, int offset)
35795912ce1SNicholas Piggin {
35895912ce1SNicholas Piggin     uint8_t pi_features[] = { 1, 0,
35995912ce1SNicholas Piggin         0x00 };
36095912ce1SNicholas Piggin 
36195912ce1SNicholas Piggin     if (kvm_enabled() && ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00,
36295912ce1SNicholas Piggin                                           0, cpu->compat_pvr)) {
36395912ce1SNicholas Piggin         /*
36495912ce1SNicholas Piggin          * POWER9 and later CPUs with KVM run in LPAR-per-thread mode where
36595912ce1SNicholas Piggin          * all threads are essentially independent CPUs, and msgsndp does not
36695912ce1SNicholas Piggin          * work (because it is physically-addressed) and therefore is
36795912ce1SNicholas Piggin          * emulated by KVM, so disable it here to ensure XIVE will be used.
36895912ce1SNicholas Piggin          * This is both KVM and CPU implementation-specific behaviour so a KVM
36995912ce1SNicholas Piggin          * cap would be cleanest, but for now this works. If KVM ever permits
37095912ce1SNicholas Piggin          * native msgsndp execution by guests, a cap could be added at that
37195912ce1SNicholas Piggin          * time.
37295912ce1SNicholas Piggin          */
37395912ce1SNicholas Piggin         pi_features[2] |= 0x08; /* 4: No msgsndp */
37495912ce1SNicholas Piggin     }
37595912ce1SNicholas Piggin 
37695912ce1SNicholas Piggin     _FDT((fdt_setprop(fdt, offset, "ibm,pi-features", pi_features,
37795912ce1SNicholas Piggin                       sizeof(pi_features))));
37895912ce1SNicholas Piggin }
37995912ce1SNicholas Piggin 
spapr_node0_size(MachineState * machine)380c86c1affSDaniel Henrique Barboza static hwaddr spapr_node0_size(MachineState *machine)
381b082d65aSAlexey Kardashevskiy {
382aa570207STao Xu     if (machine->numa_state->num_nodes) {
383b082d65aSAlexey Kardashevskiy         int i;
384aa570207STao Xu         for (i = 0; i < machine->numa_state->num_nodes; ++i) {
3857e721e7bSTao Xu             if (machine->numa_state->nodes[i].node_mem) {
3867e721e7bSTao Xu                 return MIN(pow2floor(machine->numa_state->nodes[i].node_mem),
387fb164994SDavid Gibson                            machine->ram_size);
388b082d65aSAlexey Kardashevskiy             }
389b082d65aSAlexey Kardashevskiy         }
390b082d65aSAlexey Kardashevskiy     }
391fb164994SDavid Gibson     return machine->ram_size;
392b082d65aSAlexey Kardashevskiy }
393b082d65aSAlexey Kardashevskiy 
add_str(GString * s,const gchar * s1)394a1d59c0fSAlexey Kardashevskiy static void add_str(GString *s, const gchar *s1)
395a1d59c0fSAlexey Kardashevskiy {
396a1d59c0fSAlexey Kardashevskiy     g_string_append_len(s, s1, strlen(s1) + 1);
397a1d59c0fSAlexey Kardashevskiy }
39853018216SPaolo Bonzini 
spapr_dt_memory_node(SpaprMachineState * spapr,void * fdt,int nodeid,hwaddr start,hwaddr size)399f1aa45ffSDaniel Henrique Barboza static int spapr_dt_memory_node(SpaprMachineState *spapr, void *fdt, int nodeid,
400f1aa45ffSDaniel Henrique Barboza                                 hwaddr start, hwaddr size)
40126a8c353SAlexey Kardashevskiy {
40226a8c353SAlexey Kardashevskiy     char mem_name[32];
40326a8c353SAlexey Kardashevskiy     uint64_t mem_reg_property[2];
40426a8c353SAlexey Kardashevskiy     int off;
40526a8c353SAlexey Kardashevskiy 
40626a8c353SAlexey Kardashevskiy     mem_reg_property[0] = cpu_to_be64(start);
40726a8c353SAlexey Kardashevskiy     mem_reg_property[1] = cpu_to_be64(size);
40826a8c353SAlexey Kardashevskiy 
4093a17e38fSAlexey Kardashevskiy     sprintf(mem_name, "memory@%" HWADDR_PRIx, start);
41026a8c353SAlexey Kardashevskiy     off = fdt_add_subnode(fdt, 0, mem_name);
41126a8c353SAlexey Kardashevskiy     _FDT(off);
41226a8c353SAlexey Kardashevskiy     _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
41326a8c353SAlexey Kardashevskiy     _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
41426a8c353SAlexey Kardashevskiy                       sizeof(mem_reg_property))));
415f1aa45ffSDaniel Henrique Barboza     spapr_numa_write_associativity_dt(spapr, fdt, off, nodeid);
41603d196b7SBharata B Rao     return off;
41726a8c353SAlexey Kardashevskiy }
41826a8c353SAlexey Kardashevskiy 
spapr_pc_dimm_node(MemoryDeviceInfoList * list,ram_addr_t addr)419f47bd1c8SIgor Mammedov static uint32_t spapr_pc_dimm_node(MemoryDeviceInfoList *list, ram_addr_t addr)
420f47bd1c8SIgor Mammedov {
421f47bd1c8SIgor Mammedov     MemoryDeviceInfoList *info;
422f47bd1c8SIgor Mammedov 
423f47bd1c8SIgor Mammedov     for (info = list; info; info = info->next) {
424f47bd1c8SIgor Mammedov         MemoryDeviceInfo *value = info->value;
425f47bd1c8SIgor Mammedov 
426f47bd1c8SIgor Mammedov         if (value && value->type == MEMORY_DEVICE_INFO_KIND_DIMM) {
427f47bd1c8SIgor Mammedov             PCDIMMDeviceInfo *pcdimm_info = value->u.dimm.data;
428f47bd1c8SIgor Mammedov 
429ccc2cef8SDavid Gibson             if (addr >= pcdimm_info->addr &&
430f47bd1c8SIgor Mammedov                 addr < (pcdimm_info->addr + pcdimm_info->size)) {
431f47bd1c8SIgor Mammedov                 return pcdimm_info->node;
432f47bd1c8SIgor Mammedov             }
433f47bd1c8SIgor Mammedov         }
434f47bd1c8SIgor Mammedov     }
435f47bd1c8SIgor Mammedov 
436f47bd1c8SIgor Mammedov     return -1;
437f47bd1c8SIgor Mammedov }
438f47bd1c8SIgor Mammedov 
439a324d6f1SBharata B Rao struct sPAPRDrconfCellV2 {
440a324d6f1SBharata B Rao      uint32_t seq_lmbs;
441a324d6f1SBharata B Rao      uint64_t base_addr;
442a324d6f1SBharata B Rao      uint32_t drc_index;
443a324d6f1SBharata B Rao      uint32_t aa_index;
444a324d6f1SBharata B Rao      uint32_t flags;
445a324d6f1SBharata B Rao } QEMU_PACKED;
446a324d6f1SBharata B Rao 
447a324d6f1SBharata B Rao typedef struct DrconfCellQueue {
448a324d6f1SBharata B Rao     struct sPAPRDrconfCellV2 cell;
449a324d6f1SBharata B Rao     QSIMPLEQ_ENTRY(DrconfCellQueue) entry;
450a324d6f1SBharata B Rao } DrconfCellQueue;
451a324d6f1SBharata B Rao 
452a324d6f1SBharata 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)453a324d6f1SBharata B Rao spapr_get_drconf_cell(uint32_t seq_lmbs, uint64_t base_addr,
454a324d6f1SBharata B Rao                       uint32_t drc_index, uint32_t aa_index,
455a324d6f1SBharata B Rao                       uint32_t flags)
45603d196b7SBharata B Rao {
457a324d6f1SBharata B Rao     DrconfCellQueue *elem;
458a324d6f1SBharata B Rao 
459a324d6f1SBharata B Rao     elem = g_malloc0(sizeof(*elem));
460a324d6f1SBharata B Rao     elem->cell.seq_lmbs = cpu_to_be32(seq_lmbs);
461a324d6f1SBharata B Rao     elem->cell.base_addr = cpu_to_be64(base_addr);
462a324d6f1SBharata B Rao     elem->cell.drc_index = cpu_to_be32(drc_index);
463a324d6f1SBharata B Rao     elem->cell.aa_index = cpu_to_be32(aa_index);
464a324d6f1SBharata B Rao     elem->cell.flags = cpu_to_be32(flags);
465a324d6f1SBharata B Rao 
466a324d6f1SBharata B Rao     return elem;
467a324d6f1SBharata B Rao }
468a324d6f1SBharata B Rao 
spapr_dt_dynamic_memory_v2(SpaprMachineState * spapr,void * fdt,int offset,MemoryDeviceInfoList * dimms)46991335a5eSDavid Gibson static int spapr_dt_dynamic_memory_v2(SpaprMachineState *spapr, void *fdt,
470a324d6f1SBharata B Rao                                       int offset, MemoryDeviceInfoList *dimms)
4712a6593cbSAlexey Kardashevskiy {
4722a6593cbSAlexey Kardashevskiy     MachineState *machine = MACHINE(spapr);
473cc941111SFabiano Rosas     uint8_t *int_buf, *cur_index;
474a324d6f1SBharata B Rao     int ret;
47503d196b7SBharata B Rao     uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
476a324d6f1SBharata B Rao     uint64_t addr, cur_addr, size;
477b0c14ec4SDavid Hildenbrand     uint32_t nr_boot_lmbs = (machine->device_memory->base / lmb_size);
478b0c14ec4SDavid Hildenbrand     uint64_t mem_end = machine->device_memory->base +
479b0c14ec4SDavid Hildenbrand                        memory_region_size(&machine->device_memory->mr);
480cc941111SFabiano Rosas     uint32_t node, buf_len, nr_entries = 0;
481ce2918cbSDavid Gibson     SpaprDrc *drc;
482a324d6f1SBharata B Rao     DrconfCellQueue *elem, *next;
483a324d6f1SBharata B Rao     MemoryDeviceInfoList *info;
484a324d6f1SBharata B Rao     QSIMPLEQ_HEAD(, DrconfCellQueue) drconf_queue
485a324d6f1SBharata B Rao         = QSIMPLEQ_HEAD_INITIALIZER(drconf_queue);
486a324d6f1SBharata B Rao 
487a324d6f1SBharata B Rao     /* Entry to cover RAM and the gap area */
488a324d6f1SBharata B Rao     elem = spapr_get_drconf_cell(nr_boot_lmbs, 0, 0, -1,
489a324d6f1SBharata B Rao                                  SPAPR_LMB_FLAGS_RESERVED |
490a324d6f1SBharata B Rao                                  SPAPR_LMB_FLAGS_DRC_INVALID);
491a324d6f1SBharata B Rao     QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry);
492a324d6f1SBharata B Rao     nr_entries++;
493a324d6f1SBharata B Rao 
494b0c14ec4SDavid Hildenbrand     cur_addr = machine->device_memory->base;
495a324d6f1SBharata B Rao     for (info = dimms; info; info = info->next) {
496a324d6f1SBharata B Rao         PCDIMMDeviceInfo *di = info->value->u.dimm.data;
497a324d6f1SBharata B Rao 
498a324d6f1SBharata B Rao         addr = di->addr;
499a324d6f1SBharata B Rao         size = di->size;
500a324d6f1SBharata B Rao         node = di->node;
501a324d6f1SBharata B Rao 
502ee3a71e3SShivaprasad G Bhat         /*
503ee3a71e3SShivaprasad G Bhat          * The NVDIMM area is hotpluggable after the NVDIMM is unplugged. The
504ee3a71e3SShivaprasad G Bhat          * area is marked hotpluggable in the next iteration for the bigger
505ee3a71e3SShivaprasad G Bhat          * chunk including the NVDIMM occupied area.
506ee3a71e3SShivaprasad G Bhat          */
507ee3a71e3SShivaprasad G Bhat         if (info->value->type == MEMORY_DEVICE_INFO_KIND_NVDIMM)
508ee3a71e3SShivaprasad G Bhat             continue;
509ee3a71e3SShivaprasad G Bhat 
510a324d6f1SBharata B Rao         /* Entry for hot-pluggable area */
511a324d6f1SBharata B Rao         if (cur_addr < addr) {
512a324d6f1SBharata B Rao             drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size);
513a324d6f1SBharata B Rao             g_assert(drc);
514a324d6f1SBharata B Rao             elem = spapr_get_drconf_cell((addr - cur_addr) / lmb_size,
515a324d6f1SBharata B Rao                                          cur_addr, spapr_drc_index(drc), -1, 0);
516a324d6f1SBharata B Rao             QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry);
517a324d6f1SBharata B Rao             nr_entries++;
518a324d6f1SBharata B Rao         }
519a324d6f1SBharata B Rao 
520a324d6f1SBharata B Rao         /* Entry for DIMM */
521a324d6f1SBharata B Rao         drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr / lmb_size);
522a324d6f1SBharata B Rao         g_assert(drc);
523a324d6f1SBharata B Rao         elem = spapr_get_drconf_cell(size / lmb_size, addr,
524a324d6f1SBharata B Rao                                      spapr_drc_index(drc), node,
5250911a60cSLeonardo Bras                                      (SPAPR_LMB_FLAGS_ASSIGNED |
5260911a60cSLeonardo Bras                                       SPAPR_LMB_FLAGS_HOTREMOVABLE));
527a324d6f1SBharata B Rao         QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry);
528a324d6f1SBharata B Rao         nr_entries++;
529a324d6f1SBharata B Rao         cur_addr = addr + size;
530a324d6f1SBharata B Rao     }
531a324d6f1SBharata B Rao 
532a324d6f1SBharata B Rao     /* Entry for remaining hotpluggable area */
533a324d6f1SBharata B Rao     if (cur_addr < mem_end) {
534a324d6f1SBharata B Rao         drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size);
535a324d6f1SBharata B Rao         g_assert(drc);
536a324d6f1SBharata B Rao         elem = spapr_get_drconf_cell((mem_end - cur_addr) / lmb_size,
537a324d6f1SBharata B Rao                                      cur_addr, spapr_drc_index(drc), -1, 0);
538a324d6f1SBharata B Rao         QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry);
539a324d6f1SBharata B Rao         nr_entries++;
540a324d6f1SBharata B Rao     }
541a324d6f1SBharata B Rao 
542a324d6f1SBharata B Rao     buf_len = nr_entries * sizeof(struct sPAPRDrconfCellV2) + sizeof(uint32_t);
543a324d6f1SBharata B Rao     int_buf = cur_index = g_malloc0(buf_len);
544a324d6f1SBharata B Rao     *(uint32_t *)int_buf = cpu_to_be32(nr_entries);
545a324d6f1SBharata B Rao     cur_index += sizeof(nr_entries);
546a324d6f1SBharata B Rao 
547a324d6f1SBharata B Rao     QSIMPLEQ_FOREACH_SAFE(elem, &drconf_queue, entry, next) {
548a324d6f1SBharata B Rao         memcpy(cur_index, &elem->cell, sizeof(elem->cell));
549a324d6f1SBharata B Rao         cur_index += sizeof(elem->cell);
550a324d6f1SBharata B Rao         QSIMPLEQ_REMOVE(&drconf_queue, elem, DrconfCellQueue, entry);
551a324d6f1SBharata B Rao         g_free(elem);
552a324d6f1SBharata B Rao     }
553a324d6f1SBharata B Rao 
554a324d6f1SBharata B Rao     ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory-v2", int_buf, buf_len);
555a324d6f1SBharata B Rao     g_free(int_buf);
556a324d6f1SBharata B Rao     if (ret < 0) {
557a324d6f1SBharata B Rao         return -1;
558a324d6f1SBharata B Rao     }
559a324d6f1SBharata B Rao     return 0;
560a324d6f1SBharata B Rao }
561a324d6f1SBharata B Rao 
spapr_dt_dynamic_memory(SpaprMachineState * spapr,void * fdt,int offset,MemoryDeviceInfoList * dimms)56291335a5eSDavid Gibson static int spapr_dt_dynamic_memory(SpaprMachineState *spapr, void *fdt,
563a324d6f1SBharata B Rao                                    int offset, MemoryDeviceInfoList *dimms)
564a324d6f1SBharata B Rao {
565b0c14ec4SDavid Hildenbrand     MachineState *machine = MACHINE(spapr);
566a324d6f1SBharata B Rao     int i, ret;
567a324d6f1SBharata B Rao     uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
5680c9269a5SDavid Hildenbrand     uint32_t device_lmb_start = machine->device_memory->base / lmb_size;
569b0c14ec4SDavid Hildenbrand     uint32_t nr_lmbs = (machine->device_memory->base +
570b0c14ec4SDavid Hildenbrand                        memory_region_size(&machine->device_memory->mr)) /
571d0e5a8f2SBharata B Rao                        lmb_size;
57203d196b7SBharata B Rao     uint32_t *int_buf, *cur_index, buf_len;
57316c25aefSBharata B Rao 
57416c25aefSBharata B Rao     /*
575ef001f06SThomas Huth      * Allocate enough buffer size to fit in ibm,dynamic-memory
576ef001f06SThomas Huth      */
577a324d6f1SBharata B Rao     buf_len = (nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1) * sizeof(uint32_t);
57803d196b7SBharata B Rao     cur_index = int_buf = g_malloc0(buf_len);
57903d196b7SBharata B Rao     int_buf[0] = cpu_to_be32(nr_lmbs);
58003d196b7SBharata B Rao     cur_index++;
58103d196b7SBharata B Rao     for (i = 0; i < nr_lmbs; i++) {
582d0e5a8f2SBharata B Rao         uint64_t addr = i * lmb_size;
58303d196b7SBharata B Rao         uint32_t *dynamic_memory = cur_index;
58403d196b7SBharata B Rao 
5850c9269a5SDavid Hildenbrand         if (i >= device_lmb_start) {
586ce2918cbSDavid Gibson             SpaprDrc *drc;
587d0e5a8f2SBharata B Rao 
588fbf55397SDavid Gibson             drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, i);
58903d196b7SBharata B Rao             g_assert(drc);
59003d196b7SBharata B Rao 
59103d196b7SBharata B Rao             dynamic_memory[0] = cpu_to_be32(addr >> 32);
59203d196b7SBharata B Rao             dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff);
5930b55aa91SDavid Gibson             dynamic_memory[2] = cpu_to_be32(spapr_drc_index(drc));
59403d196b7SBharata B Rao             dynamic_memory[3] = cpu_to_be32(0); /* reserved */
595f47bd1c8SIgor Mammedov             dynamic_memory[4] = cpu_to_be32(spapr_pc_dimm_node(dimms, addr));
596d0e5a8f2SBharata B Rao             if (memory_region_present(get_system_memory(), addr)) {
59703d196b7SBharata B Rao                 dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED);
59803d196b7SBharata B Rao             } else {
59903d196b7SBharata B Rao                 dynamic_memory[5] = cpu_to_be32(0);
60003d196b7SBharata B Rao             }
601d0e5a8f2SBharata B Rao         } else {
602d0e5a8f2SBharata B Rao             /*
603d0e5a8f2SBharata B Rao              * LMB information for RMA, boot time RAM and gap b/n RAM and
6040c9269a5SDavid Hildenbrand              * device memory region -- all these are marked as reserved
605d0e5a8f2SBharata B Rao              * and as having no valid DRC.
606d0e5a8f2SBharata B Rao              */
607d0e5a8f2SBharata B Rao             dynamic_memory[0] = cpu_to_be32(addr >> 32);
608d0e5a8f2SBharata B Rao             dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff);
609d0e5a8f2SBharata B Rao             dynamic_memory[2] = cpu_to_be32(0);
610d0e5a8f2SBharata B Rao             dynamic_memory[3] = cpu_to_be32(0); /* reserved */
611d0e5a8f2SBharata B Rao             dynamic_memory[4] = cpu_to_be32(-1);
612d0e5a8f2SBharata B Rao             dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED |
613d0e5a8f2SBharata B Rao                                             SPAPR_LMB_FLAGS_DRC_INVALID);
614d0e5a8f2SBharata B Rao         }
61503d196b7SBharata B Rao 
61603d196b7SBharata B Rao         cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE;
61703d196b7SBharata B Rao     }
61803d196b7SBharata B Rao     ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len);
619a324d6f1SBharata B Rao     g_free(int_buf);
62003d196b7SBharata B Rao     if (ret < 0) {
621a324d6f1SBharata B Rao         return -1;
622a324d6f1SBharata B Rao     }
623a324d6f1SBharata B Rao     return 0;
624a324d6f1SBharata B Rao }
625a324d6f1SBharata B Rao 
626a324d6f1SBharata B Rao /*
627a324d6f1SBharata B Rao  * Adds ibm,dynamic-reconfiguration-memory node.
628a324d6f1SBharata B Rao  * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation
629a324d6f1SBharata B Rao  * of this device tree node.
630a324d6f1SBharata B Rao  */
spapr_dt_dynamic_reconfiguration_memory(SpaprMachineState * spapr,void * fdt)63191335a5eSDavid Gibson static int spapr_dt_dynamic_reconfiguration_memory(SpaprMachineState *spapr,
63291335a5eSDavid Gibson                                                    void *fdt)
633a324d6f1SBharata B Rao {
634a324d6f1SBharata B Rao     MachineState *machine = MACHINE(spapr);
6350ee52012SDaniel Henrique Barboza     int ret, offset;
636a324d6f1SBharata B Rao     uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
6377abf9797SAnton Blanchard     uint32_t prop_lmb_size[] = {cpu_to_be32(lmb_size >> 32),
6387abf9797SAnton Blanchard                                 cpu_to_be32(lmb_size & 0xffffffff)};
639a324d6f1SBharata B Rao     MemoryDeviceInfoList *dimms = NULL;
640a324d6f1SBharata B Rao 
641c0ce7b4aSDavid Hildenbrand     /* Don't create the node if there is no device memory. */
642c0ce7b4aSDavid Hildenbrand     if (!machine->device_memory) {
643a324d6f1SBharata B Rao         return 0;
644a324d6f1SBharata B Rao     }
645a324d6f1SBharata B Rao 
646a324d6f1SBharata B Rao     offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory");
647a324d6f1SBharata B Rao 
648a324d6f1SBharata B Rao     ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size,
649a324d6f1SBharata B Rao                     sizeof(prop_lmb_size));
650a324d6f1SBharata B Rao     if (ret < 0) {
651a324d6f1SBharata B Rao         return ret;
652a324d6f1SBharata B Rao     }
653a324d6f1SBharata B Rao 
654a324d6f1SBharata B Rao     ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff);
655a324d6f1SBharata B Rao     if (ret < 0) {
656a324d6f1SBharata B Rao         return ret;
657a324d6f1SBharata B Rao     }
658a324d6f1SBharata B Rao 
659a324d6f1SBharata B Rao     ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0);
660a324d6f1SBharata B Rao     if (ret < 0) {
661a324d6f1SBharata B Rao         return ret;
662a324d6f1SBharata B Rao     }
663a324d6f1SBharata B Rao 
664a324d6f1SBharata B Rao     /* ibm,dynamic-memory or ibm,dynamic-memory-v2 */
6652cc0e2e8SDavid Hildenbrand     dimms = qmp_memory_device_list();
666a324d6f1SBharata B Rao     if (spapr_ovec_test(spapr->ov5_cas, OV5_DRMEM_V2)) {
66791335a5eSDavid Gibson         ret = spapr_dt_dynamic_memory_v2(spapr, fdt, offset, dimms);
668a324d6f1SBharata B Rao     } else {
66991335a5eSDavid Gibson         ret = spapr_dt_dynamic_memory(spapr, fdt, offset, dimms);
670a324d6f1SBharata B Rao     }
671a324d6f1SBharata B Rao     qapi_free_MemoryDeviceInfoList(dimms);
672a324d6f1SBharata B Rao 
673a324d6f1SBharata B Rao     if (ret < 0) {
674a324d6f1SBharata B Rao         return ret;
67503d196b7SBharata B Rao     }
67603d196b7SBharata B Rao 
6770ee52012SDaniel Henrique Barboza     ret = spapr_numa_write_assoc_lookup_arrays(spapr, fdt, offset);
678a324d6f1SBharata B Rao 
67903d196b7SBharata B Rao     return ret;
68003d196b7SBharata B Rao }
68103d196b7SBharata B Rao 
spapr_dt_memory(SpaprMachineState * spapr,void * fdt)68291335a5eSDavid Gibson static int spapr_dt_memory(SpaprMachineState *spapr, void *fdt)
6836787d27bSMichael Roth {
684fa523f0dSDavid Gibson     MachineState *machine = MACHINE(spapr);
685ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
68653018216SPaolo Bonzini     hwaddr mem_start, node_size;
68753018216SPaolo Bonzini     int i, nb_nodes = machine->numa_state->num_nodes;
68853018216SPaolo Bonzini     NodeInfo *nodes = machine->numa_state->nodes;
68953018216SPaolo Bonzini 
69053018216SPaolo Bonzini     for (i = 0, mem_start = 0; i < nb_nodes; ++i) {
69153018216SPaolo Bonzini         if (!nodes[i].node_mem) {
69253018216SPaolo Bonzini             continue;
69353018216SPaolo Bonzini         }
69453018216SPaolo Bonzini         if (mem_start >= machine->ram_size) {
69553018216SPaolo Bonzini             node_size = 0;
69653018216SPaolo Bonzini         } else {
69753018216SPaolo Bonzini             node_size = nodes[i].node_mem;
69853018216SPaolo Bonzini             if (node_size > machine->ram_size - mem_start) {
69953018216SPaolo Bonzini                 node_size = machine->ram_size - mem_start;
70053018216SPaolo Bonzini             }
70153018216SPaolo Bonzini         }
70253018216SPaolo Bonzini         if (!mem_start) {
70353018216SPaolo Bonzini             /* spapr_machine_init() checks for rma_size <= node0_size
70453018216SPaolo Bonzini              * already */
705f1aa45ffSDaniel Henrique Barboza             spapr_dt_memory_node(spapr, fdt, i, 0, spapr->rma_size);
70653018216SPaolo Bonzini             mem_start += spapr->rma_size;
70753018216SPaolo Bonzini             node_size -= spapr->rma_size;
70853018216SPaolo Bonzini         }
70953018216SPaolo Bonzini         for ( ; node_size; ) {
71053018216SPaolo Bonzini             hwaddr sizetmp = pow2floor(node_size);
71153018216SPaolo Bonzini 
71253018216SPaolo Bonzini             /* mem_start != 0 here */
71353018216SPaolo Bonzini             if (ctzl(mem_start) < ctzl(sizetmp)) {
71453018216SPaolo Bonzini                 sizetmp = 1ULL << ctzl(mem_start);
71553018216SPaolo Bonzini             }
71653018216SPaolo Bonzini 
717f1aa45ffSDaniel Henrique Barboza             spapr_dt_memory_node(spapr, fdt, i, mem_start, sizetmp);
71853018216SPaolo Bonzini             node_size -= sizetmp;
71953018216SPaolo Bonzini             mem_start += sizetmp;
72053018216SPaolo Bonzini         }
72153018216SPaolo Bonzini     }
72253018216SPaolo Bonzini 
7236787d27bSMichael Roth     /* Generate ibm,dynamic-reconfiguration-memory node if required */
724fa523f0dSDavid Gibson     if (spapr_ovec_test(spapr->ov5_cas, OV5_DRCONF_MEMORY)) {
725fa523f0dSDavid Gibson         int ret;
726fa523f0dSDavid Gibson 
7276787d27bSMichael Roth         g_assert(smc->dr_lmb_enabled);
72891335a5eSDavid Gibson         ret = spapr_dt_dynamic_reconfiguration_memory(spapr, fdt);
729417ece33SMichael Roth         if (ret) {
7309b6c1da5SDaniel Henrique Barboza             return ret;
731417ece33SMichael Roth         }
7326787d27bSMichael Roth     }
7336787d27bSMichael Roth 
73453018216SPaolo Bonzini     return 0;
73553018216SPaolo Bonzini }
73653018216SPaolo Bonzini 
spapr_dt_cpu(CPUState * cs,void * fdt,int offset,SpaprMachineState * spapr)73791335a5eSDavid Gibson static void spapr_dt_cpu(CPUState *cs, void *fdt, int offset,
73853018216SPaolo Bonzini                          SpaprMachineState *spapr)
73953018216SPaolo Bonzini {
74053018216SPaolo Bonzini     MachineState *ms = MACHINE(spapr);
74153018216SPaolo Bonzini     PowerPCCPU *cpu = POWERPC_CPU(cs);
74253018216SPaolo Bonzini     CPUPPCState *env = &cpu->env;
74353018216SPaolo Bonzini     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
74453018216SPaolo Bonzini     int index = spapr_get_vcpu_id(cpu);
74553018216SPaolo Bonzini     uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
74653018216SPaolo Bonzini                        0xffffffff, 0xffffffff};
74753018216SPaolo Bonzini     uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq()
74853018216SPaolo Bonzini         : SPAPR_TIMEBASE_FREQ;
74953018216SPaolo Bonzini     uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000;
75053018216SPaolo Bonzini     uint32_t page_sizes_prop[64];
75153018216SPaolo Bonzini     size_t page_sizes_prop_size;
75253018216SPaolo Bonzini     unsigned int smp_threads = ms->smp.threads;
75353018216SPaolo Bonzini     uint32_t vcpus_per_socket = smp_threads * ms->smp.cores;
75453018216SPaolo Bonzini     uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
75553018216SPaolo Bonzini     int compat_smt = MIN(smp_threads, ppc_compat_max_vthreads(cpu));
75653018216SPaolo Bonzini     SpaprDrc *drc;
75753018216SPaolo Bonzini     int drc_index;
75853018216SPaolo Bonzini     uint32_t radix_AP_encodings[PPC_PAGE_SIZES_MAX_SZ];
75953018216SPaolo Bonzini     int i;
76053018216SPaolo Bonzini 
76153018216SPaolo Bonzini     drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index);
76253018216SPaolo Bonzini     if (drc) {
76353018216SPaolo Bonzini         drc_index = spapr_drc_index(drc);
76453018216SPaolo Bonzini         _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index)));
7652a6593cbSAlexey Kardashevskiy     }
7662a6593cbSAlexey Kardashevskiy 
7672a6593cbSAlexey Kardashevskiy     _FDT((fdt_setprop_cell(fdt, offset, "reg", index)));
7682a6593cbSAlexey Kardashevskiy     _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
7692a6593cbSAlexey Kardashevskiy 
7702a6593cbSAlexey Kardashevskiy     _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
7712a6593cbSAlexey Kardashevskiy     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
7722a6593cbSAlexey Kardashevskiy                            env->dcache_line_size)));
7732a6593cbSAlexey Kardashevskiy     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
7742a6593cbSAlexey Kardashevskiy                            env->dcache_line_size)));
7752a6593cbSAlexey Kardashevskiy     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
7762a6593cbSAlexey Kardashevskiy                            env->icache_line_size)));
7772a6593cbSAlexey Kardashevskiy     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
7782a6593cbSAlexey Kardashevskiy                            env->icache_line_size)));
7792a6593cbSAlexey Kardashevskiy 
7802a6593cbSAlexey Kardashevskiy     if (pcc->l1_dcache_size) {
7812a6593cbSAlexey Kardashevskiy         _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
7822a6593cbSAlexey Kardashevskiy                                pcc->l1_dcache_size)));
7832a6593cbSAlexey Kardashevskiy     } else {
7842a6593cbSAlexey Kardashevskiy         warn_report("Unknown L1 dcache size for cpu");
7852a6593cbSAlexey Kardashevskiy     }
7862a6593cbSAlexey Kardashevskiy     if (pcc->l1_icache_size) {
7872a6593cbSAlexey Kardashevskiy         _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
7882a6593cbSAlexey Kardashevskiy                                pcc->l1_icache_size)));
7892a6593cbSAlexey Kardashevskiy     } else {
7902a6593cbSAlexey Kardashevskiy         warn_report("Unknown L1 icache size for cpu");
7912a6593cbSAlexey Kardashevskiy     }
7922a6593cbSAlexey Kardashevskiy 
7932a6593cbSAlexey Kardashevskiy     _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
7942a6593cbSAlexey Kardashevskiy     _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
7952a6593cbSAlexey Kardashevskiy     _FDT((fdt_setprop_cell(fdt, offset, "slb-size", cpu->hash64_opts->slb_size)));
7962a6593cbSAlexey Kardashevskiy     _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", cpu->hash64_opts->slb_size)));
7972a6593cbSAlexey Kardashevskiy     _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
7982a6593cbSAlexey Kardashevskiy     _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
7992a6593cbSAlexey Kardashevskiy 
80003282a3aSLucas Mateus Castro (alqotel)     if (ppc_has_spr(cpu, SPR_PURR)) {
80153018216SPaolo Bonzini         _FDT((fdt_setprop_cell(fdt, offset, "ibm,purr", 1)));
80253018216SPaolo Bonzini     }
80303282a3aSLucas Mateus Castro (alqotel)     if (ppc_has_spr(cpu, SPR_PURR)) {
80453018216SPaolo Bonzini         _FDT((fdt_setprop_cell(fdt, offset, "ibm,spurr", 1)));
80553018216SPaolo Bonzini     }
80653018216SPaolo Bonzini 
80753018216SPaolo Bonzini     if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
80853018216SPaolo Bonzini         _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
80953018216SPaolo Bonzini                           segs, sizeof(segs))));
81053018216SPaolo Bonzini     }
81153018216SPaolo Bonzini 
81253018216SPaolo Bonzini     /* Advertise VSX (vector extensions) if available
81353018216SPaolo Bonzini      *   1               == VMX / Altivec available
81453018216SPaolo Bonzini      *   2               == VSX available
81553018216SPaolo Bonzini      *
81653018216SPaolo Bonzini      * Only CPUs for which we create core types in spapr_cpu_core.c
81753018216SPaolo Bonzini      * are possible, and all of those have VMX */
8182460e1d7SCédric Le Goater     if (env->insns_flags & PPC_ALTIVEC) {
81953018216SPaolo Bonzini         if (spapr_get_cap(spapr, SPAPR_CAP_VSX) != 0) {
82053018216SPaolo Bonzini             _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2)));
82153018216SPaolo Bonzini         } else {
82253018216SPaolo Bonzini             _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1)));
82353018216SPaolo Bonzini         }
8242460e1d7SCédric Le Goater     }
82553018216SPaolo Bonzini 
82653018216SPaolo Bonzini     /* Advertise DFP (Decimal Floating Point) if available
82728e02042SDavid Gibson      *   0 / no property == no DFP
82853018216SPaolo Bonzini      *   1               == DFP available */
829fb164994SDavid Gibson     if (spapr_get_cap(spapr, SPAPR_CAP_DFP) != 0) {
8307db8a127SAlexey Kardashevskiy         _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
8317db8a127SAlexey Kardashevskiy     }
8327db8a127SAlexey Kardashevskiy 
8337db8a127SAlexey Kardashevskiy     page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
83453018216SPaolo Bonzini                                                       sizeof(page_sizes_prop));
8357db8a127SAlexey Kardashevskiy     if (page_sizes_prop_size) {
8367db8a127SAlexey Kardashevskiy         _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
8377db8a127SAlexey Kardashevskiy                           page_sizes_prop, page_sizes_prop_size)));
838fb164994SDavid Gibson     }
8397db8a127SAlexey Kardashevskiy 
84091335a5eSDavid Gibson     spapr_dt_pa_features(spapr, cpu, fdt, offset);
84153018216SPaolo Bonzini 
84295912ce1SNicholas Piggin     spapr_dt_pi_features(spapr, cpu, fdt, offset);
84395912ce1SNicholas Piggin 
8447db8a127SAlexey Kardashevskiy     _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id",
8457db8a127SAlexey Kardashevskiy                            cs->cpu_index / vcpus_per_socket)));
8467db8a127SAlexey Kardashevskiy 
84753018216SPaolo Bonzini     _FDT((fdt_setprop(fdt, offset, "ibm,pft-size",
848fb164994SDavid Gibson                       pft_size_prop, sizeof(pft_size_prop))));
8495fe269b1SPaul Mackerras 
8505fe269b1SPaul Mackerras     if (ms->numa_state->num_nodes > 1) {
8518f86a408SDaniel Henrique Barboza         _FDT(spapr_numa_fixup_cpu_dt(spapr, fdt, offset, cpu));
8525fe269b1SPaul Mackerras     }
8535fe269b1SPaul Mackerras 
8547db8a127SAlexey Kardashevskiy     _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt));
8557db8a127SAlexey Kardashevskiy 
8567db8a127SAlexey Kardashevskiy     if (pcc->radix_page_info) {
8577db8a127SAlexey Kardashevskiy         for (i = 0; i < pcc->radix_page_info->count; i++) {
8587db8a127SAlexey Kardashevskiy             radix_AP_encodings[i] =
8597db8a127SAlexey Kardashevskiy                 cpu_to_be32(pcc->radix_page_info->entries[i]);
8606010818cSAlexey Kardashevskiy         }
8616010818cSAlexey Kardashevskiy         _FDT((fdt_setprop(fdt, offset, "ibm,processor-radix-AP-encodings",
8626010818cSAlexey Kardashevskiy                           radix_AP_encodings,
8636010818cSAlexey Kardashevskiy                           pcc->radix_page_info->count *
8646010818cSAlexey Kardashevskiy                           sizeof(radix_AP_encodings[0]))));
8656010818cSAlexey Kardashevskiy     }
8666010818cSAlexey Kardashevskiy 
8676010818cSAlexey Kardashevskiy     /*
8686010818cSAlexey Kardashevskiy      * We set this property to let the guest know that it can use the large
8696010818cSAlexey Kardashevskiy      * decrementer and its width in bits.
8706010818cSAlexey Kardashevskiy      */
8716010818cSAlexey Kardashevskiy     if (spapr_get_cap(spapr, SPAPR_CAP_LARGE_DECREMENTER) != SPAPR_CAP_OFF)
87253018216SPaolo Bonzini         _FDT((fdt_setprop_u32(fdt, offset, "ibm,dec-bits",
87353018216SPaolo Bonzini                               pcc->lrg_decr_bits)));
87453018216SPaolo Bonzini }
87553018216SPaolo Bonzini 
spapr_dt_one_cpu(void * fdt,SpaprMachineState * spapr,CPUState * cs,int cpus_offset)876bd87a59fSCédric Le Goater static void spapr_dt_one_cpu(void *fdt, SpaprMachineState *spapr, CPUState *cs,
877bd87a59fSCédric Le Goater                              int cpus_offset)
878bd87a59fSCédric Le Goater {
879bd87a59fSCédric Le Goater     PowerPCCPU *cpu = POWERPC_CPU(cs);
880bd87a59fSCédric Le Goater     int index = spapr_get_vcpu_id(cpu);
881bd87a59fSCédric Le Goater     DeviceClass *dc = DEVICE_GET_CLASS(cs);
882bd87a59fSCédric Le Goater     g_autofree char *nodename = NULL;
883bd87a59fSCédric Le Goater     int offset;
884bd87a59fSCédric Le Goater 
885bd87a59fSCédric Le Goater     if (!spapr_is_thread0_in_vcore(spapr, cpu)) {
886bd87a59fSCédric Le Goater         return;
887bd87a59fSCédric Le Goater     }
888bd87a59fSCédric Le Goater 
889bd87a59fSCédric Le Goater     nodename = g_strdup_printf("%s@%x", dc->fw_name, index);
890bd87a59fSCédric Le Goater     offset = fdt_add_subnode(fdt, cpus_offset, nodename);
891bd87a59fSCédric Le Goater     _FDT(offset);
892bd87a59fSCédric Le Goater     spapr_dt_cpu(cs, fdt, offset, spapr);
893bd87a59fSCédric Le Goater }
894bd87a59fSCédric Le Goater 
895bd87a59fSCédric Le Goater 
spapr_dt_cpus(void * fdt,SpaprMachineState * spapr)89691335a5eSDavid Gibson static void spapr_dt_cpus(void *fdt, SpaprMachineState *spapr)
89753018216SPaolo Bonzini {
89853018216SPaolo Bonzini     CPUState **rev;
89953018216SPaolo Bonzini     CPUState *cs;
90053018216SPaolo Bonzini     int n_cpus;
90153018216SPaolo Bonzini     int cpus_offset;
90253018216SPaolo Bonzini     int i;
90353018216SPaolo Bonzini 
90453018216SPaolo Bonzini     cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
90553018216SPaolo Bonzini     _FDT(cpus_offset);
90653018216SPaolo Bonzini     _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
90753018216SPaolo Bonzini     _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
90853018216SPaolo Bonzini 
90953018216SPaolo Bonzini     /*
91053018216SPaolo Bonzini      * We walk the CPUs in reverse order to ensure that CPU DT nodes
91153018216SPaolo Bonzini      * created by fdt_add_subnode() end up in the right order in FDT
91253018216SPaolo Bonzini      * for the guest kernel the enumerate the CPUs correctly.
91353018216SPaolo Bonzini      *
91453018216SPaolo Bonzini      * The CPU list cannot be traversed in reverse order, so we need
91553018216SPaolo Bonzini      * to do extra work.
91653018216SPaolo Bonzini      */
91753018216SPaolo Bonzini     n_cpus = 0;
91853018216SPaolo Bonzini     rev = NULL;
91953018216SPaolo Bonzini     CPU_FOREACH(cs) {
92053018216SPaolo Bonzini         rev = g_renew(CPUState *, rev, n_cpus + 1);
92153018216SPaolo Bonzini         rev[n_cpus++] = cs;
92253018216SPaolo Bonzini     }
92353018216SPaolo Bonzini 
92453018216SPaolo Bonzini     for (i = n_cpus - 1; i >= 0; i--) {
925bd87a59fSCédric Le Goater         spapr_dt_one_cpu(fdt, spapr, rev[i], cpus_offset);
9260da6f3feSBharata B Rao     }
9270da6f3feSBharata B Rao 
9280da6f3feSBharata B Rao     g_free(rev);
9290da6f3feSBharata B Rao }
93022419c2aSDavid Gibson 
spapr_dt_rng(void * fdt)93191335a5eSDavid Gibson static int spapr_dt_rng(void *fdt)
9320da6f3feSBharata B Rao {
9330da6f3feSBharata B Rao     int node;
9340da6f3feSBharata B Rao     int ret;
9350da6f3feSBharata B Rao 
9360da6f3feSBharata B Rao     node = qemu_fdt_add_subnode(fdt, "/ibm,platform-facilities");
9370da6f3feSBharata B Rao     if (node <= 0) {
9380da6f3feSBharata B Rao         return -1;
9390da6f3feSBharata B Rao     }
9400da6f3feSBharata B Rao     ret = fdt_setprop_string(fdt, node, "device_type",
9410da6f3feSBharata B Rao                              "ibm,platform-facilities");
9420da6f3feSBharata B Rao     ret |= fdt_setprop_cell(fdt, node, "#address-cells", 0x1);
9430da6f3feSBharata B Rao     ret |= fdt_setprop_cell(fdt, node, "#size-cells", 0x0);
9440da6f3feSBharata B Rao 
9450da6f3feSBharata B Rao     node = fdt_add_subnode(fdt, node, "ibm,random-v1");
9460da6f3feSBharata B Rao     if (node <= 0) {
9470da6f3feSBharata B Rao         return -1;
9480da6f3feSBharata B Rao     }
9490da6f3feSBharata B Rao     ret |= fdt_setprop_string(fdt, node, "compatible", "ibm,random");
9500da6f3feSBharata B Rao 
9510da6f3feSBharata B Rao     return ret ? -1 : 0;
9520da6f3feSBharata B Rao }
9530da6f3feSBharata B Rao 
spapr_dt_rtas(SpaprMachineState * spapr,void * fdt)954ce2918cbSDavid Gibson static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt)
9553f5dabceSDavid Gibson {
956fe6b6346SLike Xu     MachineState *ms = MACHINE(spapr);
9573f5dabceSDavid Gibson     int rtas;
9583f5dabceSDavid Gibson     GString *hypertas = g_string_sized_new(256);
9593f5dabceSDavid Gibson     GString *qemu_hypertas = g_string_sized_new(256);
9603f5dabceSDavid Gibson     uint32_t lrdr_capacity[] = {
961c0ce7b4aSDavid Hildenbrand         0,
962c0ce7b4aSDavid Hildenbrand         0,
9637abf9797SAnton Blanchard         cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE >> 32),
9647abf9797SAnton Blanchard         cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE & 0xffffffff),
965fe6b6346SLike Xu         cpu_to_be32(ms->smp.max_cpus / ms->smp.threads),
9663f5dabceSDavid Gibson     };
9673f5dabceSDavid Gibson 
968c0ce7b4aSDavid Hildenbrand     /* Do we have device memory? */
969c0ce7b4aSDavid Hildenbrand     if (MACHINE(spapr)->device_memory) {
970c0ce7b4aSDavid Hildenbrand         uint64_t max_device_addr = MACHINE(spapr)->device_memory->base +
971c0ce7b4aSDavid Hildenbrand             memory_region_size(&MACHINE(spapr)->device_memory->mr);
972c0ce7b4aSDavid Hildenbrand 
973c0ce7b4aSDavid Hildenbrand         lrdr_capacity[0] = cpu_to_be32(max_device_addr >> 32);
974c0ce7b4aSDavid Hildenbrand         lrdr_capacity[1] = cpu_to_be32(max_device_addr & 0xffffffff);
975c0ce7b4aSDavid Hildenbrand     }
976c0ce7b4aSDavid Hildenbrand 
9773f5dabceSDavid Gibson     _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas"));
9783f5dabceSDavid Gibson 
9793f5dabceSDavid Gibson     /* hypertas */
9803f5dabceSDavid Gibson     add_str(hypertas, "hcall-pft");
9813f5dabceSDavid Gibson     add_str(hypertas, "hcall-term");
9823f5dabceSDavid Gibson     add_str(hypertas, "hcall-dabr");
9833f5dabceSDavid Gibson     add_str(hypertas, "hcall-interrupt");
9843f5dabceSDavid Gibson     add_str(hypertas, "hcall-tce");
9853f5dabceSDavid Gibson     add_str(hypertas, "hcall-vio");
9863f5dabceSDavid Gibson     add_str(hypertas, "hcall-splpar");
98710741314SNicholas Piggin     add_str(hypertas, "hcall-join");
9883f5dabceSDavid Gibson     add_str(hypertas, "hcall-bulk");
9893f5dabceSDavid Gibson     add_str(hypertas, "hcall-set-mode");
9903f5dabceSDavid Gibson     add_str(hypertas, "hcall-sprg0");
9913f5dabceSDavid Gibson     add_str(hypertas, "hcall-copy");
9923f5dabceSDavid Gibson     add_str(hypertas, "hcall-debug");
993c24ba3d0SLaurent Vivier     add_str(hypertas, "hcall-vphn");
99482123b75SBharata B Rao     if (spapr_get_cap(spapr, SPAPR_CAP_RPT_INVALIDATE) == SPAPR_CAP_ON) {
99582123b75SBharata B Rao         add_str(hypertas, "hcall-rpt-invalidate");
99682123b75SBharata B Rao     }
99782123b75SBharata B Rao 
9983f5dabceSDavid Gibson     add_str(qemu_hypertas, "hcall-memop1");
9993f5dabceSDavid Gibson 
10003f5dabceSDavid Gibson     if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
10013f5dabceSDavid Gibson         add_str(hypertas, "hcall-multi-tce");
10023f5dabceSDavid Gibson     }
100330f4b05bSDavid Gibson 
100430f4b05bSDavid Gibson     if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) {
100530f4b05bSDavid Gibson         add_str(hypertas, "hcall-hpt-resize");
100630f4b05bSDavid Gibson     }
100730f4b05bSDavid Gibson 
100881b205ceSAlexey Kardashevskiy     add_str(hypertas, "hcall-watchdog");
100981b205ceSAlexey Kardashevskiy 
10103f5dabceSDavid Gibson     _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions",
10113f5dabceSDavid Gibson                      hypertas->str, hypertas->len));
10123f5dabceSDavid Gibson     g_string_free(hypertas, TRUE);
10133f5dabceSDavid Gibson     _FDT(fdt_setprop(fdt, rtas, "qemu,hypertas-functions",
10143f5dabceSDavid Gibson                      qemu_hypertas->str, qemu_hypertas->len));
10153f5dabceSDavid Gibson     g_string_free(qemu_hypertas, TRUE);
10163f5dabceSDavid Gibson 
10171eee9950SDaniel Henrique Barboza     spapr_numa_write_rtas_dt(spapr, fdt, rtas);
1018da9f80fbSSerhii Popovych 
10190e236d34SNicholas Piggin     /*
10200e236d34SNicholas Piggin      * FWNMI reserves RTAS_ERROR_LOG_MAX for the machine check error log,
10210e236d34SNicholas Piggin      * and 16 bytes per CPU for system reset error log plus an extra 8 bytes.
10220e236d34SNicholas Piggin      *
10230e236d34SNicholas Piggin      * The system reset requirements are driven by existing Linux and PowerVM
10240e236d34SNicholas Piggin      * implementation which (contrary to PAPR) saves r3 in the error log
10250e236d34SNicholas Piggin      * structure like machine check, so Linux expects to find the saved r3
10260e236d34SNicholas Piggin      * value at the address in r3 upon FWNMI-enabled sreset interrupt (and
10270e236d34SNicholas Piggin      * does not look at the error value).
10280e236d34SNicholas Piggin      *
10290e236d34SNicholas Piggin      * System reset interrupts are not subject to interlock like machine
10300e236d34SNicholas Piggin      * check, so this memory area could be corrupted if the sreset is
10310e236d34SNicholas Piggin      * interrupted by a machine check (or vice versa) if it was shared. To
10320e236d34SNicholas Piggin      * prevent this, system reset uses per-CPU areas for the sreset save
10330e236d34SNicholas Piggin      * area. A system reset that interrupts a system reset handler could
10340e236d34SNicholas Piggin      * still overwrite this area, but Linux doesn't try to recover in that
10350e236d34SNicholas Piggin      * case anyway.
10360e236d34SNicholas Piggin      *
10370e236d34SNicholas Piggin      * The extra 8 bytes is required because Linux's FWNMI error log check
10380e236d34SNicholas Piggin      * is off-by-one.
10397381c5d1SAlexey Kardashevskiy      *
10407381c5d1SAlexey Kardashevskiy      * RTAS_MIN_SIZE is required for the RTAS blob itself.
10410e236d34SNicholas Piggin      */
10427381c5d1SAlexey Kardashevskiy     _FDT(fdt_setprop_cell(fdt, rtas, "rtas-size", RTAS_MIN_SIZE +
10437381c5d1SAlexey Kardashevskiy                           RTAS_ERROR_LOG_MAX +
10447381c5d1SAlexey Kardashevskiy                           ms->smp.max_cpus * sizeof(uint64_t) * 2 +
10457381c5d1SAlexey Kardashevskiy                           sizeof(uint64_t)));
10463f5dabceSDavid Gibson     _FDT(fdt_setprop_cell(fdt, rtas, "rtas-error-log-max",
10473f5dabceSDavid Gibson                           RTAS_ERROR_LOG_MAX));
10483f5dabceSDavid Gibson     _FDT(fdt_setprop_cell(fdt, rtas, "rtas-event-scan-rate",
10493f5dabceSDavid Gibson                           RTAS_EVENT_SCAN_RATE));
10503f5dabceSDavid Gibson 
10514f441474SDavid Gibson     g_assert(msi_nonbroken);
10523f5dabceSDavid Gibson     _FDT(fdt_setprop(fdt, rtas, "ibm,change-msix-capable", NULL, 0));
10533f5dabceSDavid Gibson 
10543f5dabceSDavid Gibson     /*
10553f5dabceSDavid Gibson      * According to PAPR, rtas ibm,os-term does not guarantee a return
10563f5dabceSDavid Gibson      * back to the guest cpu.
10573f5dabceSDavid Gibson      *
10583f5dabceSDavid Gibson      * While an additional ibm,extended-os-term property indicates
10593f5dabceSDavid Gibson      * that rtas call return will always occur. Set this property.
10603f5dabceSDavid Gibson      */
10613f5dabceSDavid Gibson     _FDT(fdt_setprop(fdt, rtas, "ibm,extended-os-term", NULL, 0));
10623f5dabceSDavid Gibson 
10633f5dabceSDavid Gibson     _FDT(fdt_setprop(fdt, rtas, "ibm,lrdr-capacity",
10643f5dabceSDavid Gibson                      lrdr_capacity, sizeof(lrdr_capacity)));
10653f5dabceSDavid Gibson 
10663f5dabceSDavid Gibson     spapr_dt_rtas_tokens(fdt, rtas);
10673f5dabceSDavid Gibson }
10683f5dabceSDavid Gibson 
1069db592b5bSCédric Le Goater /*
1070db592b5bSCédric Le Goater  * Prepare ibm,arch-vec-5-platform-support, which indicates the MMU
1071db592b5bSCédric Le Goater  * and the XIVE features that the guest may request and thus the valid
1072db592b5bSCédric Le Goater  * values for bytes 23..26 of option vector 5:
1073db592b5bSCédric Le Goater  */
spapr_dt_ov5_platform_support(SpaprMachineState * spapr,void * fdt,int chosen)1074ce2918cbSDavid Gibson static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt,
1075db592b5bSCédric Le Goater                                           int chosen)
10769fb4541fSSam Bobroff {
1077545d6e2bSSuraj Jitindar Singh     PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu);
1078545d6e2bSSuraj Jitindar Singh 
1079f2b14e3aSCédric Le Goater     char val[2 * 4] = {
1080ca62823bSDavid Gibson         23, 0x00, /* XICS / XIVE mode */
10819fb4541fSSam Bobroff         24, 0x00, /* Hash/Radix, filled in below. */
10829fb4541fSSam Bobroff         25, 0x00, /* Hash options: Segment Tables == no, GTSE == no. */
10839fb4541fSSam Bobroff         26, 0x40, /* Radix options: GTSE == yes. */
10849fb4541fSSam Bobroff     };
10859fb4541fSSam Bobroff 
1086ca62823bSDavid Gibson     if (spapr->irq->xics && spapr->irq->xive) {
1087ca62823bSDavid Gibson         val[1] = SPAPR_OV5_XIVE_BOTH;
1088ca62823bSDavid Gibson     } else if (spapr->irq->xive) {
1089ca62823bSDavid Gibson         val[1] = SPAPR_OV5_XIVE_EXPLOIT;
1090ca62823bSDavid Gibson     } else {
1091ca62823bSDavid Gibson         assert(spapr->irq->xics);
1092ca62823bSDavid Gibson         val[1] = SPAPR_OV5_XIVE_LEGACY;
1093ca62823bSDavid Gibson     }
1094ca62823bSDavid Gibson 
10957abd43baSSuraj Jitindar Singh     if (!ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0,
10967abd43baSSuraj Jitindar Singh                           first_ppc_cpu->compat_pvr)) {
1097db592b5bSCédric Le Goater         /*
1098db592b5bSCédric Le Goater          * If we're in a pre POWER9 compat mode then the guest should
1099db592b5bSCédric Le Goater          * do hash and use the legacy interrupt mode
1100db592b5bSCédric Le Goater          */
1101ca62823bSDavid Gibson         val[1] = SPAPR_OV5_XIVE_LEGACY; /* XICS */
11027abd43baSSuraj Jitindar Singh         val[3] = 0x00; /* Hash */
1103ab5add4cSFabiano Rosas         spapr_check_mmu_mode(false);
11047abd43baSSuraj Jitindar Singh     } else if (kvm_enabled()) {
11059fb4541fSSam Bobroff         if (kvmppc_has_cap_mmu_radix() && kvmppc_has_cap_mmu_hash_v3()) {
1106f2b14e3aSCédric Le Goater             val[3] = 0x80; /* OV5_MMU_BOTH */
11079fb4541fSSam Bobroff         } else if (kvmppc_has_cap_mmu_radix()) {
1108f2b14e3aSCédric Le Goater             val[3] = 0x40; /* OV5_MMU_RADIX_300 */
11099fb4541fSSam Bobroff         } else {
1110f2b14e3aSCédric Le Goater             val[3] = 0x00; /* Hash */
11119fb4541fSSam Bobroff         }
11129fb4541fSSam Bobroff     } else {
11137abd43baSSuraj Jitindar Singh         /* V3 MMU supports both hash and radix in tcg (with dynamic switching) */
1114f2b14e3aSCédric Le Goater         val[3] = 0xC0;
1115545d6e2bSSuraj Jitindar Singh     }
11169fb4541fSSam Bobroff     _FDT(fdt_setprop(fdt, chosen, "ibm,arch-vec-5-platform-support",
11179fb4541fSSam Bobroff                      val, sizeof(val)));
11189fb4541fSSam Bobroff }
11199fb4541fSSam Bobroff 
spapr_dt_chosen(SpaprMachineState * spapr,void * fdt,bool reset)11201e0e1108SDavid Gibson static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt, bool reset)
11217c866c6aSDavid Gibson {
11227c866c6aSDavid Gibson     MachineState *machine = MACHINE(spapr);
11236c3829a2SAlexey Kardashevskiy     SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
11247c866c6aSDavid Gibson     int chosen;
11251e0e1108SDavid Gibson 
11261e0e1108SDavid Gibson     _FDT(chosen = fdt_add_subnode(fdt, 0, "chosen"));
11271e0e1108SDavid Gibson 
11281e0e1108SDavid Gibson     if (reset) {
11293bf0844fSGreg Kurz         const char *boot_device = spapr->boot_device;
1130aebb9b9cSDaniel Henrique Barboza         g_autofree char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus);
11317c866c6aSDavid Gibson         size_t cb = 0;
1132aebb9b9cSDaniel Henrique Barboza         g_autofree char *bootlist = get_boot_devices_list(&cb);
11337c866c6aSDavid Gibson 
11345ced7895SAlexey Kardashevskiy         if (machine->kernel_cmdline && machine->kernel_cmdline[0]) {
11355ced7895SAlexey Kardashevskiy             _FDT(fdt_setprop_string(fdt, chosen, "bootargs",
11365ced7895SAlexey Kardashevskiy                                     machine->kernel_cmdline));
11375ced7895SAlexey Kardashevskiy         }
11381e0e1108SDavid Gibson 
11395ced7895SAlexey Kardashevskiy         if (spapr->initrd_size) {
11407c866c6aSDavid Gibson             _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-start",
11417c866c6aSDavid Gibson                                   spapr->initrd_base));
11427c866c6aSDavid Gibson             _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-end",
11437c866c6aSDavid Gibson                                   spapr->initrd_base + spapr->initrd_size));
11445ced7895SAlexey Kardashevskiy         }
11457c866c6aSDavid Gibson 
11467c866c6aSDavid Gibson         if (spapr->kernel_size) {
114787262806SAlexey Kardashevskiy             uint64_t kprop[2] = { cpu_to_be64(spapr->kernel_addr),
11487c866c6aSDavid Gibson                                   cpu_to_be64(spapr->kernel_size) };
11497c866c6aSDavid Gibson 
11507c866c6aSDavid Gibson             _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel",
11517c866c6aSDavid Gibson                          &kprop, sizeof(kprop)));
11527c866c6aSDavid Gibson             if (spapr->kernel_le) {
11537c866c6aSDavid Gibson                 _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel-le", NULL, 0));
11547c866c6aSDavid Gibson             }
11557c866c6aSDavid Gibson         }
115697ec4d21SPaolo Bonzini         if (machine->boot_config.has_menu && machine->boot_config.menu) {
115797ec4d21SPaolo Bonzini             _FDT((fdt_setprop_cell(fdt, chosen, "qemu,boot-menu", true)));
11587c866c6aSDavid Gibson         }
11597c866c6aSDavid Gibson         _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-width", graphic_width));
11607c866c6aSDavid Gibson         _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-height", graphic_height));
11617c866c6aSDavid Gibson         _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-depth", graphic_depth));
11627c866c6aSDavid Gibson 
11637c866c6aSDavid Gibson         if (cb && bootlist) {
11647c866c6aSDavid Gibson             int i;
11657c866c6aSDavid Gibson 
11667c866c6aSDavid Gibson             for (i = 0; i < cb; i++) {
11677c866c6aSDavid Gibson                 if (bootlist[i] == '\n') {
11687c866c6aSDavid Gibson                     bootlist[i] = ' ';
11697c866c6aSDavid Gibson                 }
11707c866c6aSDavid Gibson             }
11717c866c6aSDavid Gibson             _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-list", bootlist));
11727c866c6aSDavid Gibson         }
11737c866c6aSDavid Gibson 
11747c866c6aSDavid Gibson         if (boot_device && strlen(boot_device)) {
11757c866c6aSDavid Gibson             _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-device", boot_device));
11767c866c6aSDavid Gibson         }
11777c866c6aSDavid Gibson 
1178f73eb948SPaolo Bonzini         if (spapr->want_stdout_path && stdout_path) {
117990ee4e01SNikunj A Dadhania             /*
11801e0e1108SDavid Gibson              * "linux,stdout-path" and "stdout" properties are
11811e0e1108SDavid Gibson              * deprecated by linux kernel. New platforms should only
11821e0e1108SDavid Gibson              * use the "stdout-path" property. Set the new property
11831e0e1108SDavid Gibson              * and continue using older property to remain compatible
11841e0e1108SDavid Gibson              * with the existing firmware.
118590ee4e01SNikunj A Dadhania              */
11867c866c6aSDavid Gibson             _FDT(fdt_setprop_string(fdt, chosen, "linux,stdout-path", stdout_path));
118790ee4e01SNikunj A Dadhania             _FDT(fdt_setprop_string(fdt, chosen, "stdout-path", stdout_path));
11887c866c6aSDavid Gibson         }
11897c866c6aSDavid Gibson 
11901e0e1108SDavid Gibson         /*
11911e0e1108SDavid Gibson          * We can deal with BAR reallocation just fine, advertise it
11921e0e1108SDavid Gibson          * to the guest
11931e0e1108SDavid Gibson          */
11946c3829a2SAlexey Kardashevskiy         if (smc->linux_pci_probe) {
11956c3829a2SAlexey Kardashevskiy             _FDT(fdt_setprop_cell(fdt, chosen, "linux,pci-probe-only", 0));
11966c3829a2SAlexey Kardashevskiy         }
11976c3829a2SAlexey Kardashevskiy 
1198db592b5bSCédric Le Goater         spapr_dt_ov5_platform_support(spapr, fdt, chosen);
11997c866c6aSDavid Gibson     }
12007c866c6aSDavid Gibson 
1201b27fcb28SNicholas Piggin     _FDT(fdt_setprop(fdt, chosen, "rng-seed", spapr->fdt_rng_seed, 32));
1202c4b07531SJason A. Donenfeld 
120391335a5eSDavid Gibson     _FDT(spapr_dt_ovec(fdt, chosen, spapr->ov5_cas, "ibm,architecture-vec-5"));
12041e0e1108SDavid Gibson }
12051e0e1108SDavid Gibson 
spapr_dt_hypervisor(SpaprMachineState * spapr,void * fdt)1206ce2918cbSDavid Gibson static void spapr_dt_hypervisor(SpaprMachineState *spapr, void *fdt)
1207fca5f2dcSDavid Gibson {
1208fca5f2dcSDavid Gibson     /* The /hypervisor node isn't in PAPR - this is a hack to allow PR
1209fca5f2dcSDavid Gibson      * KVM to work under pHyp with some guest co-operation */
1210fca5f2dcSDavid Gibson     int hypervisor;
1211fca5f2dcSDavid Gibson     uint8_t hypercall[16];
1212fca5f2dcSDavid Gibson 
1213fca5f2dcSDavid Gibson     _FDT(hypervisor = fdt_add_subnode(fdt, 0, "hypervisor"));
1214fca5f2dcSDavid Gibson     /* indicate KVM hypercall interface */
1215fca5f2dcSDavid Gibson     _FDT(fdt_setprop_string(fdt, hypervisor, "compatible", "linux,kvm"));
1216fca5f2dcSDavid Gibson     if (kvmppc_has_cap_fixup_hcalls()) {
1217fca5f2dcSDavid Gibson         /*
1218fca5f2dcSDavid Gibson          * Older KVM versions with older guest kernels were broken
1219fca5f2dcSDavid Gibson          * with the magic page, don't allow the guest to map it.
1220fca5f2dcSDavid Gibson          */
1221b77af26eSRichard Henderson         if (!kvmppc_get_hypercall(cpu_env(first_cpu), hypercall,
1222fca5f2dcSDavid Gibson                                   sizeof(hypercall))) {
1223fca5f2dcSDavid Gibson             _FDT(fdt_setprop(fdt, hypervisor, "hcall-instructions",
1224fca5f2dcSDavid Gibson                              hypercall, sizeof(hypercall)));
1225fca5f2dcSDavid Gibson         }
1226fca5f2dcSDavid Gibson     }
1227fca5f2dcSDavid Gibson }
1228fca5f2dcSDavid Gibson 
spapr_build_fdt(SpaprMachineState * spapr,bool reset,size_t space)12290c21e073SDavid Gibson void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space)
123053018216SPaolo Bonzini {
1231c86c1affSDaniel Henrique Barboza     MachineState *machine = MACHINE(spapr);
12323c0c47e3SDavid Gibson     MachineClass *mc = MACHINE_GET_CLASS(machine);
1233ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
1234776e887fSGreg Kurz     uint32_t root_drc_type_mask = 0;
12357c866c6aSDavid Gibson     int ret;
123653018216SPaolo Bonzini     void *fdt;
1237ce2918cbSDavid Gibson     SpaprPhbState *phb;
1238398a0bd5SDavid Gibson     char *buf;
123953018216SPaolo Bonzini 
124097b32a6aSDavid Gibson     fdt = g_malloc0(space);
124197b32a6aSDavid Gibson     _FDT((fdt_create_empty_tree(fdt, space)));
124253018216SPaolo Bonzini 
1243398a0bd5SDavid Gibson     /* Root node */
1244398a0bd5SDavid Gibson     _FDT(fdt_setprop_string(fdt, 0, "device_type", "chrp"));
1245398a0bd5SDavid Gibson     _FDT(fdt_setprop_string(fdt, 0, "model", "IBM pSeries (emulated by qemu)"));
1246398a0bd5SDavid Gibson     _FDT(fdt_setprop_string(fdt, 0, "compatible", "qemu,pseries"));
1247398a0bd5SDavid Gibson 
12480a794529SDavid Gibson     /* Guest UUID & Name*/
1249398a0bd5SDavid Gibson     buf = qemu_uuid_unparse_strdup(&qemu_uuid);
1250398a0bd5SDavid Gibson     _FDT(fdt_setprop_string(fdt, 0, "vm,uuid", buf));
1251398a0bd5SDavid Gibson     if (qemu_uuid_set) {
1252398a0bd5SDavid Gibson         _FDT(fdt_setprop_string(fdt, 0, "system-id", buf));
1253398a0bd5SDavid Gibson     }
1254398a0bd5SDavid Gibson     g_free(buf);
1255398a0bd5SDavid Gibson 
1256398a0bd5SDavid Gibson     if (qemu_get_vm_name()) {
1257398a0bd5SDavid Gibson         _FDT(fdt_setprop_string(fdt, 0, "ibm,partition-name",
1258398a0bd5SDavid Gibson                                 qemu_get_vm_name()));
1259398a0bd5SDavid Gibson     }
1260398a0bd5SDavid Gibson 
12610a794529SDavid Gibson     /* Host Model & Serial Number */
12620a794529SDavid Gibson     if (spapr->host_model) {
12630a794529SDavid Gibson         _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model));
12640a794529SDavid Gibson     } else if (smc->broken_host_serial_model && kvmppc_get_host_model(&buf)) {
12650a794529SDavid Gibson         _FDT(fdt_setprop_string(fdt, 0, "host-model", buf));
12660a794529SDavid Gibson         g_free(buf);
12670a794529SDavid Gibson     }
12680a794529SDavid Gibson 
12690a794529SDavid Gibson     if (spapr->host_serial) {
12700a794529SDavid Gibson         _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial));
12710a794529SDavid Gibson     } else if (smc->broken_host_serial_model && kvmppc_get_host_serial(&buf)) {
12720a794529SDavid Gibson         _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf));
12730a794529SDavid Gibson         g_free(buf);
12740a794529SDavid Gibson     }
12750a794529SDavid Gibson 
1276398a0bd5SDavid Gibson     _FDT(fdt_setprop_cell(fdt, 0, "#address-cells", 2));
1277398a0bd5SDavid Gibson     _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2));
127853018216SPaolo Bonzini 
1279fc7e0765SDavid Gibson     /* /interrupt controller */
128005289273SDavid Gibson     spapr_irq_dt(spapr, spapr_max_server_number(spapr), fdt, PHANDLE_INTC);
1281fc7e0765SDavid Gibson 
128291335a5eSDavid Gibson     ret = spapr_dt_memory(spapr, fdt);
1283e8f986fcSBharata B Rao     if (ret < 0) {
1284ce9863b7SCédric Le Goater         error_report("couldn't setup memory nodes in fdt");
1285e8f986fcSBharata B Rao         exit(1);
128653018216SPaolo Bonzini     }
128753018216SPaolo Bonzini 
1288bf5a6696SDavid Gibson     /* /vdevice */
1289bf5a6696SDavid Gibson     spapr_dt_vdevice(spapr->vio_bus, fdt);
129053018216SPaolo Bonzini 
12914d9392beSThomas Huth     if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) {
129291335a5eSDavid Gibson         ret = spapr_dt_rng(fdt);
12934d9392beSThomas Huth         if (ret < 0) {
1294ce9863b7SCédric Le Goater             error_report("could not set up rng device in the fdt");
12954d9392beSThomas Huth             exit(1);
12964d9392beSThomas Huth         }
12974d9392beSThomas Huth     }
12984d9392beSThomas Huth 
129953018216SPaolo Bonzini     QLIST_FOREACH(phb, &spapr->phbs, list) {
13008cbe71ecSDavid Gibson         ret = spapr_dt_phb(spapr, phb, PHANDLE_INTC, fdt, NULL);
130153018216SPaolo Bonzini         if (ret < 0) {
1302da34fed7SThomas Huth             error_report("couldn't setup PCI devices in fdt");
130353018216SPaolo Bonzini             exit(1);
130453018216SPaolo Bonzini         }
1305da34fed7SThomas Huth     }
130653018216SPaolo Bonzini 
130791335a5eSDavid Gibson     spapr_dt_cpus(fdt, spapr);
130853018216SPaolo Bonzini 
1309776e887fSGreg Kurz     /* ibm,drc-indexes and friends */
1310c20d332aSBharata B Rao     if (smc->dr_lmb_enabled) {
1311776e887fSGreg Kurz         root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_LMB;
1312776e887fSGreg Kurz     }
1313776e887fSGreg Kurz     if (smc->dr_phb_enabled) {
1314776e887fSGreg Kurz         root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_PHB;
1315776e887fSGreg Kurz     }
1316776e887fSGreg Kurz     if (mc->nvdimm_supported) {
1317776e887fSGreg Kurz         root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_PMEM;
1318776e887fSGreg Kurz     }
1319776e887fSGreg Kurz     if (root_drc_type_mask) {
1320776e887fSGreg Kurz         _FDT(spapr_dt_drc(fdt, 0, NULL, root_drc_type_mask));
1321c20d332aSBharata B Rao     }
1322c20d332aSBharata B Rao 
1323c5514d0eSIgor Mammedov     if (mc->has_hotpluggable_cpus) {
1324af81cf32SBharata B Rao         int offset = fdt_path_offset(fdt, "/cpus");
13259e7d38e8SDavid Gibson         ret = spapr_dt_drc(fdt, offset, NULL, SPAPR_DR_CONNECTOR_TYPE_CPU);
1326af81cf32SBharata B Rao         if (ret < 0) {
1327af81cf32SBharata B Rao             error_report("Couldn't set up CPU DR device tree properties");
1328af81cf32SBharata B Rao             exit(1);
1329af81cf32SBharata B Rao         }
1330af81cf32SBharata B Rao     }
1331af81cf32SBharata B Rao 
1332ffb1e275SDavid Gibson     /* /event-sources */
1333ffbb1705SMichael Roth     spapr_dt_events(spapr, fdt);
1334ffb1e275SDavid Gibson 
13353f5dabceSDavid Gibson     /* /rtas */
13363f5dabceSDavid Gibson     spapr_dt_rtas(spapr, fdt);
13373f5dabceSDavid Gibson 
13387c866c6aSDavid Gibson     /* /chosen */
13391e0e1108SDavid Gibson     spapr_dt_chosen(spapr, fdt, reset);
1340cf6e5223SDavid Gibson 
1341fca5f2dcSDavid Gibson     /* /hypervisor */
1342fca5f2dcSDavid Gibson     if (kvm_enabled()) {
1343fca5f2dcSDavid Gibson         spapr_dt_hypervisor(spapr, fdt);
1344fca5f2dcSDavid Gibson     }
1345fca5f2dcSDavid Gibson 
1346cf6e5223SDavid Gibson     /* Build memory reserve map */
1347a49f62b9SAlexey Kardashevskiy     if (reset) {
1348cf6e5223SDavid Gibson         if (spapr->kernel_size) {
134987262806SAlexey Kardashevskiy             _FDT((fdt_add_mem_rsv(fdt, spapr->kernel_addr,
135087262806SAlexey Kardashevskiy                                   spapr->kernel_size)));
1351cf6e5223SDavid Gibson         }
1352cf6e5223SDavid Gibson         if (spapr->initrd_size) {
1353a49f62b9SAlexey Kardashevskiy             _FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base,
1354a49f62b9SAlexey Kardashevskiy                                   spapr->initrd_size)));
1355a49f62b9SAlexey Kardashevskiy         }
1356cf6e5223SDavid Gibson     }
1357cf6e5223SDavid Gibson 
1358ee3a71e3SShivaprasad G Bhat     /* NVDIMM devices */
1359ee3a71e3SShivaprasad G Bhat     if (mc->nvdimm_supported) {
1360f1aa45ffSDaniel Henrique Barboza         spapr_dt_persistent_memory(spapr, fdt);
1361ee3a71e3SShivaprasad G Bhat     }
1362ee3a71e3SShivaprasad G Bhat 
1363997b6cfcSDavid Gibson     return fdt;
136453018216SPaolo Bonzini }
136553018216SPaolo Bonzini 
translate_kernel_address(void * opaque,uint64_t addr)136653018216SPaolo Bonzini static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
136753018216SPaolo Bonzini {
136887262806SAlexey Kardashevskiy     SpaprMachineState *spapr = opaque;
136987262806SAlexey Kardashevskiy 
137087262806SAlexey Kardashevskiy     return (addr & 0x0fffffff) + spapr->kernel_addr;
137153018216SPaolo Bonzini }
137253018216SPaolo Bonzini 
emulate_spapr_hypercall(PPCVirtualHypervisor * vhyp,PowerPCCPU * cpu)13731d1be34dSDavid Gibson static void emulate_spapr_hypercall(PPCVirtualHypervisor *vhyp,
13741d1be34dSDavid Gibson                                     PowerPCCPU *cpu)
137553018216SPaolo Bonzini {
137653018216SPaolo Bonzini     CPUPPCState *env = &cpu->env;
137753018216SPaolo Bonzini 
13788d04fb55SJan Kiszka     /* The TCG path should also be holding the BQL at this point */
1379195801d7SStefan Hajnoczi     g_assert(bql_locked());
13808d04fb55SJan Kiszka 
1381120f738aSNicholas Piggin     g_assert(!vhyp_cpu_in_nested(cpu));
1382120f738aSNicholas Piggin 
1383d41ccf6eSVíctor Colombo     if (FIELD_EX64(env->msr, MSR, PR)) {
138453018216SPaolo Bonzini         hcall_dprintf("Hypercall made with MSR[PR]=1\n");
138553018216SPaolo Bonzini         env->gpr[3] = H_PRIVILEGE;
138653018216SPaolo Bonzini     } else {
138753018216SPaolo Bonzini         env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]);
138853018216SPaolo Bonzini     }
138953018216SPaolo Bonzini }
139053018216SPaolo Bonzini 
139100fd075eSBenjamin Herrenschmidt struct LPCRSyncState {
139200fd075eSBenjamin Herrenschmidt     target_ulong value;
139300fd075eSBenjamin Herrenschmidt     target_ulong mask;
139400fd075eSBenjamin Herrenschmidt };
139500fd075eSBenjamin Herrenschmidt 
do_lpcr_sync(CPUState * cs,run_on_cpu_data arg)139600fd075eSBenjamin Herrenschmidt static void do_lpcr_sync(CPUState *cs, run_on_cpu_data arg)
139700fd075eSBenjamin Herrenschmidt {
139800fd075eSBenjamin Herrenschmidt     struct LPCRSyncState *s = arg.host_ptr;
139900fd075eSBenjamin Herrenschmidt     PowerPCCPU *cpu = POWERPC_CPU(cs);
140000fd075eSBenjamin Herrenschmidt     CPUPPCState *env = &cpu->env;
140100fd075eSBenjamin Herrenschmidt     target_ulong lpcr;
140200fd075eSBenjamin Herrenschmidt 
140300fd075eSBenjamin Herrenschmidt     cpu_synchronize_state(cs);
140400fd075eSBenjamin Herrenschmidt     lpcr = env->spr[SPR_LPCR];
140500fd075eSBenjamin Herrenschmidt     lpcr &= ~s->mask;
140600fd075eSBenjamin Herrenschmidt     lpcr |= s->value;
140700fd075eSBenjamin Herrenschmidt     ppc_store_lpcr(cpu, lpcr);
140800fd075eSBenjamin Herrenschmidt }
140900fd075eSBenjamin Herrenschmidt 
spapr_set_all_lpcrs(target_ulong value,target_ulong mask)141000fd075eSBenjamin Herrenschmidt void spapr_set_all_lpcrs(target_ulong value, target_ulong mask)
141100fd075eSBenjamin Herrenschmidt {
141200fd075eSBenjamin Herrenschmidt     CPUState *cs;
141300fd075eSBenjamin Herrenschmidt     struct LPCRSyncState s = {
141400fd075eSBenjamin Herrenschmidt         .value = value,
141500fd075eSBenjamin Herrenschmidt         .mask = mask
141600fd075eSBenjamin Herrenschmidt     };
141700fd075eSBenjamin Herrenschmidt     CPU_FOREACH(cs) {
141800fd075eSBenjamin Herrenschmidt         run_on_cpu(cs, do_lpcr_sync, RUN_ON_CPU_HOST_PTR(&s));
141900fd075eSBenjamin Herrenschmidt     }
142000fd075eSBenjamin Herrenschmidt }
142100fd075eSBenjamin Herrenschmidt 
14229c7b7f01SNicholas Piggin /* May be used when the machine is not running */
spapr_init_all_lpcrs(target_ulong value,target_ulong mask)14239c7b7f01SNicholas Piggin void spapr_init_all_lpcrs(target_ulong value, target_ulong mask)
14249c7b7f01SNicholas Piggin {
14259c7b7f01SNicholas Piggin     CPUState *cs;
14269c7b7f01SNicholas Piggin     CPU_FOREACH(cs) {
14279c7b7f01SNicholas Piggin         PowerPCCPU *cpu = POWERPC_CPU(cs);
14289c7b7f01SNicholas Piggin         CPUPPCState *env = &cpu->env;
14299c7b7f01SNicholas Piggin         target_ulong lpcr;
14309c7b7f01SNicholas Piggin 
14319c7b7f01SNicholas Piggin         lpcr = env->spr[SPR_LPCR];
14329c7b7f01SNicholas Piggin         lpcr &= ~(LPCR_HR | LPCR_UPRT);
14339c7b7f01SNicholas Piggin         ppc_store_lpcr(cpu, lpcr);
14349c7b7f01SNicholas Piggin     }
14359c7b7f01SNicholas Piggin }
14369c7b7f01SNicholas Piggin 
spapr_get_pate(PPCVirtualHypervisor * vhyp,PowerPCCPU * cpu,target_ulong lpid,ppc_v3_pate_t * entry)1437f32d4ab4SNicholas Piggin static bool spapr_get_pate(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu,
1438f32d4ab4SNicholas Piggin                            target_ulong lpid, ppc_v3_pate_t *entry)
14399861bb3eSSuraj Jitindar Singh {
1440ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
1441120f738aSNicholas Piggin     SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
14429861bb3eSSuraj Jitindar Singh 
1443120f738aSNicholas Piggin     if (!spapr_cpu->in_nested) {
1444f32d4ab4SNicholas Piggin         assert(lpid == 0);
1445f32d4ab4SNicholas Piggin 
144679825f4dSBenjamin Herrenschmidt         /* Copy PATE1:GR into PATE0:HR */
144779825f4dSBenjamin Herrenschmidt         entry->dw0 = spapr->patb_entry & PATE0_HR;
144879825f4dSBenjamin Herrenschmidt         entry->dw1 = spapr->patb_entry;
1449f32d4ab4SNicholas Piggin         return true;
1450c2813a35SHarsh Prateek Bora     } else {
145121a8d22fSHarsh Prateek Bora         if (spapr_nested_api(spapr) == NESTED_API_KVM_HV) {
1452c2813a35SHarsh Prateek Bora             return spapr_get_pate_nested_hv(spapr, cpu, lpid, entry);
145398823ce0SHarsh Prateek Bora         } else if (spapr_nested_api(spapr) == NESTED_API_PAPR) {
145498823ce0SHarsh Prateek Bora             return spapr_get_pate_nested_papr(spapr, cpu, lpid, entry);
145598823ce0SHarsh Prateek Bora         } else {
145698823ce0SHarsh Prateek Bora             g_assert_not_reached();
1457c2813a35SHarsh Prateek Bora         }
145821a8d22fSHarsh Prateek Bora     }
14599861bb3eSSuraj Jitindar Singh }
14609861bb3eSSuraj Jitindar Singh 
1461e6b8fd24SSamuel Mendoza-Jonas #define HPTE(_table, _i)   (void *)(((uint64_t *)(_table)) + ((_i) * 2))
1462e6b8fd24SSamuel Mendoza-Jonas #define HPTE_VALID(_hpte)  (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID)
1463e6b8fd24SSamuel Mendoza-Jonas #define HPTE_DIRTY(_hpte)  (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY)
1464e6b8fd24SSamuel Mendoza-Jonas #define CLEAN_HPTE(_hpte)  ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY))
1465e6b8fd24SSamuel Mendoza-Jonas #define DIRTY_HPTE(_hpte)  ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY))
1466e6b8fd24SSamuel Mendoza-Jonas 
1467715c5407SDavid Gibson /*
1468715c5407SDavid Gibson  * Get the fd to access the kernel htab, re-opening it if necessary
1469715c5407SDavid Gibson  */
get_htab_fd(SpaprMachineState * spapr)1470ce2918cbSDavid Gibson static int get_htab_fd(SpaprMachineState *spapr)
1471715c5407SDavid Gibson {
147214b0d748SGreg Kurz     Error *local_err = NULL;
147314b0d748SGreg Kurz 
1474715c5407SDavid Gibson     if (spapr->htab_fd >= 0) {
1475715c5407SDavid Gibson         return spapr->htab_fd;
1476715c5407SDavid Gibson     }
1477715c5407SDavid Gibson 
147814b0d748SGreg Kurz     spapr->htab_fd = kvmppc_get_htab_fd(false, 0, &local_err);
1479715c5407SDavid Gibson     if (spapr->htab_fd < 0) {
148014b0d748SGreg Kurz         error_report_err(local_err);
1481715c5407SDavid Gibson     }
1482715c5407SDavid Gibson 
1483715c5407SDavid Gibson     return spapr->htab_fd;
1484715c5407SDavid Gibson }
1485715c5407SDavid Gibson 
close_htab_fd(SpaprMachineState * spapr)1486ce2918cbSDavid Gibson void close_htab_fd(SpaprMachineState *spapr)
1487715c5407SDavid Gibson {
1488715c5407SDavid Gibson     if (spapr->htab_fd >= 0) {
1489715c5407SDavid Gibson         close(spapr->htab_fd);
1490715c5407SDavid Gibson     }
1491715c5407SDavid Gibson     spapr->htab_fd = -1;
1492715c5407SDavid Gibson }
1493715c5407SDavid Gibson 
spapr_hpt_mask(PPCVirtualHypervisor * vhyp)1494e57ca75cSDavid Gibson static hwaddr spapr_hpt_mask(PPCVirtualHypervisor *vhyp)
1495e57ca75cSDavid Gibson {
1496ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
1497e57ca75cSDavid Gibson 
1498e57ca75cSDavid Gibson     return HTAB_SIZE(spapr) / HASH_PTEG_SIZE_64 - 1;
1499e57ca75cSDavid Gibson }
1500e57ca75cSDavid Gibson 
spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor * vhyp)15011ec26c75SGreg Kurz static target_ulong spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp)
15021ec26c75SGreg Kurz {
1503ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
15041ec26c75SGreg Kurz 
15051ec26c75SGreg Kurz     assert(kvm_enabled());
15061ec26c75SGreg Kurz 
15071ec26c75SGreg Kurz     if (!spapr->htab) {
15081ec26c75SGreg Kurz         return 0;
15091ec26c75SGreg Kurz     }
15101ec26c75SGreg Kurz 
15111ec26c75SGreg Kurz     return (target_ulong)(uintptr_t)spapr->htab | (spapr->htab_shift - 18);
15121ec26c75SGreg Kurz }
15131ec26c75SGreg Kurz 
spapr_map_hptes(PPCVirtualHypervisor * vhyp,hwaddr ptex,int n)1514e57ca75cSDavid Gibson static const ppc_hash_pte64_t *spapr_map_hptes(PPCVirtualHypervisor *vhyp,
1515e57ca75cSDavid Gibson                                                 hwaddr ptex, int n)
1516e57ca75cSDavid Gibson {
1517ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
1518e57ca75cSDavid Gibson     hwaddr pte_offset = ptex * HASH_PTE_SIZE_64;
1519e57ca75cSDavid Gibson 
1520e57ca75cSDavid Gibson     if (!spapr->htab) {
1521e57ca75cSDavid Gibson         /*
1522e57ca75cSDavid Gibson          * HTAB is controlled by KVM. Fetch into temporary buffer
1523e57ca75cSDavid Gibson          */
1524e57ca75cSDavid Gibson         ppc_hash_pte64_t *hptes = g_malloc(n * HASH_PTE_SIZE_64);
1525e57ca75cSDavid Gibson         kvmppc_read_hptes(hptes, ptex, n);
1526e57ca75cSDavid Gibson         return hptes;
1527e57ca75cSDavid Gibson     }
1528e57ca75cSDavid Gibson 
1529e57ca75cSDavid Gibson     /*
1530e57ca75cSDavid Gibson      * HTAB is controlled by QEMU. Just point to the internally
1531e57ca75cSDavid Gibson      * accessible PTEG.
1532e57ca75cSDavid Gibson      */
1533e57ca75cSDavid Gibson     return (const ppc_hash_pte64_t *)(spapr->htab + pte_offset);
1534e57ca75cSDavid Gibson }
1535e57ca75cSDavid Gibson 
spapr_unmap_hptes(PPCVirtualHypervisor * vhyp,const ppc_hash_pte64_t * hptes,hwaddr ptex,int n)1536e57ca75cSDavid Gibson static void spapr_unmap_hptes(PPCVirtualHypervisor *vhyp,
1537e57ca75cSDavid Gibson                               const ppc_hash_pte64_t *hptes,
1538e57ca75cSDavid Gibson                               hwaddr ptex, int n)
1539e57ca75cSDavid Gibson {
1540ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
1541e57ca75cSDavid Gibson 
1542e57ca75cSDavid Gibson     if (!spapr->htab) {
1543e57ca75cSDavid Gibson         g_free((void *)hptes);
1544e57ca75cSDavid Gibson     }
1545e57ca75cSDavid Gibson 
1546e57ca75cSDavid Gibson     /* Nothing to do for qemu managed HPT */
1547e57ca75cSDavid Gibson }
1548e57ca75cSDavid Gibson 
spapr_store_hpte(PowerPCCPU * cpu,hwaddr ptex,uint64_t pte0,uint64_t pte1)1549a2dd4e83SBenjamin Herrenschmidt void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
1550e57ca75cSDavid Gibson                       uint64_t pte0, uint64_t pte1)
1551e57ca75cSDavid Gibson {
1552a2dd4e83SBenjamin Herrenschmidt     SpaprMachineState *spapr = SPAPR_MACHINE(cpu->vhyp);
1553e57ca75cSDavid Gibson     hwaddr offset = ptex * HASH_PTE_SIZE_64;
1554e57ca75cSDavid Gibson 
1555e57ca75cSDavid Gibson     if (!spapr->htab) {
1556e57ca75cSDavid Gibson         kvmppc_write_hpte(ptex, pte0, pte1);
1557e57ca75cSDavid Gibson     } else {
15583054b0caSBenjamin Herrenschmidt         if (pte0 & HPTE64_V_VALID) {
15597bf00dfbSLeandro Lupori             stq_p(spapr->htab + offset + HPTE64_DW1, pte1);
15603054b0caSBenjamin Herrenschmidt             /*
15613054b0caSBenjamin Herrenschmidt              * When setting valid, we write PTE1 first. This ensures
15623054b0caSBenjamin Herrenschmidt              * proper synchronization with the reading code in
15633054b0caSBenjamin Herrenschmidt              * ppc_hash64_pteg_search()
15643054b0caSBenjamin Herrenschmidt              */
15653054b0caSBenjamin Herrenschmidt             smp_wmb();
15663054b0caSBenjamin Herrenschmidt             stq_p(spapr->htab + offset, pte0);
15673054b0caSBenjamin Herrenschmidt         } else {
15683054b0caSBenjamin Herrenschmidt             stq_p(spapr->htab + offset, pte0);
15693054b0caSBenjamin Herrenschmidt             /*
15703054b0caSBenjamin Herrenschmidt              * When clearing it we set PTE0 first. This ensures proper
15713054b0caSBenjamin Herrenschmidt              * synchronization with the reading code in
15723054b0caSBenjamin Herrenschmidt              * ppc_hash64_pteg_search()
15733054b0caSBenjamin Herrenschmidt              */
15743054b0caSBenjamin Herrenschmidt             smp_wmb();
15757bf00dfbSLeandro Lupori             stq_p(spapr->htab + offset + HPTE64_DW1, pte1);
15763054b0caSBenjamin Herrenschmidt         }
1577e57ca75cSDavid Gibson     }
1578e57ca75cSDavid Gibson }
1579e57ca75cSDavid Gibson 
spapr_hpte_set_c(PPCVirtualHypervisor * vhyp,hwaddr ptex,uint64_t pte1)1580a2dd4e83SBenjamin Herrenschmidt static void spapr_hpte_set_c(PPCVirtualHypervisor *vhyp, hwaddr ptex,
1581a2dd4e83SBenjamin Herrenschmidt                              uint64_t pte1)
1582a2dd4e83SBenjamin Herrenschmidt {
15837bf00dfbSLeandro Lupori     hwaddr offset = ptex * HASH_PTE_SIZE_64 + HPTE64_DW1_C;
1584a2dd4e83SBenjamin Herrenschmidt     SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
1585a2dd4e83SBenjamin Herrenschmidt 
1586a2dd4e83SBenjamin Herrenschmidt     if (!spapr->htab) {
1587a2dd4e83SBenjamin Herrenschmidt         /* There should always be a hash table when this is called */
1588a2dd4e83SBenjamin Herrenschmidt         error_report("spapr_hpte_set_c called with no hash table !");
1589a2dd4e83SBenjamin Herrenschmidt         return;
1590a2dd4e83SBenjamin Herrenschmidt     }
1591a2dd4e83SBenjamin Herrenschmidt 
1592a2dd4e83SBenjamin Herrenschmidt     /* The HW performs a non-atomic byte update */
1593a2dd4e83SBenjamin Herrenschmidt     stb_p(spapr->htab + offset, (pte1 & 0xff) | 0x80);
1594a2dd4e83SBenjamin Herrenschmidt }
1595a2dd4e83SBenjamin Herrenschmidt 
spapr_hpte_set_r(PPCVirtualHypervisor * vhyp,hwaddr ptex,uint64_t pte1)1596a2dd4e83SBenjamin Herrenschmidt static void spapr_hpte_set_r(PPCVirtualHypervisor *vhyp, hwaddr ptex,
1597a2dd4e83SBenjamin Herrenschmidt                              uint64_t pte1)
1598a2dd4e83SBenjamin Herrenschmidt {
15997bf00dfbSLeandro Lupori     hwaddr offset = ptex * HASH_PTE_SIZE_64 + HPTE64_DW1_R;
1600a2dd4e83SBenjamin Herrenschmidt     SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
1601a2dd4e83SBenjamin Herrenschmidt 
1602a2dd4e83SBenjamin Herrenschmidt     if (!spapr->htab) {
1603a2dd4e83SBenjamin Herrenschmidt         /* There should always be a hash table when this is called */
1604a2dd4e83SBenjamin Herrenschmidt         error_report("spapr_hpte_set_r called with no hash table !");
1605a2dd4e83SBenjamin Herrenschmidt         return;
1606a2dd4e83SBenjamin Herrenschmidt     }
1607a2dd4e83SBenjamin Herrenschmidt 
1608a2dd4e83SBenjamin Herrenschmidt     /* The HW performs a non-atomic byte update */
1609a2dd4e83SBenjamin Herrenschmidt     stb_p(spapr->htab + offset, ((pte1 >> 8) & 0xff) | 0x01);
1610a2dd4e83SBenjamin Herrenschmidt }
1611a2dd4e83SBenjamin Herrenschmidt 
spapr_hpt_shift_for_ramsize(uint64_t ramsize)16120b0b8310SDavid Gibson int spapr_hpt_shift_for_ramsize(uint64_t ramsize)
16138dfe8e7fSDavid Gibson {
16148dfe8e7fSDavid Gibson     int shift;
16158dfe8e7fSDavid Gibson 
16168dfe8e7fSDavid Gibson     /* We aim for a hash table of size 1/128 the size of RAM (rounded
16178dfe8e7fSDavid Gibson      * up).  The PAPR recommendation is actually 1/64 of RAM size, but
16188dfe8e7fSDavid Gibson      * that's much more than is needed for Linux guests */
16198dfe8e7fSDavid Gibson     shift = ctz64(pow2ceil(ramsize)) - 7;
16208dfe8e7fSDavid Gibson     shift = MAX(shift, 18); /* Minimum architected size */
16218dfe8e7fSDavid Gibson     shift = MIN(shift, 46); /* Maximum architected size */
16228dfe8e7fSDavid Gibson     return shift;
16238dfe8e7fSDavid Gibson }
16248dfe8e7fSDavid Gibson 
spapr_free_hpt(SpaprMachineState * spapr)1625ce2918cbSDavid Gibson void spapr_free_hpt(SpaprMachineState *spapr)
162606ec79e8SBharata B Rao {
1627cb5b5ab9SXuzhou Cheng     qemu_vfree(spapr->htab);
162806ec79e8SBharata B Rao     spapr->htab = NULL;
162906ec79e8SBharata B Rao     spapr->htab_shift = 0;
163006ec79e8SBharata B Rao     close_htab_fd(spapr);
163106ec79e8SBharata B Rao }
163206ec79e8SBharata B Rao 
spapr_reallocate_hpt(SpaprMachineState * spapr,int shift,Error ** errp)1633a4e3a7c0SGreg Kurz int spapr_reallocate_hpt(SpaprMachineState *spapr, int shift, Error **errp)
163453018216SPaolo Bonzini {
1635c3e051edSGreg Kurz     ERRP_GUARD();
1636c5f54f3eSDavid Gibson     long rc;
163753018216SPaolo Bonzini 
1638c5f54f3eSDavid Gibson     /* Clean up any HPT info from a previous boot */
163906ec79e8SBharata B Rao     spapr_free_hpt(spapr);
164053018216SPaolo Bonzini 
1641c5f54f3eSDavid Gibson     rc = kvmppc_reset_htab(shift);
1642f0638a0bSFabiano Rosas 
1643f0638a0bSFabiano Rosas     if (rc == -EOPNOTSUPP) {
1644f0638a0bSFabiano Rosas         error_setg(errp, "HPT not supported in nested guests");
1645a4e3a7c0SGreg Kurz         return -EOPNOTSUPP;
1646f0638a0bSFabiano Rosas     }
1647f0638a0bSFabiano Rosas 
1648c5f54f3eSDavid Gibson     if (rc < 0) {
1649c5f54f3eSDavid Gibson         /* kernel-side HPT needed, but couldn't allocate one */
1650c3e051edSGreg Kurz         error_setg_errno(errp, errno, "Failed to allocate KVM HPT of order %d",
1651c5f54f3eSDavid Gibson                          shift);
1652c3e051edSGreg Kurz         error_append_hint(errp, "Try smaller maxmem?\n");
1653a4e3a7c0SGreg Kurz         return -errno;
1654c5f54f3eSDavid Gibson     } else if (rc > 0) {
1655c5f54f3eSDavid Gibson         /* kernel-side HPT allocated */
1656c5f54f3eSDavid Gibson         if (rc != shift) {
1657c5f54f3eSDavid Gibson             error_setg(errp,
1658c3e051edSGreg Kurz                        "Requested order %d HPT, but kernel allocated order %ld",
1659c5f54f3eSDavid Gibson                        shift, rc);
1660c3e051edSGreg Kurz             error_append_hint(errp, "Try smaller maxmem?\n");
1661a4e3a7c0SGreg Kurz             return -ENOSPC;
16627735fedaSBharata B Rao         }
16637735fedaSBharata B Rao 
166453018216SPaolo Bonzini         spapr->htab_shift = shift;
1665c18ad9a5SDavid Gibson         spapr->htab = NULL;
1666b817772aSBharata B Rao     } else {
1667c5f54f3eSDavid Gibson         /* kernel-side HPT not needed, allocate in userspace instead */
1668c5f54f3eSDavid Gibson         size_t size = 1ULL << shift;
1669c5f54f3eSDavid Gibson         int i;
167001a57972SSamuel Mendoza-Jonas 
1671c5f54f3eSDavid Gibson         spapr->htab = qemu_memalign(size, size);
1672c5f54f3eSDavid Gibson         memset(spapr->htab, 0, size);
1673c5f54f3eSDavid Gibson         spapr->htab_shift = shift;
1674b817772aSBharata B Rao 
1675c5f54f3eSDavid Gibson         for (i = 0; i < size / HASH_PTE_SIZE_64; i++) {
1676c5f54f3eSDavid Gibson             DIRTY_HPTE(HPTE(spapr->htab, i));
16777735fedaSBharata B Rao         }
167853018216SPaolo Bonzini     }
1679ee4d9eccSSuraj Jitindar Singh     /* We're setting up a hash table, so that means we're not radix */
1680176dcceeSSuraj Jitindar Singh     spapr->patb_entry = 0;
16819c7b7f01SNicholas Piggin     spapr_init_all_lpcrs(0, LPCR_HR | LPCR_UPRT);
1682a4e3a7c0SGreg Kurz     return 0;
168353018216SPaolo Bonzini }
168453018216SPaolo Bonzini 
spapr_setup_hpt(SpaprMachineState * spapr)16858897ea5aSDavid Gibson void spapr_setup_hpt(SpaprMachineState *spapr)
1686b4db5413SSuraj Jitindar Singh {
16872772cf6bSDavid Gibson     int hpt_shift;
16882772cf6bSDavid Gibson 
1689087820e3SGreg Kurz     if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DISABLED) {
16902772cf6bSDavid Gibson         hpt_shift = spapr_hpt_shift_for_ramsize(MACHINE(spapr)->maxram_size);
16912772cf6bSDavid Gibson     } else {
1692768a20f3SDavid Gibson         uint64_t current_ram_size;
1693768a20f3SDavid Gibson 
1694768a20f3SDavid Gibson         current_ram_size = MACHINE(spapr)->ram_size + get_plugged_memory_size();
1695768a20f3SDavid Gibson         hpt_shift = spapr_hpt_shift_for_ramsize(current_ram_size);
16962772cf6bSDavid Gibson     }
16972772cf6bSDavid Gibson     spapr_reallocate_hpt(spapr, hpt_shift, &error_fatal);
16982772cf6bSDavid Gibson 
16998897ea5aSDavid Gibson     if (kvm_enabled()) {
17006a84737cSDavid Gibson         hwaddr vrma_limit = kvmppc_vrma_limit(spapr->htab_shift);
17016a84737cSDavid Gibson 
17028897ea5aSDavid Gibson         /* Check our RMA fits in the possible VRMA */
17038897ea5aSDavid Gibson         if (vrma_limit < spapr->rma_size) {
17048897ea5aSDavid Gibson             error_report("Unable to create %" HWADDR_PRIu
17058897ea5aSDavid Gibson                          "MiB RMA (VRMA only allows %" HWADDR_PRIu "MiB",
17068897ea5aSDavid Gibson                          spapr->rma_size / MiB, vrma_limit / MiB);
17078897ea5aSDavid Gibson             exit(EXIT_FAILURE);
17088897ea5aSDavid Gibson         }
1709b4db5413SSuraj Jitindar Singh     }
1710b4db5413SSuraj Jitindar Singh }
1711b4db5413SSuraj Jitindar Singh 
spapr_check_mmu_mode(bool guest_radix)1712068479e1SFabiano Rosas void spapr_check_mmu_mode(bool guest_radix)
1713068479e1SFabiano Rosas {
1714068479e1SFabiano Rosas     if (guest_radix) {
1715068479e1SFabiano Rosas         if (kvm_enabled() && !kvmppc_has_cap_mmu_radix()) {
1716068479e1SFabiano Rosas             error_report("Guest requested unavailable MMU mode (radix).");
1717068479e1SFabiano Rosas             exit(EXIT_FAILURE);
1718068479e1SFabiano Rosas         }
1719068479e1SFabiano Rosas     } else {
1720068479e1SFabiano Rosas         if (kvm_enabled() && kvmppc_has_cap_mmu_radix()
1721068479e1SFabiano Rosas             && !kvmppc_has_cap_mmu_hash_v3()) {
1722068479e1SFabiano Rosas             error_report("Guest requested unavailable MMU mode (hash).");
1723068479e1SFabiano Rosas             exit(EXIT_FAILURE);
1724068479e1SFabiano Rosas         }
1725068479e1SFabiano Rosas     }
1726068479e1SFabiano Rosas }
1727068479e1SFabiano Rosas 
spapr_machine_reset(MachineState * machine,ShutdownCause reason)17287966d70fSJason A. Donenfeld static void spapr_machine_reset(MachineState *machine, ShutdownCause reason)
172953018216SPaolo Bonzini {
1730ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(machine);
1731182735efSAndreas Färber     PowerPCCPU *first_ppc_cpu;
1732744a928cSAlexey Kardashevskiy     hwaddr fdt_addr;
1733997b6cfcSDavid Gibson     void *fdt;
1734997b6cfcSDavid Gibson     int rc;
1735259186a7SAndreas Färber 
1736b27fcb28SNicholas Piggin     if (reason != SHUTDOWN_CAUSE_SNAPSHOT_LOAD) {
1737b27fcb28SNicholas Piggin         /*
1738b27fcb28SNicholas Piggin          * Record-replay snapshot load must not consume random, this was
1739b27fcb28SNicholas Piggin          * already replayed from initial machine reset.
1740b27fcb28SNicholas Piggin          */
1741b27fcb28SNicholas Piggin         qemu_guest_getrandom_nofail(spapr->fdt_rng_seed, 32);
1742b27fcb28SNicholas Piggin     }
1743b27fcb28SNicholas Piggin 
174400a238b1SXiaoyao Li     if (machine->cgs) {
174500a238b1SXiaoyao Li         confidential_guest_kvm_reset(machine->cgs, &error_fatal);
174600a238b1SXiaoyao Li     }
17479f6edd06SDavid Gibson     spapr_caps_apply(spapr);
17486026fdbdSHarsh Prateek Bora     spapr_nested_reset(spapr);
174933face6bSDavid Gibson 
17501481fe5fSLaurent Vivier     first_ppc_cpu = POWERPC_CPU(first_cpu);
17511481fe5fSLaurent Vivier     if (kvm_enabled() && kvmppc_has_cap_mmu_radix() &&
1752ad99d04cSDavid Gibson         ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0,
17531481fe5fSLaurent Vivier                               spapr->max_compat_pvr)) {
175479825f4dSBenjamin Herrenschmidt         /*
175579825f4dSBenjamin Herrenschmidt          * If using KVM with radix mode available, VCPUs can be started
1756b4db5413SSuraj Jitindar Singh          * without a HPT because KVM will start them in radix mode.
175779825f4dSBenjamin Herrenschmidt          * Set the GR bit in PATE so that we know there is no HPT.
175879825f4dSBenjamin Herrenschmidt          */
175979825f4dSBenjamin Herrenschmidt         spapr->patb_entry = PATE1_GR;
176000fd075eSBenjamin Herrenschmidt         spapr_set_all_lpcrs(LPCR_HR | LPCR_UPRT, LPCR_HR | LPCR_UPRT);
1761b4db5413SSuraj Jitindar Singh     } else {
17628897ea5aSDavid Gibson         spapr_setup_hpt(spapr);
1763c5f54f3eSDavid Gibson     }
176453018216SPaolo Bonzini 
17657966d70fSJason A. Donenfeld     qemu_devices_reset(reason);
176625c9780dSDavid Gibson 
17679012a53fSGreg Kurz     spapr_ovec_cleanup(spapr->ov5_cas);
17689012a53fSGreg Kurz     spapr->ov5_cas = spapr_ovec_new();
17699012a53fSGreg Kurz 
17709c7b7f01SNicholas Piggin     ppc_init_compat_all(spapr->max_compat_pvr, &error_fatal);
17719012a53fSGreg Kurz 
1772ec132efaSAlexey Kardashevskiy     /*
1773b2e22477SCédric Le Goater      * This is fixing some of the default configuration of the XIVE
1774b2e22477SCédric Le Goater      * devices. To be called after the reset of the machine devices.
1775b2e22477SCédric Le Goater      */
1776b2e22477SCédric Le Goater     spapr_irq_reset(spapr, &error_fatal);
1777b2e22477SCédric Le Goater 
177823ff81bdSGreg Kurz     /*
177923ff81bdSGreg Kurz      * There is no CAS under qtest. Simulate one to please the code that
178023ff81bdSGreg Kurz      * depends on spapr->ov5_cas. This is especially needed to test device
178123ff81bdSGreg Kurz      * unplug, so we do that before resetting the DRCs.
178223ff81bdSGreg Kurz      */
178323ff81bdSGreg Kurz     if (qtest_enabled()) {
178423ff81bdSGreg Kurz         spapr_ovec_cleanup(spapr->ov5_cas);
178523ff81bdSGreg Kurz         spapr->ov5_cas = spapr_ovec_clone(spapr->ov5);
178623ff81bdSGreg Kurz     }
178723ff81bdSGreg Kurz 
1788b5513584SShivaprasad G Bhat     spapr_nvdimm_finish_flushes();
1789b5513584SShivaprasad G Bhat 
179082512483SGreg Kurz     /* DRC reset may cause a device to be unplugged. This will cause troubles
179182512483SGreg Kurz      * if this device is used by another device (eg, a running vhost backend
179282512483SGreg Kurz      * will crash QEMU if the DIMM holding the vring goes away). To avoid such
179382512483SGreg Kurz      * situations, we reset DRCs after all devices have been reset.
179482512483SGreg Kurz      */
179511055041SGreg Kurz     spapr_drc_reset_all(spapr);
179682512483SGreg Kurz 
179756258174SDaniel Henrique Barboza     spapr_clear_pending_events(spapr);
179853018216SPaolo Bonzini 
1799b7d1f77aSBenjamin Herrenschmidt     /*
18004b98e72dSAlexey Kardashevskiy      * We place the device tree just below either the top of the RMA,
1801df269271SAlexey Kardashevskiy      * or just below 2GB, whichever is lower, so that it can be
1802b7d1f77aSBenjamin Herrenschmidt      * processed with 32-bit real mode code if necessary
1803b7d1f77aSBenjamin Herrenschmidt      */
18044b98e72dSAlexey Kardashevskiy     fdt_addr = MIN(spapr->rma_size, FDT_MAX_ADDR) - FDT_MAX_SIZE;
1805b7d1f77aSBenjamin Herrenschmidt 
180697b32a6aSDavid Gibson     fdt = spapr_build_fdt(spapr, true, FDT_MAX_SIZE);
1807fc8c745dSAlexey Kardashevskiy     if (spapr->vof) {
180821bde1ecSAlexey Kardashevskiy         spapr_vof_reset(spapr, fdt, &error_fatal);
1809fc8c745dSAlexey Kardashevskiy         /*
1810fc8c745dSAlexey Kardashevskiy          * Do not pack the FDT as the client may change properties.
1811fc8c745dSAlexey Kardashevskiy          * VOF client does not expect the FDT so we do not load it to the VM.
1812fc8c745dSAlexey Kardashevskiy          */
1813fc8c745dSAlexey Kardashevskiy     } else {
1814997b6cfcSDavid Gibson         rc = fdt_pack(fdt);
1815997b6cfcSDavid Gibson         /* Should only fail if we've built a corrupted tree */
1816997b6cfcSDavid Gibson         assert(rc == 0);
1817997b6cfcSDavid Gibson 
1818fc8c745dSAlexey Kardashevskiy         spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT,
1819fc8c745dSAlexey Kardashevskiy                                   0, fdt_addr, 0);
1820cae172abSDavid Gibson         cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
1821fc8c745dSAlexey Kardashevskiy     }
1822fc8c745dSAlexey Kardashevskiy     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
1823fc8c745dSAlexey Kardashevskiy 
1824fea35ca4SAlexey Kardashevskiy     g_free(spapr->fdt_blob);
1825fea35ca4SAlexey Kardashevskiy     spapr->fdt_size = fdt_totalsize(fdt);
1826fea35ca4SAlexey Kardashevskiy     spapr->fdt_initial_size = spapr->fdt_size;
1827fea35ca4SAlexey Kardashevskiy     spapr->fdt_blob = fdt;
1828997b6cfcSDavid Gibson 
1829d890f2faSDaniel Henrique Barboza     /* Set machine->fdt for 'dumpdtb' QMP/HMP command */
1830d890f2faSDaniel Henrique Barboza     machine->fdt = fdt;
1831d890f2faSDaniel Henrique Barboza 
183253018216SPaolo Bonzini     /* Set up the entry state */
1833182735efSAndreas Färber     first_ppc_cpu->env.gpr[5] = 0;
183453018216SPaolo Bonzini 
1835edfdbf9cSNicholas Piggin     spapr->fwnmi_system_reset_addr = -1;
18368af7e1feSNicholas Piggin     spapr->fwnmi_machine_check_addr = -1;
18378af7e1feSNicholas Piggin     spapr->fwnmi_machine_check_interlock = -1;
18389ac703acSAravinda Prasad 
18399ac703acSAravinda Prasad     /* Signal all vCPUs waiting on this condition */
18408af7e1feSNicholas Piggin     qemu_cond_broadcast(&spapr->fwnmi_machine_check_interlock_cond);
18412500fb42SAravinda Prasad 
1842c8a7fc51SSteve Sistare     migrate_del_blocker(&spapr->fwnmi_migration_blocker);
184353018216SPaolo Bonzini }
184453018216SPaolo Bonzini 
spapr_create_nvram(SpaprMachineState * spapr)1845ce2918cbSDavid Gibson static void spapr_create_nvram(SpaprMachineState *spapr)
184653018216SPaolo Bonzini {
18473e80f690SMarkus Armbruster     DeviceState *dev = qdev_new("spapr-nvram");
18483978b863SPaolo Bonzini     DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
184953018216SPaolo Bonzini 
18503978b863SPaolo Bonzini     if (dinfo) {
1851934df912SMarkus Armbruster         qdev_prop_set_drive_err(dev, "drive", blk_by_legacy_dinfo(dinfo),
18526231a6daSMarkus Armbruster                                 &error_fatal);
185353018216SPaolo Bonzini     }
185453018216SPaolo Bonzini 
18553e80f690SMarkus Armbruster     qdev_realize_and_unref(dev, &spapr->vio_bus->bus, &error_fatal);
185653018216SPaolo Bonzini 
1857ce2918cbSDavid Gibson     spapr->nvram = (struct SpaprNvram *)dev;
185853018216SPaolo Bonzini }
185953018216SPaolo Bonzini 
spapr_rtc_create(SpaprMachineState * spapr)1860ce2918cbSDavid Gibson static void spapr_rtc_create(SpaprMachineState *spapr)
186128df36a1SDavid Gibson {
18629fc7fc4dSMarkus Armbruster     object_initialize_child_with_props(OBJECT(spapr), "rtc", &spapr->rtc,
18639fc7fc4dSMarkus Armbruster                                        sizeof(spapr->rtc), TYPE_SPAPR_RTC,
1864f6d4dca8SThomas Huth                                        &error_fatal, NULL);
1865ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(&spapr->rtc), NULL, &error_fatal);
1866147ff807SCédric Le Goater     object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc),
1867d2623129SMarkus Armbruster                               "date");
186828df36a1SDavid Gibson }
186928df36a1SDavid Gibson 
187053018216SPaolo Bonzini /* Returns whether we want to use VGA or not */
spapr_vga_init(PCIBus * pci_bus,Error ** errp)187114c6a894SDavid Gibson static bool spapr_vga_init(PCIBus *pci_bus, Error **errp)
187253018216SPaolo Bonzini {
1873f9bcb2d6SGautam Agrawal     vga_interface_created = true;
187453018216SPaolo Bonzini     switch (vga_interface_type) {
187553018216SPaolo Bonzini     case VGA_NONE:
18767effdaa3SMark Wu         return false;
18777effdaa3SMark Wu     case VGA_DEVICE:
18787effdaa3SMark Wu         return true;
187953018216SPaolo Bonzini     case VGA_STD:
1880b798c190SBenjamin Herrenschmidt     case VGA_VIRTIO:
18816e66d0c6SThomas Huth     case VGA_CIRRUS:
188253018216SPaolo Bonzini         return pci_vga_init(pci_bus) != NULL;
188353018216SPaolo Bonzini     default:
188414c6a894SDavid Gibson         error_setg(errp,
188514c6a894SDavid Gibson                    "Unsupported VGA mode, only -vga std or -vga virtio is supported");
188614c6a894SDavid Gibson         return false;
188753018216SPaolo Bonzini     }
188853018216SPaolo Bonzini }
188953018216SPaolo Bonzini 
spapr_pre_load(void * opaque)18904e5fe368SSuraj Jitindar Singh static int spapr_pre_load(void *opaque)
18914e5fe368SSuraj Jitindar Singh {
18924e5fe368SSuraj Jitindar Singh     int rc;
18934e5fe368SSuraj Jitindar Singh 
18944e5fe368SSuraj Jitindar Singh     rc = spapr_caps_pre_load(opaque);
18954e5fe368SSuraj Jitindar Singh     if (rc) {
18964e5fe368SSuraj Jitindar Singh         return rc;
18974e5fe368SSuraj Jitindar Singh     }
18984e5fe368SSuraj Jitindar Singh 
18994e5fe368SSuraj Jitindar Singh     return 0;
19004e5fe368SSuraj Jitindar Singh }
19014e5fe368SSuraj Jitindar Singh 
spapr_post_load(void * opaque,int version_id)1902880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id)
1903880ae7deSDavid Gibson {
1904ce2918cbSDavid Gibson     SpaprMachineState *spapr = (SpaprMachineState *)opaque;
1905880ae7deSDavid Gibson     int err = 0;
1906880ae7deSDavid Gibson 
1907be85537dSDavid Gibson     err = spapr_caps_post_migration(spapr);
1908be85537dSDavid Gibson     if (err) {
1909be85537dSDavid Gibson         return err;
1910be85537dSDavid Gibson     }
1911be85537dSDavid Gibson 
1912e502202cSCédric Le Goater     /*
1913e502202cSCédric Le Goater      * In earlier versions, there was no separate qdev for the PAPR
1914880ae7deSDavid Gibson      * RTC, so the RTC offset was stored directly in sPAPREnvironment.
1915880ae7deSDavid Gibson      * So when migrating from those versions, poke the incoming offset
1916e502202cSCédric Le Goater      * value into the RTC device
1917e502202cSCédric Le Goater      */
1918880ae7deSDavid Gibson     if (version_id < 3) {
1919147ff807SCédric Le Goater         err = spapr_rtc_import_offset(&spapr->rtc, spapr->rtc_offset);
1920e502202cSCédric Le Goater         if (err) {
1921e502202cSCédric Le Goater             return err;
1922e502202cSCédric Le Goater         }
1923880ae7deSDavid Gibson     }
1924880ae7deSDavid Gibson 
19250c86b2dfSLaurent Vivier     if (kvm_enabled() && spapr->patb_entry) {
1926d39c90f5SBharata B Rao         PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
192779825f4dSBenjamin Herrenschmidt         bool radix = !!(spapr->patb_entry & PATE1_GR);
1928d39c90f5SBharata B Rao         bool gtse = !!(cpu->env.spr[SPR_LPCR] & LPCR_GTSE);
1929d39c90f5SBharata B Rao 
193000fd075eSBenjamin Herrenschmidt         /*
193100fd075eSBenjamin Herrenschmidt          * Update LPCR:HR and UPRT as they may not be set properly in
193200fd075eSBenjamin Herrenschmidt          * the stream
193300fd075eSBenjamin Herrenschmidt          */
193400fd075eSBenjamin Herrenschmidt         spapr_set_all_lpcrs(radix ? (LPCR_HR | LPCR_UPRT) : 0,
193500fd075eSBenjamin Herrenschmidt                             LPCR_HR | LPCR_UPRT);
193600fd075eSBenjamin Herrenschmidt 
1937d39c90f5SBharata B Rao         err = kvmppc_configure_v3_mmu(cpu, radix, gtse, spapr->patb_entry);
1938d39c90f5SBharata B Rao         if (err) {
1939d39c90f5SBharata B Rao             error_report("Process table config unsupported by the host");
1940d39c90f5SBharata B Rao             return -EINVAL;
1941d39c90f5SBharata B Rao         }
1942d39c90f5SBharata B Rao     }
1943d39c90f5SBharata B Rao 
19441c53b06cSCédric Le Goater     err = spapr_irq_post_load(spapr, version_id);
19451c53b06cSCédric Le Goater     if (err) {
19461c53b06cSCédric Le Goater         return err;
19471c53b06cSCédric Le Goater     }
19481c53b06cSCédric Le Goater 
1949880ae7deSDavid Gibson     return err;
1950880ae7deSDavid Gibson }
1951880ae7deSDavid Gibson 
spapr_pre_save(void * opaque)19524e5fe368SSuraj Jitindar Singh static int spapr_pre_save(void *opaque)
19534e5fe368SSuraj Jitindar Singh {
19544e5fe368SSuraj Jitindar Singh     int rc;
19554e5fe368SSuraj Jitindar Singh 
19564e5fe368SSuraj Jitindar Singh     rc = spapr_caps_pre_save(opaque);
19574e5fe368SSuraj Jitindar Singh     if (rc) {
19584e5fe368SSuraj Jitindar Singh         return rc;
19594e5fe368SSuraj Jitindar Singh     }
19604e5fe368SSuraj Jitindar Singh 
19614e5fe368SSuraj Jitindar Singh     return 0;
19624e5fe368SSuraj Jitindar Singh }
19634e5fe368SSuraj Jitindar Singh 
version_before_3(void * opaque,int version_id)1964880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id)
1965880ae7deSDavid Gibson {
1966880ae7deSDavid Gibson     return version_id < 3;
1967880ae7deSDavid Gibson }
1968880ae7deSDavid Gibson 
spapr_pending_events_needed(void * opaque)1969fd38804bSDaniel Henrique Barboza static bool spapr_pending_events_needed(void *opaque)
1970fd38804bSDaniel Henrique Barboza {
1971ce2918cbSDavid Gibson     SpaprMachineState *spapr = (SpaprMachineState *)opaque;
1972fd38804bSDaniel Henrique Barboza     return !QTAILQ_EMPTY(&spapr->pending_events);
1973fd38804bSDaniel Henrique Barboza }
1974fd38804bSDaniel Henrique Barboza 
1975fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_event_entry = {
1976fd38804bSDaniel Henrique Barboza     .name = "spapr_event_log_entry",
1977fd38804bSDaniel Henrique Barboza     .version_id = 1,
1978fd38804bSDaniel Henrique Barboza     .minimum_version_id = 1,
1979078ddbc9SRichard Henderson     .fields = (const VMStateField[]) {
1980ce2918cbSDavid Gibson         VMSTATE_UINT32(summary, SpaprEventLogEntry),
1981ce2918cbSDavid Gibson         VMSTATE_UINT32(extended_length, SpaprEventLogEntry),
1982ce2918cbSDavid Gibson         VMSTATE_VBUFFER_ALLOC_UINT32(extended_log, SpaprEventLogEntry, 0,
19835341258eSDavid Gibson                                      NULL, extended_length),
1984fd38804bSDaniel Henrique Barboza         VMSTATE_END_OF_LIST()
1985fd38804bSDaniel Henrique Barboza     },
1986fd38804bSDaniel Henrique Barboza };
1987fd38804bSDaniel Henrique Barboza 
1988fd38804bSDaniel Henrique Barboza static const VMStateDescription vmstate_spapr_pending_events = {
1989fd38804bSDaniel Henrique Barboza     .name = "spapr_pending_events",
1990fd38804bSDaniel Henrique Barboza     .version_id = 1,
1991fd38804bSDaniel Henrique Barboza     .minimum_version_id = 1,
1992fd38804bSDaniel Henrique Barboza     .needed = spapr_pending_events_needed,
1993078ddbc9SRichard Henderson     .fields = (const VMStateField[]) {
1994ce2918cbSDavid Gibson         VMSTATE_QTAILQ_V(pending_events, SpaprMachineState, 1,
1995ce2918cbSDavid Gibson                          vmstate_spapr_event_entry, SpaprEventLogEntry, next),
1996fd38804bSDaniel Henrique Barboza         VMSTATE_END_OF_LIST()
1997fd38804bSDaniel Henrique Barboza     },
1998fd38804bSDaniel Henrique Barboza };
1999fd38804bSDaniel Henrique Barboza 
spapr_ov5_cas_needed(void * opaque)200062ef3760SMichael Roth static bool spapr_ov5_cas_needed(void *opaque)
200162ef3760SMichael Roth {
2002ce2918cbSDavid Gibson     SpaprMachineState *spapr = opaque;
2003ce2918cbSDavid Gibson     SpaprOptionVector *ov5_mask = spapr_ovec_new();
200462ef3760SMichael Roth     bool cas_needed;
200562ef3760SMichael Roth 
2006ce2918cbSDavid Gibson     /* Prior to the introduction of SpaprOptionVector, we had two option
200762ef3760SMichael Roth      * vectors we dealt with: OV5_FORM1_AFFINITY, and OV5_DRCONF_MEMORY.
200862ef3760SMichael Roth      * Both of these options encode machine topology into the device-tree
200962ef3760SMichael Roth      * in such a way that the now-booted OS should still be able to interact
201062ef3760SMichael Roth      * appropriately with QEMU regardless of what options were actually
201162ef3760SMichael Roth      * negotiatied on the source side.
201262ef3760SMichael Roth      *
201362ef3760SMichael Roth      * As such, we can avoid migrating the CAS-negotiated options if these
201462ef3760SMichael Roth      * are the only options available on the current machine/platform.
201562ef3760SMichael Roth      * Since these are the only options available for pseries-2.7 and
201662ef3760SMichael Roth      * earlier, this allows us to maintain old->new/new->old migration
201762ef3760SMichael Roth      * compatibility.
201862ef3760SMichael Roth      *
201962ef3760SMichael Roth      * For QEMU 2.8+, there are additional CAS-negotiatable options available
202062ef3760SMichael Roth      * via default pseries-2.8 machines and explicit command-line parameters.
202162ef3760SMichael Roth      * Some of these options, like OV5_HP_EVT, *do* require QEMU to be aware
202262ef3760SMichael Roth      * of the actual CAS-negotiated values to continue working properly. For
202362ef3760SMichael Roth      * example, availability of memory unplug depends on knowing whether
202462ef3760SMichael Roth      * OV5_HP_EVT was negotiated via CAS.
202562ef3760SMichael Roth      *
202662ef3760SMichael Roth      * Thus, for any cases where the set of available CAS-negotiatable
202762ef3760SMichael Roth      * options extends beyond OV5_FORM1_AFFINITY and OV5_DRCONF_MEMORY, we
2028aef19c04SGreg Kurz      * include the CAS-negotiated options in the migration stream, unless
2029aef19c04SGreg Kurz      * if they affect boot time behaviour only.
203062ef3760SMichael Roth      */
203162ef3760SMichael Roth     spapr_ovec_set(ov5_mask, OV5_FORM1_AFFINITY);
203262ef3760SMichael Roth     spapr_ovec_set(ov5_mask, OV5_DRCONF_MEMORY);
2033aef19c04SGreg Kurz     spapr_ovec_set(ov5_mask, OV5_DRMEM_V2);
203462ef3760SMichael Roth 
2035d1d32d62SDavid Gibson     /* We need extra information if we have any bits outside the mask
2036d1d32d62SDavid Gibson      * defined above */
2037d1d32d62SDavid Gibson     cas_needed = !spapr_ovec_subset(spapr->ov5, ov5_mask);
203862ef3760SMichael Roth 
203962ef3760SMichael Roth     spapr_ovec_cleanup(ov5_mask);
204062ef3760SMichael Roth 
204162ef3760SMichael Roth     return cas_needed;
204262ef3760SMichael Roth }
204362ef3760SMichael Roth 
204462ef3760SMichael Roth static const VMStateDescription vmstate_spapr_ov5_cas = {
204562ef3760SMichael Roth     .name = "spapr_option_vector_ov5_cas",
204662ef3760SMichael Roth     .version_id = 1,
204762ef3760SMichael Roth     .minimum_version_id = 1,
204862ef3760SMichael Roth     .needed = spapr_ov5_cas_needed,
2049078ddbc9SRichard Henderson     .fields = (const VMStateField[]) {
2050ce2918cbSDavid Gibson         VMSTATE_STRUCT_POINTER_V(ov5_cas, SpaprMachineState, 1,
2051ce2918cbSDavid Gibson                                  vmstate_spapr_ovec, SpaprOptionVector),
205262ef3760SMichael Roth         VMSTATE_END_OF_LIST()
205362ef3760SMichael Roth     },
205462ef3760SMichael Roth };
205562ef3760SMichael Roth 
spapr_patb_entry_needed(void * opaque)20569861bb3eSSuraj Jitindar Singh static bool spapr_patb_entry_needed(void *opaque)
20579861bb3eSSuraj Jitindar Singh {
2058ce2918cbSDavid Gibson     SpaprMachineState *spapr = opaque;
20599861bb3eSSuraj Jitindar Singh 
20609861bb3eSSuraj Jitindar Singh     return !!spapr->patb_entry;
20619861bb3eSSuraj Jitindar Singh }
20629861bb3eSSuraj Jitindar Singh 
20639861bb3eSSuraj Jitindar Singh static const VMStateDescription vmstate_spapr_patb_entry = {
20649861bb3eSSuraj Jitindar Singh     .name = "spapr_patb_entry",
20659861bb3eSSuraj Jitindar Singh     .version_id = 1,
20669861bb3eSSuraj Jitindar Singh     .minimum_version_id = 1,
20679861bb3eSSuraj Jitindar Singh     .needed = spapr_patb_entry_needed,
2068078ddbc9SRichard Henderson     .fields = (const VMStateField[]) {
2069ce2918cbSDavid Gibson         VMSTATE_UINT64(patb_entry, SpaprMachineState),
20709861bb3eSSuraj Jitindar Singh         VMSTATE_END_OF_LIST()
20719861bb3eSSuraj Jitindar Singh     },
20729861bb3eSSuraj Jitindar Singh };
20739861bb3eSSuraj Jitindar Singh 
spapr_irq_map_needed(void * opaque)207482cffa2eSCédric Le Goater static bool spapr_irq_map_needed(void *opaque)
207582cffa2eSCédric Le Goater {
2076ce2918cbSDavid Gibson     SpaprMachineState *spapr = opaque;
207782cffa2eSCédric Le Goater 
207882cffa2eSCédric Le Goater     return spapr->irq_map && !bitmap_empty(spapr->irq_map, spapr->irq_map_nr);
207982cffa2eSCédric Le Goater }
208082cffa2eSCédric Le Goater 
208182cffa2eSCédric Le Goater static const VMStateDescription vmstate_spapr_irq_map = {
208282cffa2eSCédric Le Goater     .name = "spapr_irq_map",
208382cffa2eSCédric Le Goater     .version_id = 1,
208482cffa2eSCédric Le Goater     .minimum_version_id = 1,
208582cffa2eSCédric Le Goater     .needed = spapr_irq_map_needed,
2086078ddbc9SRichard Henderson     .fields = (const VMStateField[]) {
2087ce2918cbSDavid Gibson         VMSTATE_BITMAP(irq_map, SpaprMachineState, 0, irq_map_nr),
208882cffa2eSCédric Le Goater         VMSTATE_END_OF_LIST()
208982cffa2eSCédric Le Goater     },
209082cffa2eSCédric Le Goater };
209182cffa2eSCédric Le Goater 
spapr_dtb_needed(void * opaque)2092fea35ca4SAlexey Kardashevskiy static bool spapr_dtb_needed(void *opaque)
2093fea35ca4SAlexey Kardashevskiy {
2094ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(opaque);
2095fea35ca4SAlexey Kardashevskiy 
2096fea35ca4SAlexey Kardashevskiy     return smc->update_dt_enabled;
2097fea35ca4SAlexey Kardashevskiy }
2098fea35ca4SAlexey Kardashevskiy 
spapr_dtb_pre_load(void * opaque)2099fea35ca4SAlexey Kardashevskiy static int spapr_dtb_pre_load(void *opaque)
2100fea35ca4SAlexey Kardashevskiy {
2101ce2918cbSDavid Gibson     SpaprMachineState *spapr = (SpaprMachineState *)opaque;
2102fea35ca4SAlexey Kardashevskiy 
2103fea35ca4SAlexey Kardashevskiy     g_free(spapr->fdt_blob);
2104fea35ca4SAlexey Kardashevskiy     spapr->fdt_blob = NULL;
2105fea35ca4SAlexey Kardashevskiy     spapr->fdt_size = 0;
2106fea35ca4SAlexey Kardashevskiy 
2107fea35ca4SAlexey Kardashevskiy     return 0;
2108fea35ca4SAlexey Kardashevskiy }
2109fea35ca4SAlexey Kardashevskiy 
2110fea35ca4SAlexey Kardashevskiy static const VMStateDescription vmstate_spapr_dtb = {
2111fea35ca4SAlexey Kardashevskiy     .name = "spapr_dtb",
2112fea35ca4SAlexey Kardashevskiy     .version_id = 1,
2113fea35ca4SAlexey Kardashevskiy     .minimum_version_id = 1,
2114fea35ca4SAlexey Kardashevskiy     .needed = spapr_dtb_needed,
2115fea35ca4SAlexey Kardashevskiy     .pre_load = spapr_dtb_pre_load,
2116078ddbc9SRichard Henderson     .fields = (const VMStateField[]) {
2117ce2918cbSDavid Gibson         VMSTATE_UINT32(fdt_initial_size, SpaprMachineState),
2118ce2918cbSDavid Gibson         VMSTATE_UINT32(fdt_size, SpaprMachineState),
2119ce2918cbSDavid Gibson         VMSTATE_VBUFFER_ALLOC_UINT32(fdt_blob, SpaprMachineState, 0, NULL,
2120fea35ca4SAlexey Kardashevskiy                                      fdt_size),
2121fea35ca4SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
2122fea35ca4SAlexey Kardashevskiy     },
2123fea35ca4SAlexey Kardashevskiy };
2124fea35ca4SAlexey Kardashevskiy 
spapr_fwnmi_needed(void * opaque)21252500fb42SAravinda Prasad static bool spapr_fwnmi_needed(void *opaque)
21262500fb42SAravinda Prasad {
21272500fb42SAravinda Prasad     SpaprMachineState *spapr = (SpaprMachineState *)opaque;
21282500fb42SAravinda Prasad 
21298af7e1feSNicholas Piggin     return spapr->fwnmi_machine_check_addr != -1;
21302500fb42SAravinda Prasad }
21312500fb42SAravinda Prasad 
spapr_fwnmi_pre_save(void * opaque)21322500fb42SAravinda Prasad static int spapr_fwnmi_pre_save(void *opaque)
21332500fb42SAravinda Prasad {
21342500fb42SAravinda Prasad     SpaprMachineState *spapr = (SpaprMachineState *)opaque;
21352500fb42SAravinda Prasad 
21362500fb42SAravinda Prasad     /*
21372500fb42SAravinda Prasad      * Check if machine check handling is in progress and print a
21382500fb42SAravinda Prasad      * warning message.
21392500fb42SAravinda Prasad      */
21408af7e1feSNicholas Piggin     if (spapr->fwnmi_machine_check_interlock != -1) {
21412500fb42SAravinda Prasad         warn_report("A machine check is being handled during migration. The"
21422500fb42SAravinda Prasad                 "handler may run and log hardware error on the destination");
21432500fb42SAravinda Prasad     }
21442500fb42SAravinda Prasad 
21452500fb42SAravinda Prasad     return 0;
21462500fb42SAravinda Prasad }
21472500fb42SAravinda Prasad 
21488af7e1feSNicholas Piggin static const VMStateDescription vmstate_spapr_fwnmi = {
21498af7e1feSNicholas Piggin     .name = "spapr_fwnmi",
21502500fb42SAravinda Prasad     .version_id = 1,
21512500fb42SAravinda Prasad     .minimum_version_id = 1,
21522500fb42SAravinda Prasad     .needed = spapr_fwnmi_needed,
21532500fb42SAravinda Prasad     .pre_save = spapr_fwnmi_pre_save,
2154078ddbc9SRichard Henderson     .fields = (const VMStateField[]) {
2155edfdbf9cSNicholas Piggin         VMSTATE_UINT64(fwnmi_system_reset_addr, SpaprMachineState),
21568af7e1feSNicholas Piggin         VMSTATE_UINT64(fwnmi_machine_check_addr, SpaprMachineState),
21578af7e1feSNicholas Piggin         VMSTATE_INT32(fwnmi_machine_check_interlock, SpaprMachineState),
21582500fb42SAravinda Prasad         VMSTATE_END_OF_LIST()
21592500fb42SAravinda Prasad     },
21602500fb42SAravinda Prasad };
21612500fb42SAravinda Prasad 
21624be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = {
21634be21d56SDavid Gibson     .name = "spapr",
2164880ae7deSDavid Gibson     .version_id = 3,
21654be21d56SDavid Gibson     .minimum_version_id = 1,
21664e5fe368SSuraj Jitindar Singh     .pre_load = spapr_pre_load,
2167880ae7deSDavid Gibson     .post_load = spapr_post_load,
21684e5fe368SSuraj Jitindar Singh     .pre_save = spapr_pre_save,
2169078ddbc9SRichard Henderson     .fields = (const VMStateField[]) {
2170880ae7deSDavid Gibson         /* used to be @next_irq */
2171880ae7deSDavid Gibson         VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4),
21724be21d56SDavid Gibson 
21734be21d56SDavid Gibson         /* RTC offset */
2174ce2918cbSDavid Gibson         VMSTATE_UINT64_TEST(rtc_offset, SpaprMachineState, version_before_3),
2175880ae7deSDavid Gibson 
2176ce2918cbSDavid Gibson         VMSTATE_PPC_TIMEBASE_V(tb, SpaprMachineState, 2),
21774be21d56SDavid Gibson         VMSTATE_END_OF_LIST()
21784be21d56SDavid Gibson     },
2179078ddbc9SRichard Henderson     .subsections = (const VMStateDescription * const []) {
218062ef3760SMichael Roth         &vmstate_spapr_ov5_cas,
21819861bb3eSSuraj Jitindar Singh         &vmstate_spapr_patb_entry,
2182fd38804bSDaniel Henrique Barboza         &vmstate_spapr_pending_events,
21834e5fe368SSuraj Jitindar Singh         &vmstate_spapr_cap_htm,
21844e5fe368SSuraj Jitindar Singh         &vmstate_spapr_cap_vsx,
21854e5fe368SSuraj Jitindar Singh         &vmstate_spapr_cap_dfp,
21868f38eaf8SSuraj Jitindar Singh         &vmstate_spapr_cap_cfpc,
218709114fd8SSuraj Jitindar Singh         &vmstate_spapr_cap_sbbc,
21884be8d4e7SSuraj Jitindar Singh         &vmstate_spapr_cap_ibs,
218964d4a534SDavid Gibson         &vmstate_spapr_cap_hpt_maxpagesize,
219082cffa2eSCédric Le Goater         &vmstate_spapr_irq_map,
2191b9a477b7SSuraj Jitindar Singh         &vmstate_spapr_cap_nested_kvm_hv,
2192fea35ca4SAlexey Kardashevskiy         &vmstate_spapr_dtb,
2193c982f5cfSSuraj Jitindar Singh         &vmstate_spapr_cap_large_decr,
21948ff43ee4SSuraj Jitindar Singh         &vmstate_spapr_cap_ccf_assist,
21959d953ce4SAravinda Prasad         &vmstate_spapr_cap_fwnmi,
21968af7e1feSNicholas Piggin         &vmstate_spapr_fwnmi,
219782123b75SBharata B Rao         &vmstate_spapr_cap_rpt_invalidate,
2198*1a7a31aeSNicholas Piggin         &vmstate_spapr_cap_ail_mode_3,
2199e1617b84SHarsh Prateek Bora         &vmstate_spapr_cap_nested_papr,
220062ef3760SMichael Roth         NULL
220162ef3760SMichael Roth     }
22024be21d56SDavid Gibson };
22034be21d56SDavid Gibson 
htab_save_setup(QEMUFile * f,void * opaque,Error ** errp)220401c3ac68SCédric Le Goater static int htab_save_setup(QEMUFile *f, void *opaque, Error **errp)
22054be21d56SDavid Gibson {
2206ce2918cbSDavid Gibson     SpaprMachineState *spapr = opaque;
22074be21d56SDavid Gibson 
22084be21d56SDavid Gibson     /* "Iteration" header */
22093a384297SBharata B Rao     if (!spapr->htab_shift) {
22103a384297SBharata B Rao         qemu_put_be32(f, -1);
22113a384297SBharata B Rao     } else {
22124be21d56SDavid Gibson         qemu_put_be32(f, spapr->htab_shift);
22133a384297SBharata B Rao     }
22144be21d56SDavid Gibson 
2215e68cb8b4SAlexey Kardashevskiy     if (spapr->htab) {
2216e68cb8b4SAlexey Kardashevskiy         spapr->htab_save_index = 0;
2217e68cb8b4SAlexey Kardashevskiy         spapr->htab_first_pass = true;
2218e68cb8b4SAlexey Kardashevskiy     } else {
22193a384297SBharata B Rao         if (spapr->htab_shift) {
2220e68cb8b4SAlexey Kardashevskiy             assert(kvm_enabled());
22214be21d56SDavid Gibson         }
22223a384297SBharata B Rao     }
22234be21d56SDavid Gibson 
2224e68cb8b4SAlexey Kardashevskiy 
2225e68cb8b4SAlexey Kardashevskiy     return 0;
2226e68cb8b4SAlexey Kardashevskiy }
22274be21d56SDavid Gibson 
htab_save_chunk(QEMUFile * f,SpaprMachineState * spapr,int chunkstart,int n_valid,int n_invalid)2228ce2918cbSDavid Gibson static void htab_save_chunk(QEMUFile *f, SpaprMachineState *spapr,
2229332f7721SGreg Kurz                             int chunkstart, int n_valid, int n_invalid)
2230332f7721SGreg Kurz {
2231332f7721SGreg Kurz     qemu_put_be32(f, chunkstart);
2232332f7721SGreg Kurz     qemu_put_be16(f, n_valid);
2233332f7721SGreg Kurz     qemu_put_be16(f, n_invalid);
2234332f7721SGreg Kurz     qemu_put_buffer(f, HPTE(spapr->htab, chunkstart),
2235332f7721SGreg Kurz                     HASH_PTE_SIZE_64 * n_valid);
2236332f7721SGreg Kurz }
2237332f7721SGreg Kurz 
htab_save_end_marker(QEMUFile * f)2238332f7721SGreg Kurz static void htab_save_end_marker(QEMUFile *f)
2239332f7721SGreg Kurz {
2240332f7721SGreg Kurz     qemu_put_be32(f, 0);
2241332f7721SGreg Kurz     qemu_put_be16(f, 0);
2242332f7721SGreg Kurz     qemu_put_be16(f, 0);
2243332f7721SGreg Kurz }
2244332f7721SGreg Kurz 
htab_save_first_pass(QEMUFile * f,SpaprMachineState * spapr,int64_t max_ns)2245ce2918cbSDavid Gibson static void htab_save_first_pass(QEMUFile *f, SpaprMachineState *spapr,
22464be21d56SDavid Gibson                                  int64_t max_ns)
22474be21d56SDavid Gibson {
2248378bc217SDavid Gibson     bool has_timeout = max_ns != -1;
22494be21d56SDavid Gibson     int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64;
22504be21d56SDavid Gibson     int index = spapr->htab_save_index;
2251bc72ad67SAlex Bligh     int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
22524be21d56SDavid Gibson 
22534be21d56SDavid Gibson     assert(spapr->htab_first_pass);
22544be21d56SDavid Gibson 
22554be21d56SDavid Gibson     do {
22564be21d56SDavid Gibson         int chunkstart;
22574be21d56SDavid Gibson 
22584be21d56SDavid Gibson         /* Consume invalid HPTEs */
22594be21d56SDavid Gibson         while ((index < htabslots)
22604be21d56SDavid Gibson                && !HPTE_VALID(HPTE(spapr->htab, index))) {
22614be21d56SDavid Gibson             CLEAN_HPTE(HPTE(spapr->htab, index));
226224ec2863SMarc-André Lureau             index++;
22634be21d56SDavid Gibson         }
22644be21d56SDavid Gibson 
22654be21d56SDavid Gibson         /* Consume valid HPTEs */
22664be21d56SDavid Gibson         chunkstart = index;
2267338c25b6SSamuel Mendoza-Jonas         while ((index < htabslots) && (index - chunkstart < USHRT_MAX)
22684be21d56SDavid Gibson                && HPTE_VALID(HPTE(spapr->htab, index))) {
22694be21d56SDavid Gibson             CLEAN_HPTE(HPTE(spapr->htab, index));
227024ec2863SMarc-André Lureau             index++;
22714be21d56SDavid Gibson         }
22724be21d56SDavid Gibson 
22734be21d56SDavid Gibson         if (index > chunkstart) {
22744be21d56SDavid Gibson             int n_valid = index - chunkstart;
22754be21d56SDavid Gibson 
2276332f7721SGreg Kurz             htab_save_chunk(f, spapr, chunkstart, n_valid, 0);
22774be21d56SDavid Gibson 
2278378bc217SDavid Gibson             if (has_timeout &&
2279378bc217SDavid Gibson                 (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) {
22804be21d56SDavid Gibson                 break;
22814be21d56SDavid Gibson             }
22824be21d56SDavid Gibson         }
2283e1fde0e0SJuan Quintela     } while ((index < htabslots) && !migration_rate_exceeded(f));
22844be21d56SDavid Gibson 
22854be21d56SDavid Gibson     if (index >= htabslots) {
22864be21d56SDavid Gibson         assert(index == htabslots);
22874be21d56SDavid Gibson         index = 0;
22884be21d56SDavid Gibson         spapr->htab_first_pass = false;
22894be21d56SDavid Gibson     }
22904be21d56SDavid Gibson     spapr->htab_save_index = index;
22914be21d56SDavid Gibson }
22924be21d56SDavid Gibson 
htab_save_later_pass(QEMUFile * f,SpaprMachineState * spapr,int64_t max_ns)2293ce2918cbSDavid Gibson static int htab_save_later_pass(QEMUFile *f, SpaprMachineState *spapr,
22944be21d56SDavid Gibson                                 int64_t max_ns)
22954be21d56SDavid Gibson {
22964be21d56SDavid Gibson     bool final = max_ns < 0;
22974be21d56SDavid Gibson     int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64;
22984be21d56SDavid Gibson     int examined = 0, sent = 0;
22994be21d56SDavid Gibson     int index = spapr->htab_save_index;
2300bc72ad67SAlex Bligh     int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
23014be21d56SDavid Gibson 
23024be21d56SDavid Gibson     assert(!spapr->htab_first_pass);
23034be21d56SDavid Gibson 
23044be21d56SDavid Gibson     do {
23054be21d56SDavid Gibson         int chunkstart, invalidstart;
23064be21d56SDavid Gibson 
23074be21d56SDavid Gibson         /* Consume non-dirty HPTEs */
23084be21d56SDavid Gibson         while ((index < htabslots)
23094be21d56SDavid Gibson                && !HPTE_DIRTY(HPTE(spapr->htab, index))) {
23104be21d56SDavid Gibson             index++;
23114be21d56SDavid Gibson             examined++;
23124be21d56SDavid Gibson         }
23134be21d56SDavid Gibson 
23144be21d56SDavid Gibson         chunkstart = index;
23154be21d56SDavid Gibson         /* Consume valid dirty HPTEs */
2316338c25b6SSamuel Mendoza-Jonas         while ((index < htabslots) && (index - chunkstart < USHRT_MAX)
23174be21d56SDavid Gibson                && HPTE_DIRTY(HPTE(spapr->htab, index))
23184be21d56SDavid Gibson                && HPTE_VALID(HPTE(spapr->htab, index))) {
23194be21d56SDavid Gibson             CLEAN_HPTE(HPTE(spapr->htab, index));
23204be21d56SDavid Gibson             index++;
23214be21d56SDavid Gibson             examined++;
23224be21d56SDavid Gibson         }
23234be21d56SDavid Gibson 
23244be21d56SDavid Gibson         invalidstart = index;
23254be21d56SDavid Gibson         /* Consume invalid dirty HPTEs */
2326338c25b6SSamuel Mendoza-Jonas         while ((index < htabslots) && (index - invalidstart < USHRT_MAX)
23274be21d56SDavid Gibson                && HPTE_DIRTY(HPTE(spapr->htab, index))
23284be21d56SDavid Gibson                && !HPTE_VALID(HPTE(spapr->htab, index))) {
23294be21d56SDavid Gibson             CLEAN_HPTE(HPTE(spapr->htab, index));
23304be21d56SDavid Gibson             index++;
23314be21d56SDavid Gibson             examined++;
23324be21d56SDavid Gibson         }
23334be21d56SDavid Gibson 
23344be21d56SDavid Gibson         if (index > chunkstart) {
23354be21d56SDavid Gibson             int n_valid = invalidstart - chunkstart;
23364be21d56SDavid Gibson             int n_invalid = index - invalidstart;
23374be21d56SDavid Gibson 
2338332f7721SGreg Kurz             htab_save_chunk(f, spapr, chunkstart, n_valid, n_invalid);
23394be21d56SDavid Gibson             sent += index - chunkstart;
23404be21d56SDavid Gibson 
2341bc72ad67SAlex Bligh             if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) {
23424be21d56SDavid Gibson                 break;
23434be21d56SDavid Gibson             }
23444be21d56SDavid Gibson         }
23454be21d56SDavid Gibson 
23464be21d56SDavid Gibson         if (examined >= htabslots) {
23474be21d56SDavid Gibson             break;
23484be21d56SDavid Gibson         }
23494be21d56SDavid Gibson 
23504be21d56SDavid Gibson         if (index >= htabslots) {
23514be21d56SDavid Gibson             assert(index == htabslots);
23524be21d56SDavid Gibson             index = 0;
23534be21d56SDavid Gibson         }
2354e1fde0e0SJuan Quintela     } while ((examined < htabslots) && (!migration_rate_exceeded(f) || final));
23554be21d56SDavid Gibson 
23564be21d56SDavid Gibson     if (index >= htabslots) {
23574be21d56SDavid Gibson         assert(index == htabslots);
23584be21d56SDavid Gibson         index = 0;
23594be21d56SDavid Gibson     }
23604be21d56SDavid Gibson 
23614be21d56SDavid Gibson     spapr->htab_save_index = index;
23624be21d56SDavid Gibson 
2363e68cb8b4SAlexey Kardashevskiy     return (examined >= htabslots) && (sent == 0) ? 1 : 0;
23644be21d56SDavid Gibson }
23654be21d56SDavid Gibson 
2366e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS    5000000 /* 5 ms */
2367e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE    2048
2368e68cb8b4SAlexey Kardashevskiy 
htab_save_iterate(QEMUFile * f,void * opaque)23694be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque)
23704be21d56SDavid Gibson {
2371ce2918cbSDavid Gibson     SpaprMachineState *spapr = opaque;
2372715c5407SDavid Gibson     int fd;
2373e68cb8b4SAlexey Kardashevskiy     int rc = 0;
23744be21d56SDavid Gibson 
23754be21d56SDavid Gibson     /* Iteration header */
23763a384297SBharata B Rao     if (!spapr->htab_shift) {
23773a384297SBharata B Rao         qemu_put_be32(f, -1);
2378e8cd4247SLaurent Vivier         return 1;
23793a384297SBharata B Rao     } else {
23804be21d56SDavid Gibson         qemu_put_be32(f, 0);
23813a384297SBharata B Rao     }
23824be21d56SDavid Gibson 
2383e68cb8b4SAlexey Kardashevskiy     if (!spapr->htab) {
2384e68cb8b4SAlexey Kardashevskiy         assert(kvm_enabled());
2385e68cb8b4SAlexey Kardashevskiy 
2386715c5407SDavid Gibson         fd = get_htab_fd(spapr);
2387715c5407SDavid Gibson         if (fd < 0) {
2388715c5407SDavid Gibson             return fd;
238901a57972SSamuel Mendoza-Jonas         }
239001a57972SSamuel Mendoza-Jonas 
2391715c5407SDavid Gibson         rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS);
2392e68cb8b4SAlexey Kardashevskiy         if (rc < 0) {
2393e68cb8b4SAlexey Kardashevskiy             return rc;
2394e68cb8b4SAlexey Kardashevskiy         }
2395e68cb8b4SAlexey Kardashevskiy     } else  if (spapr->htab_first_pass) {
23964be21d56SDavid Gibson         htab_save_first_pass(f, spapr, MAX_ITERATION_NS);
23974be21d56SDavid Gibson     } else {
2398e68cb8b4SAlexey Kardashevskiy         rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS);
23994be21d56SDavid Gibson     }
24004be21d56SDavid Gibson 
2401332f7721SGreg Kurz     htab_save_end_marker(f);
24024be21d56SDavid Gibson 
2403e68cb8b4SAlexey Kardashevskiy     return rc;
24044be21d56SDavid Gibson }
24054be21d56SDavid Gibson 
htab_save_complete(QEMUFile * f,void * opaque)24064be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque)
24074be21d56SDavid Gibson {
2408ce2918cbSDavid Gibson     SpaprMachineState *spapr = opaque;
2409715c5407SDavid Gibson     int fd;
24104be21d56SDavid Gibson 
24114be21d56SDavid Gibson     /* Iteration header */
24123a384297SBharata B Rao     if (!spapr->htab_shift) {
24133a384297SBharata B Rao         qemu_put_be32(f, -1);
24143a384297SBharata B Rao         return 0;
24153a384297SBharata B Rao     } else {
24164be21d56SDavid Gibson         qemu_put_be32(f, 0);
24173a384297SBharata B Rao     }
24184be21d56SDavid Gibson 
2419e68cb8b4SAlexey Kardashevskiy     if (!spapr->htab) {
2420e68cb8b4SAlexey Kardashevskiy         int rc;
2421e68cb8b4SAlexey Kardashevskiy 
2422e68cb8b4SAlexey Kardashevskiy         assert(kvm_enabled());
2423e68cb8b4SAlexey Kardashevskiy 
2424715c5407SDavid Gibson         fd = get_htab_fd(spapr);
2425715c5407SDavid Gibson         if (fd < 0) {
2426715c5407SDavid Gibson             return fd;
242701a57972SSamuel Mendoza-Jonas         }
242801a57972SSamuel Mendoza-Jonas 
2429715c5407SDavid Gibson         rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1);
2430e68cb8b4SAlexey Kardashevskiy         if (rc < 0) {
2431e68cb8b4SAlexey Kardashevskiy             return rc;
2432e68cb8b4SAlexey Kardashevskiy         }
2433e68cb8b4SAlexey Kardashevskiy     } else {
2434378bc217SDavid Gibson         if (spapr->htab_first_pass) {
2435378bc217SDavid Gibson             htab_save_first_pass(f, spapr, -1);
2436378bc217SDavid Gibson         }
24374be21d56SDavid Gibson         htab_save_later_pass(f, spapr, -1);
2438e68cb8b4SAlexey Kardashevskiy     }
24394be21d56SDavid Gibson 
24404be21d56SDavid Gibson     /* End marker */
2441332f7721SGreg Kurz     htab_save_end_marker(f);
24424be21d56SDavid Gibson 
24434be21d56SDavid Gibson     return 0;
24444be21d56SDavid Gibson }
24454be21d56SDavid Gibson 
htab_load(QEMUFile * f,void * opaque,int version_id)24464be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id)
24474be21d56SDavid Gibson {
2448ce2918cbSDavid Gibson     SpaprMachineState *spapr = opaque;
24494be21d56SDavid Gibson     uint32_t section_hdr;
2450e68cb8b4SAlexey Kardashevskiy     int fd = -1;
245114b0d748SGreg Kurz     Error *local_err = NULL;
24524be21d56SDavid Gibson 
24534be21d56SDavid Gibson     if (version_id < 1 || version_id > 1) {
245498a5d100SDavid Gibson         error_report("htab_load() bad version");
24554be21d56SDavid Gibson         return -EINVAL;
24564be21d56SDavid Gibson     }
24574be21d56SDavid Gibson 
24584be21d56SDavid Gibson     section_hdr = qemu_get_be32(f);
24594be21d56SDavid Gibson 
24603a384297SBharata B Rao     if (section_hdr == -1) {
24613a384297SBharata B Rao         spapr_free_hpt(spapr);
24623a384297SBharata B Rao         return 0;
24633a384297SBharata B Rao     }
24643a384297SBharata B Rao 
24654be21d56SDavid Gibson     if (section_hdr) {
2466a4e3a7c0SGreg Kurz         int ret;
2467a4e3a7c0SGreg Kurz 
2468c5f54f3eSDavid Gibson         /* First section gives the htab size */
2469a4e3a7c0SGreg Kurz         ret = spapr_reallocate_hpt(spapr, section_hdr, &local_err);
2470a4e3a7c0SGreg Kurz         if (ret < 0) {
2471c5f54f3eSDavid Gibson             error_report_err(local_err);
2472a4e3a7c0SGreg Kurz             return ret;
24734be21d56SDavid Gibson         }
24744be21d56SDavid Gibson         return 0;
24754be21d56SDavid Gibson     }
24764be21d56SDavid Gibson 
2477e68cb8b4SAlexey Kardashevskiy     if (!spapr->htab) {
2478e68cb8b4SAlexey Kardashevskiy         assert(kvm_enabled());
2479e68cb8b4SAlexey Kardashevskiy 
248014b0d748SGreg Kurz         fd = kvmppc_get_htab_fd(true, 0, &local_err);
2481e68cb8b4SAlexey Kardashevskiy         if (fd < 0) {
248214b0d748SGreg Kurz             error_report_err(local_err);
248382be8e73SGreg Kurz             return fd;
2484e68cb8b4SAlexey Kardashevskiy         }
2485e68cb8b4SAlexey Kardashevskiy     }
2486e68cb8b4SAlexey Kardashevskiy 
24874be21d56SDavid Gibson     while (true) {
24884be21d56SDavid Gibson         uint32_t index;
24894be21d56SDavid Gibson         uint16_t n_valid, n_invalid;
24904be21d56SDavid Gibson 
24914be21d56SDavid Gibson         index = qemu_get_be32(f);
24924be21d56SDavid Gibson         n_valid = qemu_get_be16(f);
24934be21d56SDavid Gibson         n_invalid = qemu_get_be16(f);
24944be21d56SDavid Gibson 
24954be21d56SDavid Gibson         if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) {
24964be21d56SDavid Gibson             /* End of Stream */
24974be21d56SDavid Gibson             break;
24984be21d56SDavid Gibson         }
24994be21d56SDavid Gibson 
2500e68cb8b4SAlexey Kardashevskiy         if ((index + n_valid + n_invalid) >
25014be21d56SDavid Gibson             (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) {
25024be21d56SDavid Gibson             /* Bad index in stream */
250398a5d100SDavid Gibson             error_report(
250498a5d100SDavid Gibson                 "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)",
250598a5d100SDavid Gibson                 index, n_valid, n_invalid, spapr->htab_shift);
25064be21d56SDavid Gibson             return -EINVAL;
25074be21d56SDavid Gibson         }
25084be21d56SDavid Gibson 
2509e68cb8b4SAlexey Kardashevskiy         if (spapr->htab) {
25104be21d56SDavid Gibson             if (n_valid) {
25114be21d56SDavid Gibson                 qemu_get_buffer(f, HPTE(spapr->htab, index),
25124be21d56SDavid Gibson                                 HASH_PTE_SIZE_64 * n_valid);
25134be21d56SDavid Gibson             }
25144be21d56SDavid Gibson             if (n_invalid) {
25154be21d56SDavid Gibson                 memset(HPTE(spapr->htab, index + n_valid), 0,
25164be21d56SDavid Gibson                        HASH_PTE_SIZE_64 * n_invalid);
25174be21d56SDavid Gibson             }
2518e68cb8b4SAlexey Kardashevskiy         } else {
2519e68cb8b4SAlexey Kardashevskiy             int rc;
2520e68cb8b4SAlexey Kardashevskiy 
2521e68cb8b4SAlexey Kardashevskiy             assert(fd >= 0);
2522e68cb8b4SAlexey Kardashevskiy 
25230a06e4d6SGreg Kurz             rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid,
25240a06e4d6SGreg Kurz                                         &local_err);
2525e68cb8b4SAlexey Kardashevskiy             if (rc < 0) {
25260a06e4d6SGreg Kurz                 error_report_err(local_err);
2527e68cb8b4SAlexey Kardashevskiy                 return rc;
2528e68cb8b4SAlexey Kardashevskiy             }
2529e68cb8b4SAlexey Kardashevskiy         }
2530e68cb8b4SAlexey Kardashevskiy     }
2531e68cb8b4SAlexey Kardashevskiy 
2532e68cb8b4SAlexey Kardashevskiy     if (!spapr->htab) {
2533e68cb8b4SAlexey Kardashevskiy         assert(fd >= 0);
2534e68cb8b4SAlexey Kardashevskiy         close(fd);
25354be21d56SDavid Gibson     }
25364be21d56SDavid Gibson 
25374be21d56SDavid Gibson     return 0;
25384be21d56SDavid Gibson }
25394be21d56SDavid Gibson 
htab_save_cleanup(void * opaque)254070f794fcSJuan Quintela static void htab_save_cleanup(void *opaque)
2541c573fc03SThomas Huth {
2542ce2918cbSDavid Gibson     SpaprMachineState *spapr = opaque;
2543c573fc03SThomas Huth 
2544c573fc03SThomas Huth     close_htab_fd(spapr);
2545c573fc03SThomas Huth }
2546c573fc03SThomas Huth 
25474be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = {
25489907e842SJuan Quintela     .save_setup = htab_save_setup,
25494be21d56SDavid Gibson     .save_live_iterate = htab_save_iterate,
2550a3e06c3dSDr. David Alan Gilbert     .save_live_complete_precopy = htab_save_complete,
255170f794fcSJuan Quintela     .save_cleanup = htab_save_cleanup,
25524be21d56SDavid Gibson     .load_state = htab_load,
25534be21d56SDavid Gibson };
25544be21d56SDavid Gibson 
spapr_boot_set(void * opaque,const char * boot_device,Error ** errp)25555b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device,
25565b2128d2SAlexander Graf                            Error **errp)
25575b2128d2SAlexander Graf {
25583bf0844fSGreg Kurz     SpaprMachineState *spapr = SPAPR_MACHINE(opaque);
25593bf0844fSGreg Kurz 
25603bf0844fSGreg Kurz     g_free(spapr->boot_device);
25613bf0844fSGreg Kurz     spapr->boot_device = g_strdup(boot_device);
25625b2128d2SAlexander Graf }
25635b2128d2SAlexander Graf 
spapr_create_lmb_dr_connectors(SpaprMachineState * spapr)2564ce2918cbSDavid Gibson static void spapr_create_lmb_dr_connectors(SpaprMachineState *spapr)
2565224245bfSDavid Gibson {
2566224245bfSDavid Gibson     MachineState *machine = MACHINE(spapr);
2567224245bfSDavid Gibson     uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
2568e8f986fcSBharata B Rao     uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size;
2569224245bfSDavid Gibson     int i;
2570224245bfSDavid Gibson 
2571c0ce7b4aSDavid Hildenbrand     g_assert(!nr_lmbs || machine->device_memory);
2572224245bfSDavid Gibson     for (i = 0; i < nr_lmbs; i++) {
2573224245bfSDavid Gibson         uint64_t addr;
2574224245bfSDavid Gibson 
2575b0c14ec4SDavid Hildenbrand         addr = i * lmb_size + machine->device_memory->base;
25766caf3ac6SDavid Gibson         spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_LMB,
2577224245bfSDavid Gibson                                addr / lmb_size);
2578224245bfSDavid Gibson     }
2579224245bfSDavid Gibson }
2580224245bfSDavid Gibson 
2581224245bfSDavid Gibson /*
2582224245bfSDavid Gibson  * If RAM size, maxmem size and individual node mem sizes aren't aligned
2583224245bfSDavid Gibson  * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest
2584224245bfSDavid Gibson  * since we can't support such unaligned sizes with DRCONF_MEMORY.
2585224245bfSDavid Gibson  */
spapr_validate_node_memory(MachineState * machine,Error ** errp)25867c150d6fSDavid Gibson static void spapr_validate_node_memory(MachineState *machine, Error **errp)
2587224245bfSDavid Gibson {
2588224245bfSDavid Gibson     int i;
2589224245bfSDavid Gibson 
25907c150d6fSDavid Gibson     if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) {
25917c150d6fSDavid Gibson         error_setg(errp, "Memory size 0x" RAM_ADDR_FMT
2592ab3dd749SPhilippe Mathieu-Daudé                    " is not aligned to %" PRIu64 " MiB",
25937c150d6fSDavid Gibson                    machine->ram_size,
2594d23b6caaSPhilippe Mathieu-Daudé                    SPAPR_MEMORY_BLOCK_SIZE / MiB);
25957c150d6fSDavid Gibson         return;
25967c150d6fSDavid Gibson     }
25977c150d6fSDavid Gibson 
25987c150d6fSDavid Gibson     if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) {
25997c150d6fSDavid Gibson         error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT
2600ab3dd749SPhilippe Mathieu-Daudé                    " is not aligned to %" PRIu64 " MiB",
26017c150d6fSDavid Gibson                    machine->ram_size,
2602d23b6caaSPhilippe Mathieu-Daudé                    SPAPR_MEMORY_BLOCK_SIZE / MiB);
26037c150d6fSDavid Gibson         return;
2604224245bfSDavid Gibson     }
2605224245bfSDavid Gibson 
2606aa570207STao Xu     for (i = 0; i < machine->numa_state->num_nodes; i++) {
26077e721e7bSTao Xu         if (machine->numa_state->nodes[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) {
26087c150d6fSDavid Gibson             error_setg(errp,
26097c150d6fSDavid Gibson                        "Node %d memory size 0x%" PRIx64
2610ab3dd749SPhilippe Mathieu-Daudé                        " is not aligned to %" PRIu64 " MiB",
26117e721e7bSTao Xu                        i, machine->numa_state->nodes[i].node_mem,
2612d23b6caaSPhilippe Mathieu-Daudé                        SPAPR_MEMORY_BLOCK_SIZE / MiB);
26137c150d6fSDavid Gibson             return;
2614224245bfSDavid Gibson         }
2615224245bfSDavid Gibson     }
2616224245bfSDavid Gibson }
2617224245bfSDavid Gibson 
2618535455fdSIgor Mammedov /* find cpu slot in machine->possible_cpus by core_id */
spapr_find_cpu_slot(MachineState * ms,uint32_t id,int * idx)2619535455fdSIgor Mammedov static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx)
2620535455fdSIgor Mammedov {
2621fe6b6346SLike Xu     int index = id / ms->smp.threads;
2622535455fdSIgor Mammedov 
2623535455fdSIgor Mammedov     if (index >= ms->possible_cpus->len) {
2624535455fdSIgor Mammedov         return NULL;
2625535455fdSIgor Mammedov     }
2626535455fdSIgor Mammedov     if (idx) {
2627535455fdSIgor Mammedov         *idx = index;
2628535455fdSIgor Mammedov     }
2629535455fdSIgor Mammedov     return &ms->possible_cpus->cpus[index];
2630535455fdSIgor Mammedov }
2631535455fdSIgor Mammedov 
spapr_set_vsmt_mode(SpaprMachineState * spapr,Error ** errp)2632ce2918cbSDavid Gibson static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp)
2633fa98fbfcSSam Bobroff {
2634fe6b6346SLike Xu     MachineState *ms = MACHINE(spapr);
263529cb4187SGreg Kurz     SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
2636fa98fbfcSSam Bobroff     Error *local_err = NULL;
2637fa98fbfcSSam Bobroff     bool vsmt_user = !!spapr->vsmt;
2638fa98fbfcSSam Bobroff     int kvm_smt = kvmppc_smt_threads();
2639fa98fbfcSSam Bobroff     int ret;
2640fe6b6346SLike Xu     unsigned int smp_threads = ms->smp.threads;
2641fa98fbfcSSam Bobroff 
2642dc5e0721SNicholas Piggin     if (tcg_enabled()) {
2643dc5e0721SNicholas Piggin         if (smp_threads > 1 &&
2644dc5e0721SNicholas Piggin             !ppc_type_check_compat(ms->cpu_type, CPU_POWERPC_LOGICAL_2_07, 0,
2645dc5e0721SNicholas Piggin                                    spapr->max_compat_pvr)) {
2646dc5e0721SNicholas Piggin             error_setg(errp, "TCG only supports SMT on POWER8 or newer CPUs");
2647dc5e0721SNicholas Piggin             return;
2648dc5e0721SNicholas Piggin         }
2649dc5e0721SNicholas Piggin 
2650dc5e0721SNicholas Piggin         if (smp_threads > 8) {
2651dc5e0721SNicholas Piggin             error_setg(errp, "TCG cannot support more than 8 threads/core "
2652fa98fbfcSSam Bobroff                        "on a pseries machine");
2653dcfe4805SMarkus Armbruster             return;
2654fa98fbfcSSam Bobroff         }
2655dc5e0721SNicholas Piggin     }
2656fa98fbfcSSam Bobroff     if (!is_power_of_2(smp_threads)) {
2657dcfe4805SMarkus Armbruster         error_setg(errp, "Cannot support %d threads/core on a pseries "
2658fa98fbfcSSam Bobroff                    "machine because it must be a power of 2", smp_threads);
2659dcfe4805SMarkus Armbruster         return;
2660fa98fbfcSSam Bobroff     }
2661fa98fbfcSSam Bobroff 
2662e6a19a64SMichael Tokarev     /* Determine the VSMT mode to use: */
2663fa98fbfcSSam Bobroff     if (vsmt_user) {
2664fa98fbfcSSam Bobroff         if (spapr->vsmt < smp_threads) {
2665dcfe4805SMarkus Armbruster             error_setg(errp, "Cannot support VSMT mode %d"
2666fa98fbfcSSam Bobroff                        " because it must be >= threads/core (%d)",
2667fa98fbfcSSam Bobroff                        spapr->vsmt, smp_threads);
2668dcfe4805SMarkus Armbruster             return;
2669fa98fbfcSSam Bobroff         }
2670fa98fbfcSSam Bobroff         /* In this case, spapr->vsmt has been set by the command line */
267129cb4187SGreg Kurz     } else if (!smc->smp_threads_vsmt) {
26728904e5a7SDavid Gibson         /*
26738904e5a7SDavid Gibson          * Default VSMT value is tricky, because we need it to be as
26748904e5a7SDavid Gibson          * consistent as possible (for migration), but this requires
26758904e5a7SDavid Gibson          * changing it for at least some existing cases.  We pick 8 as
26768904e5a7SDavid Gibson          * the value that we'd get with KVM on POWER8, the
26778904e5a7SDavid Gibson          * overwhelmingly common case in production systems.
26788904e5a7SDavid Gibson          */
26794ad64cbdSLaurent Vivier         spapr->vsmt = MAX(8, smp_threads);
268029cb4187SGreg Kurz     } else {
268129cb4187SGreg Kurz         spapr->vsmt = smp_threads;
2682fa98fbfcSSam Bobroff     }
2683fa98fbfcSSam Bobroff 
2684fa98fbfcSSam Bobroff     /* KVM: If necessary, set the SMT mode: */
2685fa98fbfcSSam Bobroff     if (kvm_enabled() && (spapr->vsmt != kvm_smt)) {
2686fa98fbfcSSam Bobroff         ret = kvmppc_set_smt_threads(spapr->vsmt);
2687fa98fbfcSSam Bobroff         if (ret) {
26881f20f2e0SDavid Gibson             /* Looks like KVM isn't able to change VSMT mode */
2689fa98fbfcSSam Bobroff             error_setg(&local_err,
2690fa98fbfcSSam Bobroff                        "Failed to set KVM's VSMT mode to %d (errno %d)",
2691fa98fbfcSSam Bobroff                        spapr->vsmt, ret);
26921f20f2e0SDavid Gibson             /* We can live with that if the default one is big enough
26931f20f2e0SDavid Gibson              * for the number of threads, and a submultiple of the one
26941f20f2e0SDavid Gibson              * we want.  In this case we'll waste some vcpu ids, but
26951f20f2e0SDavid Gibson              * behaviour will be correct */
26961f20f2e0SDavid Gibson             if ((kvm_smt >= smp_threads) && ((spapr->vsmt % kvm_smt) == 0)) {
26971f20f2e0SDavid Gibson                 warn_report_err(local_err);
26981f20f2e0SDavid Gibson             } else {
2699fa98fbfcSSam Bobroff                 if (!vsmt_user) {
27001f20f2e0SDavid Gibson                     error_append_hint(&local_err,
27011f20f2e0SDavid Gibson                                       "On PPC, a VM with %d threads/core"
27021f20f2e0SDavid Gibson                                       " on a host with %d threads/core"
27031f20f2e0SDavid Gibson                                       " requires the use of VSMT mode %d.\n",
2704fa98fbfcSSam Bobroff                                       smp_threads, kvm_smt, spapr->vsmt);
2705fa98fbfcSSam Bobroff                 }
2706cdcca22aSVladimir Sementsov-Ogievskiy                 kvmppc_error_append_smt_possible_hint(&local_err);
2707dcfe4805SMarkus Armbruster                 error_propagate(errp, local_err);
2708fa98fbfcSSam Bobroff             }
2709fa98fbfcSSam Bobroff         }
27101f20f2e0SDavid Gibson     }
2711fa98fbfcSSam Bobroff     /* else TCG: nothing to do currently */
2712fa98fbfcSSam Bobroff }
2713fa98fbfcSSam Bobroff 
spapr_init_cpus(SpaprMachineState * spapr)2714ce2918cbSDavid Gibson static void spapr_init_cpus(SpaprMachineState *spapr)
27151a5008fcSGreg Kurz {
27161a5008fcSGreg Kurz     MachineState *machine = MACHINE(spapr);
27171a5008fcSGreg Kurz     MachineClass *mc = MACHINE_GET_CLASS(machine);
2718ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
27191a5008fcSGreg Kurz     const char *type = spapr_get_cpu_core_type(machine->cpu_type);
27201a5008fcSGreg Kurz     const CPUArchIdList *possible_cpus;
2721fe6b6346SLike Xu     unsigned int smp_cpus = machine->smp.cpus;
2722fe6b6346SLike Xu     unsigned int smp_threads = machine->smp.threads;
2723fe6b6346SLike Xu     unsigned int max_cpus = machine->smp.max_cpus;
27241a5008fcSGreg Kurz     int boot_cores_nr = smp_cpus / smp_threads;
27251a5008fcSGreg Kurz     int i;
27261a5008fcSGreg Kurz 
27271a5008fcSGreg Kurz     possible_cpus = mc->possible_cpu_arch_ids(machine);
27281a5008fcSGreg Kurz     if (mc->has_hotpluggable_cpus) {
27291a5008fcSGreg Kurz         if (smp_cpus % smp_threads) {
27301a5008fcSGreg Kurz             error_report("smp_cpus (%u) must be multiple of threads (%u)",
27311a5008fcSGreg Kurz                          smp_cpus, smp_threads);
27321a5008fcSGreg Kurz             exit(1);
27331a5008fcSGreg Kurz         }
27341a5008fcSGreg Kurz         if (max_cpus % smp_threads) {
27351a5008fcSGreg Kurz             error_report("max_cpus (%u) must be multiple of threads (%u)",
27361a5008fcSGreg Kurz                          max_cpus, smp_threads);
27371a5008fcSGreg Kurz             exit(1);
27381a5008fcSGreg Kurz         }
27391a5008fcSGreg Kurz     } else {
27401a5008fcSGreg Kurz         if (max_cpus != smp_cpus) {
27411a5008fcSGreg Kurz             error_report("This machine version does not support CPU hotplug");
27421a5008fcSGreg Kurz             exit(1);
27431a5008fcSGreg Kurz         }
27441a5008fcSGreg Kurz         boot_cores_nr = possible_cpus->len;
27451a5008fcSGreg Kurz     }
27461a5008fcSGreg Kurz 
27471a5008fcSGreg Kurz     if (smc->pre_2_10_has_unused_icps) {
27481a518e76SCédric Le Goater         for (i = 0; i < spapr_max_server_number(spapr); i++) {
27491a5008fcSGreg Kurz             /* Dummy entries get deregistered when real ICPState objects
27501a5008fcSGreg Kurz              * are registered during CPU core hotplug.
27511a5008fcSGreg Kurz              */
27521a5008fcSGreg Kurz             pre_2_10_vmstate_register_dummy_icp(i);
27531a5008fcSGreg Kurz         }
27541a5008fcSGreg Kurz     }
27551a5008fcSGreg Kurz 
27561a5008fcSGreg Kurz     for (i = 0; i < possible_cpus->len; i++) {
27571a5008fcSGreg Kurz         int core_id = i * smp_threads;
27581a5008fcSGreg Kurz 
27591a5008fcSGreg Kurz         if (mc->has_hotpluggable_cpus) {
27601a5008fcSGreg Kurz             spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU,
27611a5008fcSGreg Kurz                                    spapr_vcpu_id(spapr, core_id));
27621a5008fcSGreg Kurz         }
27631a5008fcSGreg Kurz 
27641a5008fcSGreg Kurz         if (i < boot_cores_nr) {
27651a5008fcSGreg Kurz             Object *core  = object_new(type);
27661a5008fcSGreg Kurz             int nr_threads = smp_threads;
27671a5008fcSGreg Kurz 
27681a5008fcSGreg Kurz             /* Handle the partially filled core for older machine types */
27691a5008fcSGreg Kurz             if ((i + 1) * smp_threads >= smp_cpus) {
27701a5008fcSGreg Kurz                 nr_threads = smp_cpus - i * smp_threads;
27711a5008fcSGreg Kurz             }
27721a5008fcSGreg Kurz 
27735325cc34SMarkus Armbruster             object_property_set_int(core, "nr-threads", nr_threads,
27741a5008fcSGreg Kurz                                     &error_fatal);
27755325cc34SMarkus Armbruster             object_property_set_int(core, CPU_CORE_PROP_CORE_ID, core_id,
27761a5008fcSGreg Kurz                                     &error_fatal);
2777ce189ab2SMarkus Armbruster             qdev_realize(DEVICE(core), NULL, &error_fatal);
2778ecda255eSSam Bobroff 
2779ecda255eSSam Bobroff             object_unref(core);
27801a5008fcSGreg Kurz         }
27811a5008fcSGreg Kurz     }
27821a5008fcSGreg Kurz }
27831a5008fcSGreg Kurz 
spapr_create_default_phb(void)2784999c9cafSGreg Kurz static PCIHostState *spapr_create_default_phb(void)
2785999c9cafSGreg Kurz {
2786999c9cafSGreg Kurz     DeviceState *dev;
2787999c9cafSGreg Kurz 
27883e80f690SMarkus Armbruster     dev = qdev_new(TYPE_SPAPR_PCI_HOST_BRIDGE);
2789999c9cafSGreg Kurz     qdev_prop_set_uint32(dev, "index", 0);
27903c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
2791999c9cafSGreg Kurz 
2792999c9cafSGreg Kurz     return PCI_HOST_BRIDGE(dev);
2793999c9cafSGreg Kurz }
2794999c9cafSGreg Kurz 
spapr_rma_size(SpaprMachineState * spapr,Error ** errp)2795425f0b7aSDavid Gibson static hwaddr spapr_rma_size(SpaprMachineState *spapr, Error **errp)
2796425f0b7aSDavid Gibson {
2797425f0b7aSDavid Gibson     MachineState *machine = MACHINE(spapr);
2798425f0b7aSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
2799425f0b7aSDavid Gibson     hwaddr rma_size = machine->ram_size;
2800425f0b7aSDavid Gibson     hwaddr node0_size = spapr_node0_size(machine);
2801425f0b7aSDavid Gibson 
2802425f0b7aSDavid Gibson     /* RMA has to fit in the first NUMA node */
2803425f0b7aSDavid Gibson     rma_size = MIN(rma_size, node0_size);
2804425f0b7aSDavid Gibson 
2805425f0b7aSDavid Gibson     /*
2806425f0b7aSDavid Gibson      * VRMA access is via a special 1TiB SLB mapping, so the RMA can
2807425f0b7aSDavid Gibson      * never exceed that
2808425f0b7aSDavid Gibson      */
2809425f0b7aSDavid Gibson     rma_size = MIN(rma_size, 1 * TiB);
2810425f0b7aSDavid Gibson 
2811425f0b7aSDavid Gibson     /*
2812425f0b7aSDavid Gibson      * Clamp the RMA size based on machine type.  This is for
2813425f0b7aSDavid Gibson      * migration compatibility with older qemu versions, which limited
2814425f0b7aSDavid Gibson      * the RMA size for complicated and mostly bad reasons.
2815425f0b7aSDavid Gibson      */
2816425f0b7aSDavid Gibson     if (smc->rma_limit) {
2817425f0b7aSDavid Gibson         rma_size = MIN(rma_size, smc->rma_limit);
2818425f0b7aSDavid Gibson     }
2819425f0b7aSDavid Gibson 
2820425f0b7aSDavid Gibson     if (rma_size < MIN_RMA_SLOF) {
2821425f0b7aSDavid Gibson         error_setg(errp,
2822425f0b7aSDavid Gibson                    "pSeries SLOF firmware requires >= %" HWADDR_PRIx
2823425f0b7aSDavid Gibson                    "ldMiB guest RMA (Real Mode Area memory)",
2824425f0b7aSDavid Gibson                    MIN_RMA_SLOF / MiB);
2825425f0b7aSDavid Gibson         return 0;
2826425f0b7aSDavid Gibson     }
2827425f0b7aSDavid Gibson 
2828425f0b7aSDavid Gibson     return rma_size;
2829425f0b7aSDavid Gibson }
2830425f0b7aSDavid Gibson 
spapr_create_nvdimm_dr_connectors(SpaprMachineState * spapr)2831ce316b51SGreg Kurz static void spapr_create_nvdimm_dr_connectors(SpaprMachineState *spapr)
2832ce316b51SGreg Kurz {
2833ce316b51SGreg Kurz     MachineState *machine = MACHINE(spapr);
2834ce316b51SGreg Kurz     int i;
2835ce316b51SGreg Kurz 
2836ce316b51SGreg Kurz     for (i = 0; i < machine->ram_slots; i++) {
2837ce316b51SGreg Kurz         spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_PMEM, i);
2838ce316b51SGreg Kurz     }
2839ce316b51SGreg Kurz }
2840ce316b51SGreg Kurz 
284153018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */
spapr_machine_init(MachineState * machine)2842bcb5ce08SDavid Gibson static void spapr_machine_init(MachineState *machine)
284353018216SPaolo Bonzini {
2844ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(machine);
2845ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
2846ee3a71e3SShivaprasad G Bhat     MachineClass *mc = MACHINE_GET_CLASS(machine);
2847fc8c745dSAlexey Kardashevskiy     const char *bios_default = spapr->vof ? FW_FILE_NAME_VOF : FW_FILE_NAME;
2848fc8c745dSAlexey Kardashevskiy     const char *bios_name = machine->firmware ?: bios_default;
28495f2b96b3SDaniel Henrique Barboza     g_autofree char *filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
28503ef96221SMarcel Apfelbaum     const char *kernel_filename = machine->kernel_filename;
28513ef96221SMarcel Apfelbaum     const char *initrd_filename = machine->initrd_filename;
285253018216SPaolo Bonzini     PCIHostState *phb;
2853f73eb948SPaolo Bonzini     bool has_vga;
285453018216SPaolo Bonzini     int i;
285553018216SPaolo Bonzini     MemoryRegion *sysmem = get_system_memory();
2856b7d1f77aSBenjamin Herrenschmidt     long load_limit, fw_size;
285730f4b05bSDavid Gibson     Error *resize_hpt_err = NULL;
28580aff8161SDavid Woodhouse     NICInfo *nd;
285953018216SPaolo Bonzini 
28605f2b96b3SDaniel Henrique Barboza     if (!filename) {
28615f2b96b3SDaniel Henrique Barboza         error_report("Could not find LPAR firmware '%s'", bios_name);
28625f2b96b3SDaniel Henrique Barboza         exit(1);
28635f2b96b3SDaniel Henrique Barboza     }
28645f2b96b3SDaniel Henrique Barboza     fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE);
28655f2b96b3SDaniel Henrique Barboza     if (fw_size <= 0) {
28665f2b96b3SDaniel Henrique Barboza         error_report("Could not load LPAR firmware '%s'", filename);
28675f2b96b3SDaniel Henrique Barboza         exit(1);
28685f2b96b3SDaniel Henrique Barboza     }
28695f2b96b3SDaniel Henrique Barboza 
28706c8ebe30SDavid Gibson     /*
28716c8ebe30SDavid Gibson      * if Secure VM (PEF) support is configured, then initialize it
28726c8ebe30SDavid Gibson      */
287300a238b1SXiaoyao Li     if (machine->cgs) {
287400a238b1SXiaoyao Li         confidential_guest_kvm_init(machine->cgs, &error_fatal);
287500a238b1SXiaoyao Li     }
28766c8ebe30SDavid Gibson 
2877226419d6SMichael S. Tsirkin     msi_nonbroken = true;
287853018216SPaolo Bonzini 
287953018216SPaolo Bonzini     QLIST_INIT(&spapr->phbs);
28800cffce56SDavid Gibson     QTAILQ_INIT(&spapr->pending_dimm_unplugs);
288153018216SPaolo Bonzini 
28829f6edd06SDavid Gibson     /* Determine capabilities to run with */
28839f6edd06SDavid Gibson     spapr_caps_init(spapr);
28849f6edd06SDavid Gibson 
288530f4b05bSDavid Gibson     kvmppc_check_papr_resize_hpt(&resize_hpt_err);
288630f4b05bSDavid Gibson     if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) {
288730f4b05bSDavid Gibson         /*
288830f4b05bSDavid Gibson          * If the user explicitly requested a mode we should either
288930f4b05bSDavid Gibson          * supply it, or fail completely (which we do below).  But if
289030f4b05bSDavid Gibson          * it's not set explicitly, we reset our mode to something
289130f4b05bSDavid Gibson          * that works
289230f4b05bSDavid Gibson          */
289330f4b05bSDavid Gibson         if (resize_hpt_err) {
289430f4b05bSDavid Gibson             spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED;
289530f4b05bSDavid Gibson             error_free(resize_hpt_err);
289630f4b05bSDavid Gibson             resize_hpt_err = NULL;
289730f4b05bSDavid Gibson         } else {
289830f4b05bSDavid Gibson             spapr->resize_hpt = smc->resize_hpt_default;
289930f4b05bSDavid Gibson         }
290030f4b05bSDavid Gibson     }
290130f4b05bSDavid Gibson 
290230f4b05bSDavid Gibson     assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT);
290330f4b05bSDavid Gibson 
290430f4b05bSDavid Gibson     if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && resize_hpt_err) {
290530f4b05bSDavid Gibson         /*
290630f4b05bSDavid Gibson          * User requested HPT resize, but this host can't supply it.  Bail out
290730f4b05bSDavid Gibson          */
290830f4b05bSDavid Gibson         error_report_err(resize_hpt_err);
290930f4b05bSDavid Gibson         exit(1);
291030f4b05bSDavid Gibson     }
291114963c34SMarkus Armbruster     error_free(resize_hpt_err);
291230f4b05bSDavid Gibson 
2913425f0b7aSDavid Gibson     spapr->rma_size = spapr_rma_size(spapr, &error_fatal);
2914c4177479SAlexey Kardashevskiy 
2915b7d1f77aSBenjamin Herrenschmidt     /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */
29164b98e72dSAlexey Kardashevskiy     load_limit = MIN(spapr->rma_size, FDT_MAX_ADDR) - FW_OVERHEAD;
291753018216SPaolo Bonzini 
2918482969d6SCédric Le Goater     /*
2919482969d6SCédric Le Goater      * VSMT must be set in order to be able to compute VCPU ids, ie to
29201a518e76SCédric Le Goater      * call spapr_max_server_number() or spapr_vcpu_id().
2921482969d6SCédric Le Goater      */
2922482969d6SCédric Le Goater     spapr_set_vsmt_mode(spapr, &error_fatal);
2923482969d6SCédric Le Goater 
29247b565160SDavid Gibson     /* Set up Interrupt Controller before we create the VCPUs */
2925fab397d8SCédric Le Goater     spapr_irq_init(spapr, &error_fatal);
29267b565160SDavid Gibson 
2927dc1b5eeeSGreg Kurz     /* Set up containers for ibm,client-architecture-support negotiated options
2928dc1b5eeeSGreg Kurz      */
2929facdb8b6SMichael Roth     spapr->ov5 = spapr_ovec_new();
2930facdb8b6SMichael Roth     spapr->ov5_cas = spapr_ovec_new();
2931facdb8b6SMichael Roth 
2932224245bfSDavid Gibson     if (smc->dr_lmb_enabled) {
2933facdb8b6SMichael Roth         spapr_ovec_set(spapr->ov5, OV5_DRCONF_MEMORY);
29347c150d6fSDavid Gibson         spapr_validate_node_memory(machine, &error_fatal);
2935224245bfSDavid Gibson     }
2936224245bfSDavid Gibson 
2937417ece33SMichael Roth     spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY);
2938417ece33SMichael Roth 
2939e0eb84d4SDaniel Henrique Barboza     /* Do not advertise FORM2 NUMA support for pseries-6.1 and older */
2940e0eb84d4SDaniel Henrique Barboza     if (!smc->pre_6_2_numa_affinity) {
2941e0eb84d4SDaniel Henrique Barboza         spapr_ovec_set(spapr->ov5, OV5_FORM2_AFFINITY);
2942e0eb84d4SDaniel Henrique Barboza     }
2943e0eb84d4SDaniel Henrique Barboza 
2944ffbb1705SMichael Roth     /* advertise support for dedicated HP event source to guests */
2945ffbb1705SMichael Roth     if (spapr->use_hotplug_event_source) {
2946ffbb1705SMichael Roth         spapr_ovec_set(spapr->ov5, OV5_HP_EVT);
2947ffbb1705SMichael Roth     }
2948ffbb1705SMichael Roth 
29492772cf6bSDavid Gibson     /* advertise support for HPT resizing */
29502772cf6bSDavid Gibson     if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) {
29512772cf6bSDavid Gibson         spapr_ovec_set(spapr->ov5, OV5_HPT_RESIZE);
29522772cf6bSDavid Gibson     }
29532772cf6bSDavid Gibson 
2954a324d6f1SBharata B Rao     /* advertise support for ibm,dyamic-memory-v2 */
2955a324d6f1SBharata B Rao     spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2);
2956a324d6f1SBharata B Rao 
2957db592b5bSCédric Le Goater     /* advertise XIVE on POWER9 machines */
2958ca62823bSDavid Gibson     if (spapr->irq->xive) {
2959db592b5bSCédric Le Goater         spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT);
2960db592b5bSCédric Le Goater     }
2961db592b5bSCédric Le Goater 
296253018216SPaolo Bonzini     /* init CPUs */
29630c86d0fdSDavid Gibson     spapr_init_cpus(spapr);
296453018216SPaolo Bonzini 
2965f1aa45ffSDaniel Henrique Barboza     /* Init numa_assoc_array */
2966f1aa45ffSDaniel Henrique Barboza     spapr_numa_associativity_init(spapr, machine);
2967f1aa45ffSDaniel Henrique Barboza 
29680550b120SGreg Kurz     if ((!kvm_enabled() || kvmppc_has_cap_mmu_radix()) &&
2969ad99d04cSDavid Gibson         ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0,
29700550b120SGreg Kurz                               spapr->max_compat_pvr)) {
2971b4b83312SGreg Kurz         spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_300);
29720550b120SGreg Kurz         /* KVM and TCG always allow GTSE with radix... */
29730550b120SGreg Kurz         spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE);
29740550b120SGreg Kurz     }
29750550b120SGreg Kurz     /* ... but not with hash (currently). */
29760550b120SGreg Kurz 
2977026bfd89SDavid Gibson     if (kvm_enabled()) {
2978026bfd89SDavid Gibson         /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */
2979026bfd89SDavid Gibson         kvmppc_enable_logical_ci_hcalls();
2980ef9971ddSAlexey Kardashevskiy         kvmppc_enable_set_mode_hcall();
29815145ad4fSNathan Whitehorn 
29825145ad4fSNathan Whitehorn         /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */
29835145ad4fSNathan Whitehorn         kvmppc_enable_clear_ref_mod_hcalls();
298468f9f708SSuraj Jitindar Singh 
298568f9f708SSuraj Jitindar Singh         /* Enable H_PAGE_INIT */
298668f9f708SSuraj Jitindar Singh         kvmppc_enable_h_page_init();
2987026bfd89SDavid Gibson     }
2988026bfd89SDavid Gibson 
2989ab74e543SIgor Mammedov     /* map RAM */
2990ab74e543SIgor Mammedov     memory_region_add_subregion(sysmem, 0, machine->ram);
299153018216SPaolo Bonzini 
29924a1c9cf0SBharata B Rao     /* initialize hotplug memory address space */
29934a1c9cf0SBharata B Rao     if (machine->ram_size < machine->maxram_size) {
29940c9269a5SDavid Hildenbrand         ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size;
2995c0ce7b4aSDavid Hildenbrand         hwaddr device_mem_base;
2996c0ce7b4aSDavid Hildenbrand 
299771c9a3ddSBharata B Rao         /*
299871c9a3ddSBharata B Rao          * Limit the number of hotpluggable memory slots to half the number
299971c9a3ddSBharata B Rao          * slots that KVM supports, leaving the other half for PCI and other
300071c9a3ddSBharata B Rao          * devices. However ensure that number of slots doesn't drop below 32.
300171c9a3ddSBharata B Rao          */
300271c9a3ddSBharata B Rao         int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 :
300371c9a3ddSBharata B Rao                            SPAPR_MAX_RAM_SLOTS;
30044a1c9cf0SBharata B Rao 
300571c9a3ddSBharata B Rao         if (max_memslots < SPAPR_MAX_RAM_SLOTS) {
300671c9a3ddSBharata B Rao             max_memslots = SPAPR_MAX_RAM_SLOTS;
300771c9a3ddSBharata B Rao         }
300871c9a3ddSBharata B Rao         if (machine->ram_slots > max_memslots) {
3009d54e4d76SDavid Gibson             error_report("Specified number of memory slots %"
3010d54e4d76SDavid Gibson                          PRIu64" exceeds max supported %d",
301171c9a3ddSBharata B Rao                          machine->ram_slots, max_memslots);
3012d54e4d76SDavid Gibson             exit(1);
30134a1c9cf0SBharata B Rao         }
30144a1c9cf0SBharata B Rao 
3015c0ce7b4aSDavid Hildenbrand         device_mem_base = ROUND_UP(machine->ram_size, SPAPR_DEVICE_MEM_ALIGN);
3016c0ce7b4aSDavid Hildenbrand         machine_memory_devices_init(machine, device_mem_base, device_mem_size);
30174a1c9cf0SBharata B Rao     }
30184a1c9cf0SBharata B Rao 
3019224245bfSDavid Gibson     if (smc->dr_lmb_enabled) {
3020224245bfSDavid Gibson         spapr_create_lmb_dr_connectors(spapr);
3021224245bfSDavid Gibson     }
3022224245bfSDavid Gibson 
3023ee3a71e3SShivaprasad G Bhat     if (mc->nvdimm_supported) {
3024ee3a71e3SShivaprasad G Bhat         spapr_create_nvdimm_dr_connectors(spapr);
3025ee3a71e3SShivaprasad G Bhat     }
3026ee3a71e3SShivaprasad G Bhat 
3027ffbb1705SMichael Roth     /* Set up RTAS event infrastructure */
302853018216SPaolo Bonzini     spapr_events_init(spapr);
302953018216SPaolo Bonzini 
303012f42174SDavid Gibson     /* Set up the RTC RTAS interfaces */
303128df36a1SDavid Gibson     spapr_rtc_create(spapr);
303212f42174SDavid Gibson 
303353018216SPaolo Bonzini     /* Set up VIO bus */
303453018216SPaolo Bonzini     spapr->vio_bus = spapr_vio_bus_init();
303553018216SPaolo Bonzini 
303646ee119fSPaolo Bonzini     for (i = 0; serial_hd(i); i++) {
30379bca0edbSPeter Maydell         spapr_vty_create(spapr->vio_bus, serial_hd(i));
303853018216SPaolo Bonzini     }
303953018216SPaolo Bonzini 
304053018216SPaolo Bonzini     /* We always have at least the nvram device on VIO */
304153018216SPaolo Bonzini     spapr_create_nvram(spapr);
304253018216SPaolo Bonzini 
3043962b6c36SMichael Roth     /*
3044962b6c36SMichael Roth      * Setup hotplug / dynamic-reconfiguration connectors. top-level
3045962b6c36SMichael Roth      * connectors (described in root DT node's "ibm,drc-types" property)
3046962b6c36SMichael Roth      * are pre-initialized here. additional child connectors (such as
3047962b6c36SMichael Roth      * connectors for a PHBs PCI slots) are added as needed during their
3048962b6c36SMichael Roth      * parent's realization.
3049962b6c36SMichael Roth      */
3050962b6c36SMichael Roth     if (smc->dr_phb_enabled) {
3051962b6c36SMichael Roth         for (i = 0; i < SPAPR_MAX_PHBS; i++) {
3052962b6c36SMichael Roth             spapr_dr_connector_new(OBJECT(machine), TYPE_SPAPR_DRC_PHB, i);
3053962b6c36SMichael Roth         }
3054962b6c36SMichael Roth     }
3055962b6c36SMichael Roth 
305653018216SPaolo Bonzini     /* Set up PCI */
305753018216SPaolo Bonzini     spapr_pci_rtas_init();
305853018216SPaolo Bonzini 
3059999c9cafSGreg Kurz     phb = spapr_create_default_phb();
306053018216SPaolo Bonzini 
30610aff8161SDavid Woodhouse     while ((nd = qemu_find_nic_info("spapr-vlan", true, "ibmveth"))) {
306253018216SPaolo Bonzini         spapr_vlan_create(spapr->vio_bus, nd);
306353018216SPaolo Bonzini     }
30640aff8161SDavid Woodhouse 
30650aff8161SDavid Woodhouse     pci_init_nic_devices(phb->bus, NULL);
306653018216SPaolo Bonzini 
306753018216SPaolo Bonzini     for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) {
306853018216SPaolo Bonzini         spapr_vscsi_create(spapr->vio_bus);
306953018216SPaolo Bonzini     }
307053018216SPaolo Bonzini 
307153018216SPaolo Bonzini     /* Graphics */
3072f73eb948SPaolo Bonzini     has_vga = spapr_vga_init(phb->bus, &error_fatal);
3073f73eb948SPaolo Bonzini     if (has_vga) {
3074f73eb948SPaolo Bonzini         spapr->want_stdout_path = !machine->enable_graphics;
3075c6e76503SPaolo Bonzini         machine->usb |= defaults_enabled() && !machine->usb_disabled;
3076f73eb948SPaolo Bonzini     } else {
3077f73eb948SPaolo Bonzini         spapr->want_stdout_path = true;
307853018216SPaolo Bonzini     }
307953018216SPaolo Bonzini 
30804ee9ced9SMarcel Apfelbaum     if (machine->usb) {
308157040d45SThomas Huth         if (smc->use_ohci_by_default) {
308253018216SPaolo Bonzini             pci_create_simple(phb->bus, -1, "pci-ohci");
308357040d45SThomas Huth         } else {
308457040d45SThomas Huth             pci_create_simple(phb->bus, -1, "nec-usb-xhci");
308557040d45SThomas Huth         }
3086c86580b8SMarkus Armbruster 
3087f73eb948SPaolo Bonzini         if (has_vga) {
3088ae1011d4SPaolo Bonzini             USBBus *usb_bus;
3089c86580b8SMarkus Armbruster 
3090ae1011d4SPaolo Bonzini             usb_bus = USB_BUS(object_resolve_type_unambiguous(TYPE_USB_BUS,
3091ae1011d4SPaolo Bonzini                                                               &error_abort));
3092c86580b8SMarkus Armbruster             usb_create_simple(usb_bus, "usb-kbd");
3093c86580b8SMarkus Armbruster             usb_create_simple(usb_bus, "usb-mouse");
309453018216SPaolo Bonzini         }
309553018216SPaolo Bonzini     }
309653018216SPaolo Bonzini 
309753018216SPaolo Bonzini     if (kernel_filename) {
30985bb55f3eSAlexey Kardashevskiy         uint64_t loaded_addr = 0;
30995bb55f3eSAlexey Kardashevskiy 
31004366e1dbSLiam Merwick         spapr->kernel_size = load_elf(kernel_filename, NULL,
310187262806SAlexey Kardashevskiy                                       translate_kernel_address, spapr,
31025bb55f3eSAlexey Kardashevskiy                                       NULL, &loaded_addr, NULL, NULL, 1,
3103a19f7fb0SDavid Gibson                                       PPC_ELF_MACHINE, 0, 0);
3104a19f7fb0SDavid Gibson         if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) {
31054366e1dbSLiam Merwick             spapr->kernel_size = load_elf(kernel_filename, NULL,
3106617160c9SBALATON Zoltan                                           translate_kernel_address, spapr,
31075bb55f3eSAlexey Kardashevskiy                                           NULL, &loaded_addr, NULL, NULL, 0,
3108617160c9SBALATON Zoltan                                           PPC_ELF_MACHINE, 0, 0);
3109a19f7fb0SDavid Gibson             spapr->kernel_le = spapr->kernel_size > 0;
311016457e7fSBenjamin Herrenschmidt         }
3111a19f7fb0SDavid Gibson         if (spapr->kernel_size < 0) {
3112a19f7fb0SDavid Gibson             error_report("error loading %s: %s", kernel_filename,
3113a19f7fb0SDavid Gibson                          load_elf_strerror(spapr->kernel_size));
311453018216SPaolo Bonzini             exit(1);
311553018216SPaolo Bonzini         }
311653018216SPaolo Bonzini 
31175bb55f3eSAlexey Kardashevskiy         if (spapr->kernel_addr != loaded_addr) {
31185bb55f3eSAlexey Kardashevskiy             warn_report("spapr: kernel_addr changed from 0x%"PRIx64
31195bb55f3eSAlexey Kardashevskiy                         " to 0x%"PRIx64,
31205bb55f3eSAlexey Kardashevskiy                         spapr->kernel_addr, loaded_addr);
31215bb55f3eSAlexey Kardashevskiy             spapr->kernel_addr = loaded_addr;
31225bb55f3eSAlexey Kardashevskiy         }
31235bb55f3eSAlexey Kardashevskiy 
312453018216SPaolo Bonzini         /* load initrd */
312553018216SPaolo Bonzini         if (initrd_filename) {
312653018216SPaolo Bonzini             /* Try to locate the initrd in the gap between the kernel
312753018216SPaolo Bonzini              * and the firmware. Add a bit of space just in case
312853018216SPaolo Bonzini              */
312987262806SAlexey Kardashevskiy             spapr->initrd_base = (spapr->kernel_addr + spapr->kernel_size
3130a19f7fb0SDavid Gibson                                   + 0x1ffff) & ~0xffff;
3131a19f7fb0SDavid Gibson             spapr->initrd_size = load_image_targphys(initrd_filename,
3132a19f7fb0SDavid Gibson                                                      spapr->initrd_base,
3133a19f7fb0SDavid Gibson                                                      load_limit
3134a19f7fb0SDavid Gibson                                                      - spapr->initrd_base);
3135a19f7fb0SDavid Gibson             if (spapr->initrd_size < 0) {
3136d54e4d76SDavid Gibson                 error_report("could not load initial ram disk '%s'",
313753018216SPaolo Bonzini                              initrd_filename);
313853018216SPaolo Bonzini                 exit(1);
313953018216SPaolo Bonzini             }
314053018216SPaolo Bonzini         }
314153018216SPaolo Bonzini     }
314253018216SPaolo Bonzini 
314328e02042SDavid Gibson     /* FIXME: Should register things through the MachineState's qdev
314428e02042SDavid Gibson      * interface, this is a legacy from the sPAPREnvironment structure
314528e02042SDavid Gibson      * which predated MachineState but had a similar function */
31464be21d56SDavid Gibson     vmstate_register(NULL, 0, &vmstate_spapr, spapr);
31471df2c9a2SPeter Xu     register_savevm_live("spapr/htab", VMSTATE_INSTANCE_ID_ANY, 1,
31484be21d56SDavid Gibson                          &savevm_htab_handlers, spapr);
31494be21d56SDavid Gibson 
31509bc6bfdfSMarkus Armbruster     qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine));
3151bb2bdd81SGreg Kurz 
31525b2128d2SAlexander Graf     qemu_register_boot_set(spapr_boot_set, spapr);
315342043e4fSLaurent Vivier 
315493eac7b8SNicholas Piggin     /*
315593eac7b8SNicholas Piggin      * Nothing needs to be done to resume a suspended guest because
315693eac7b8SNicholas Piggin      * suspending does not change the machine state, so no need for
315793eac7b8SNicholas Piggin      * a ->wakeup method.
315893eac7b8SNicholas Piggin      */
315993eac7b8SNicholas Piggin     qemu_register_wakeup_support();
316093eac7b8SNicholas Piggin 
316142043e4fSLaurent Vivier     if (kvm_enabled()) {
31623dc410aeSAlexey Kardashevskiy         /* to stop and start vmclock */
316342043e4fSLaurent Vivier         qemu_add_vm_change_state_handler(cpu_ppc_clock_vm_state_change,
316442043e4fSLaurent Vivier                                          &spapr->tb);
31653dc410aeSAlexey Kardashevskiy 
31663dc410aeSAlexey Kardashevskiy         kvmppc_spapr_enable_inkernel_multitce();
316742043e4fSLaurent Vivier     }
31689ac703acSAravinda Prasad 
31698af7e1feSNicholas Piggin     qemu_cond_init(&spapr->fwnmi_machine_check_interlock_cond);
3170fc8c745dSAlexey Kardashevskiy     if (spapr->vof) {
3171fc8c745dSAlexey Kardashevskiy         spapr->vof->fw_size = fw_size; /* for claim() on itself */
3172fc8c745dSAlexey Kardashevskiy         spapr_register_hypercall(KVMPPC_H_VOF_CLIENT, spapr_h_vof_client);
3173fc8c745dSAlexey Kardashevskiy     }
317481b205ceSAlexey Kardashevskiy 
317581b205ceSAlexey Kardashevskiy     spapr_watchdog_init(spapr);
317653018216SPaolo Bonzini }
317753018216SPaolo Bonzini 
317807b10bc4SDaniel Henrique Barboza #define DEFAULT_KVM_TYPE "auto"
spapr_kvm_type(MachineState * machine,const char * vm_type)3179dc0ca80eSEric Auger static int spapr_kvm_type(MachineState *machine, const char *vm_type)
3180135a129aSAneesh Kumar K.V {
318107b10bc4SDaniel Henrique Barboza     /*
318207b10bc4SDaniel Henrique Barboza      * The use of g_ascii_strcasecmp() for 'hv' and 'pr' is to
3183e6a19a64SMichael Tokarev      * accommodate the 'HV' and 'PV' formats that exists in the
318407b10bc4SDaniel Henrique Barboza      * wild. The 'auto' mode is being introduced already as
318507b10bc4SDaniel Henrique Barboza      * lower-case, thus we don't need to bother checking for
318607b10bc4SDaniel Henrique Barboza      * "AUTO".
318707b10bc4SDaniel Henrique Barboza      */
318807b10bc4SDaniel Henrique Barboza     if (!vm_type || !strcmp(vm_type, DEFAULT_KVM_TYPE)) {
3189135a129aSAneesh Kumar K.V         return 0;
3190135a129aSAneesh Kumar K.V     }
3191135a129aSAneesh Kumar K.V 
319207b10bc4SDaniel Henrique Barboza     if (!g_ascii_strcasecmp(vm_type, "hv")) {
3193135a129aSAneesh Kumar K.V         return 1;
3194135a129aSAneesh Kumar K.V     }
3195135a129aSAneesh Kumar K.V 
319607b10bc4SDaniel Henrique Barboza     if (!g_ascii_strcasecmp(vm_type, "pr")) {
3197135a129aSAneesh Kumar K.V         return 2;
3198135a129aSAneesh Kumar K.V     }
3199135a129aSAneesh Kumar K.V 
3200135a129aSAneesh Kumar K.V     error_report("Unknown kvm-type specified '%s'", vm_type);
3201bc3e41a0SAkihiko Odaki     return -1;
3202135a129aSAneesh Kumar K.V }
3203135a129aSAneesh Kumar K.V 
320471461b0fSAlexey Kardashevskiy /*
3205627b84f4SGonglei  * Implementation of an interface to adjust firmware path
320671461b0fSAlexey Kardashevskiy  * for the bootindex property handling.
320771461b0fSAlexey Kardashevskiy  */
spapr_get_fw_dev_path(FWPathProvider * p,BusState * bus,DeviceState * dev)320871461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus,
320971461b0fSAlexey Kardashevskiy                                    DeviceState *dev)
321071461b0fSAlexey Kardashevskiy {
321171461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \
321271461b0fSAlexey Kardashevskiy     ((type *)object_dynamic_cast(OBJECT(obj), (name)))
321371461b0fSAlexey Kardashevskiy     SCSIDevice *d = CAST(SCSIDevice,  dev, TYPE_SCSI_DEVICE);
3214ce2918cbSDavid Gibson     SpaprPhbState *phb = CAST(SpaprPhbState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE);
3215c4e13492SFelipe Franciosi     VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON);
3216040bdafcSGreg Kurz     PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE);
321771461b0fSAlexey Kardashevskiy 
32181977434bSDaniel Henrique Barboza     if (d && bus) {
321971461b0fSAlexey Kardashevskiy         void *spapr = CAST(void, bus->parent, "spapr-vscsi");
322071461b0fSAlexey Kardashevskiy         VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI);
322171461b0fSAlexey Kardashevskiy         USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE);
322271461b0fSAlexey Kardashevskiy 
322371461b0fSAlexey Kardashevskiy         if (spapr) {
322471461b0fSAlexey Kardashevskiy             /*
322571461b0fSAlexey Kardashevskiy              * Replace "channel@0/disk@0,0" with "disk@8000000000000000":
32261ac24c91SThomas Huth              * In the top 16 bits of the 64-bit LUN, we use SRP luns of the form
32271ac24c91SThomas Huth              * 0x8000 | (target << 8) | (bus << 5) | lun
32281ac24c91SThomas Huth              * (see the "Logical unit addressing format" table in SAM5)
322971461b0fSAlexey Kardashevskiy              */
32301ac24c91SThomas Huth             unsigned id = 0x8000 | (d->id << 8) | (d->channel << 5) | d->lun;
323171461b0fSAlexey Kardashevskiy             return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev),
323271461b0fSAlexey Kardashevskiy                                    (uint64_t)id << 48);
323371461b0fSAlexey Kardashevskiy         } else if (virtio) {
323471461b0fSAlexey Kardashevskiy             /*
323571461b0fSAlexey Kardashevskiy              * We use SRP luns of the form 01000000 | (target << 8) | lun
323671461b0fSAlexey Kardashevskiy              * in the top 32 bits of the 64-bit LUN
323771461b0fSAlexey Kardashevskiy              * Note: the quote above is from SLOF and it is wrong,
323871461b0fSAlexey Kardashevskiy              * the actual binding is:
323971461b0fSAlexey Kardashevskiy              * swap 0100 or 10 << or 20 << ( target lun-id -- srplun )
324071461b0fSAlexey Kardashevskiy              */
324171461b0fSAlexey Kardashevskiy             unsigned id = 0x1000000 | (d->id << 16) | d->lun;
3242bac658d1SThomas Huth             if (d->lun >= 256) {
3243bac658d1SThomas Huth                 /* Use the LUN "flat space addressing method" */
3244bac658d1SThomas Huth                 id |= 0x4000;
3245bac658d1SThomas Huth             }
324671461b0fSAlexey Kardashevskiy             return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev),
324771461b0fSAlexey Kardashevskiy                                    (uint64_t)id << 32);
324871461b0fSAlexey Kardashevskiy         } else if (usb) {
324971461b0fSAlexey Kardashevskiy             /*
325071461b0fSAlexey Kardashevskiy              * We use SRP luns of the form 01000000 | (usb-port << 16) | lun
325171461b0fSAlexey Kardashevskiy              * in the top 32 bits of the 64-bit LUN
325271461b0fSAlexey Kardashevskiy              */
325371461b0fSAlexey Kardashevskiy             unsigned usb_port = atoi(usb->port->path);
325471461b0fSAlexey Kardashevskiy             unsigned id = 0x1000000 | (usb_port << 16) | d->lun;
325571461b0fSAlexey Kardashevskiy             return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev),
325671461b0fSAlexey Kardashevskiy                                    (uint64_t)id << 32);
325771461b0fSAlexey Kardashevskiy         }
325871461b0fSAlexey Kardashevskiy     }
325971461b0fSAlexey Kardashevskiy 
3260b99260ebSThomas Huth     /*
3261b99260ebSThomas Huth      * SLOF probes the USB devices, and if it recognizes that the device is a
3262b99260ebSThomas Huth      * storage device, it changes its name to "storage" instead of "usb-host",
3263b99260ebSThomas Huth      * and additionally adds a child node for the SCSI LUN, so the correct
3264b99260ebSThomas Huth      * boot path in SLOF is something like .../storage@1/disk@xxx" instead.
3265b99260ebSThomas Huth      */
3266b99260ebSThomas Huth     if (strcmp("usb-host", qdev_fw_name(dev)) == 0) {
3267b99260ebSThomas Huth         USBDevice *usbdev = CAST(USBDevice, dev, TYPE_USB_DEVICE);
3268b7b2a60bSGerd Hoffmann         if (usb_device_is_scsi_storage(usbdev)) {
3269b99260ebSThomas Huth             return g_strdup_printf("storage@%s/disk", usbdev->port->path);
3270b99260ebSThomas Huth         }
3271b99260ebSThomas Huth     }
3272b99260ebSThomas Huth 
327371461b0fSAlexey Kardashevskiy     if (phb) {
327471461b0fSAlexey Kardashevskiy         /* Replace "pci" with "pci@800000020000000" */
327571461b0fSAlexey Kardashevskiy         return g_strdup_printf("pci@%"PRIX64, phb->buid);
327671461b0fSAlexey Kardashevskiy     }
327771461b0fSAlexey Kardashevskiy 
3278c4e13492SFelipe Franciosi     if (vsc) {
3279c4e13492SFelipe Franciosi         /* Same logic as virtio above */
3280c4e13492SFelipe Franciosi         unsigned id = 0x1000000 | (vsc->target << 16) | vsc->lun;
3281c4e13492SFelipe Franciosi         return g_strdup_printf("disk@%"PRIX64, (uint64_t)id << 32);
3282c4e13492SFelipe Franciosi     }
3283c4e13492SFelipe Franciosi 
32844871dd4cSThomas Huth     if (g_str_equal("pci-bridge", qdev_fw_name(dev))) {
32854871dd4cSThomas Huth         /* SLOF uses "pci" instead of "pci-bridge" for PCI bridges */
328601a78f23SCédric Le Goater         PCIDevice *pdev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE);
328701a78f23SCédric Le Goater         return g_strdup_printf("pci@%x", PCI_SLOT(pdev->devfn));
32884871dd4cSThomas Huth     }
32894871dd4cSThomas Huth 
3290040bdafcSGreg Kurz     if (pcidev) {
3291040bdafcSGreg Kurz         return spapr_pci_fw_dev_name(pcidev);
3292040bdafcSGreg Kurz     }
3293040bdafcSGreg Kurz 
329471461b0fSAlexey Kardashevskiy     return NULL;
329571461b0fSAlexey Kardashevskiy }
329671461b0fSAlexey Kardashevskiy 
spapr_get_kvm_type(Object * obj,Error ** errp)329723825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp)
329823825581SEduardo Habkost {
3299ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
330023825581SEduardo Habkost 
330128e02042SDavid Gibson     return g_strdup(spapr->kvm_type);
330223825581SEduardo Habkost }
330323825581SEduardo Habkost 
spapr_set_kvm_type(Object * obj,const char * value,Error ** errp)330423825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp)
330523825581SEduardo Habkost {
3306ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
330723825581SEduardo Habkost 
330828e02042SDavid Gibson     g_free(spapr->kvm_type);
330928e02042SDavid Gibson     spapr->kvm_type = g_strdup(value);
331023825581SEduardo Habkost }
331123825581SEduardo Habkost 
spapr_get_modern_hotplug_events(Object * obj,Error ** errp)3312f6229214SMichael Roth static bool spapr_get_modern_hotplug_events(Object *obj, Error **errp)
3313f6229214SMichael Roth {
3314ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
3315f6229214SMichael Roth 
3316f6229214SMichael Roth     return spapr->use_hotplug_event_source;
3317f6229214SMichael Roth }
3318f6229214SMichael Roth 
spapr_set_modern_hotplug_events(Object * obj,bool value,Error ** errp)3319f6229214SMichael Roth static void spapr_set_modern_hotplug_events(Object *obj, bool value,
3320f6229214SMichael Roth                                             Error **errp)
3321f6229214SMichael Roth {
3322ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
3323f6229214SMichael Roth 
3324f6229214SMichael Roth     spapr->use_hotplug_event_source = value;
3325f6229214SMichael Roth }
3326f6229214SMichael Roth 
spapr_get_msix_emulation(Object * obj,Error ** errp)3327fcad0d21SAlexey Kardashevskiy static bool spapr_get_msix_emulation(Object *obj, Error **errp)
3328fcad0d21SAlexey Kardashevskiy {
3329fcad0d21SAlexey Kardashevskiy     return true;
3330fcad0d21SAlexey Kardashevskiy }
3331fcad0d21SAlexey Kardashevskiy 
spapr_get_resize_hpt(Object * obj,Error ** errp)333230f4b05bSDavid Gibson static char *spapr_get_resize_hpt(Object *obj, Error **errp)
333330f4b05bSDavid Gibson {
3334ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
333530f4b05bSDavid Gibson 
333630f4b05bSDavid Gibson     switch (spapr->resize_hpt) {
333730f4b05bSDavid Gibson     case SPAPR_RESIZE_HPT_DEFAULT:
333830f4b05bSDavid Gibson         return g_strdup("default");
333930f4b05bSDavid Gibson     case SPAPR_RESIZE_HPT_DISABLED:
334030f4b05bSDavid Gibson         return g_strdup("disabled");
334130f4b05bSDavid Gibson     case SPAPR_RESIZE_HPT_ENABLED:
334230f4b05bSDavid Gibson         return g_strdup("enabled");
334330f4b05bSDavid Gibson     case SPAPR_RESIZE_HPT_REQUIRED:
334430f4b05bSDavid Gibson         return g_strdup("required");
334530f4b05bSDavid Gibson     }
334630f4b05bSDavid Gibson     g_assert_not_reached();
334730f4b05bSDavid Gibson }
334830f4b05bSDavid Gibson 
spapr_set_resize_hpt(Object * obj,const char * value,Error ** errp)334930f4b05bSDavid Gibson static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp)
335030f4b05bSDavid Gibson {
3351ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
335230f4b05bSDavid Gibson 
335330f4b05bSDavid Gibson     if (strcmp(value, "default") == 0) {
335430f4b05bSDavid Gibson         spapr->resize_hpt = SPAPR_RESIZE_HPT_DEFAULT;
335530f4b05bSDavid Gibson     } else if (strcmp(value, "disabled") == 0) {
335630f4b05bSDavid Gibson         spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED;
335730f4b05bSDavid Gibson     } else if (strcmp(value, "enabled") == 0) {
335830f4b05bSDavid Gibson         spapr->resize_hpt = SPAPR_RESIZE_HPT_ENABLED;
335930f4b05bSDavid Gibson     } else if (strcmp(value, "required") == 0) {
336030f4b05bSDavid Gibson         spapr->resize_hpt = SPAPR_RESIZE_HPT_REQUIRED;
336130f4b05bSDavid Gibson     } else {
336230f4b05bSDavid Gibson         error_setg(errp, "Bad value for \"resize-hpt\" property");
336330f4b05bSDavid Gibson     }
336430f4b05bSDavid Gibson }
336530f4b05bSDavid Gibson 
spapr_get_vof(Object * obj,Error ** errp)3366fc8c745dSAlexey Kardashevskiy static bool spapr_get_vof(Object *obj, Error **errp)
3367fc8c745dSAlexey Kardashevskiy {
3368fc8c745dSAlexey Kardashevskiy     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
3369fc8c745dSAlexey Kardashevskiy 
3370fc8c745dSAlexey Kardashevskiy     return spapr->vof != NULL;
3371fc8c745dSAlexey Kardashevskiy }
3372fc8c745dSAlexey Kardashevskiy 
spapr_set_vof(Object * obj,bool value,Error ** errp)3373fc8c745dSAlexey Kardashevskiy static void spapr_set_vof(Object *obj, bool value, Error **errp)
3374fc8c745dSAlexey Kardashevskiy {
3375fc8c745dSAlexey Kardashevskiy     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
3376fc8c745dSAlexey Kardashevskiy 
3377fc8c745dSAlexey Kardashevskiy     if (spapr->vof) {
3378fc8c745dSAlexey Kardashevskiy         vof_cleanup(spapr->vof);
3379fc8c745dSAlexey Kardashevskiy         g_free(spapr->vof);
3380fc8c745dSAlexey Kardashevskiy         spapr->vof = NULL;
3381fc8c745dSAlexey Kardashevskiy     }
3382fc8c745dSAlexey Kardashevskiy     if (!value) {
3383fc8c745dSAlexey Kardashevskiy         return;
3384fc8c745dSAlexey Kardashevskiy     }
3385fc8c745dSAlexey Kardashevskiy     spapr->vof = g_malloc0(sizeof(*spapr->vof));
3386fc8c745dSAlexey Kardashevskiy }
3387fc8c745dSAlexey Kardashevskiy 
spapr_get_ic_mode(Object * obj,Error ** errp)33883ba3d0bcSCédric Le Goater static char *spapr_get_ic_mode(Object *obj, Error **errp)
33893ba3d0bcSCédric Le Goater {
3390ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
33913ba3d0bcSCédric Le Goater 
33923ba3d0bcSCédric Le Goater     if (spapr->irq == &spapr_irq_xics_legacy) {
33933ba3d0bcSCédric Le Goater         return g_strdup("legacy");
33943ba3d0bcSCédric Le Goater     } else if (spapr->irq == &spapr_irq_xics) {
33953ba3d0bcSCédric Le Goater         return g_strdup("xics");
33963ba3d0bcSCédric Le Goater     } else if (spapr->irq == &spapr_irq_xive) {
33973ba3d0bcSCédric Le Goater         return g_strdup("xive");
339813db0cd9SCédric Le Goater     } else if (spapr->irq == &spapr_irq_dual) {
339913db0cd9SCédric Le Goater         return g_strdup("dual");
34003ba3d0bcSCédric Le Goater     }
34013ba3d0bcSCédric Le Goater     g_assert_not_reached();
34023ba3d0bcSCédric Le Goater }
34033ba3d0bcSCédric Le Goater 
spapr_set_ic_mode(Object * obj,const char * value,Error ** errp)34043ba3d0bcSCédric Le Goater static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp)
34053ba3d0bcSCédric Le Goater {
3406ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
34073ba3d0bcSCédric Le Goater 
340821df5e4fSGreg Kurz     if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
340921df5e4fSGreg Kurz         error_setg(errp, "This machine only uses the legacy XICS backend, don't pass ic-mode");
341021df5e4fSGreg Kurz         return;
341121df5e4fSGreg Kurz     }
341221df5e4fSGreg Kurz 
34133ba3d0bcSCédric Le Goater     /* The legacy IRQ backend can not be set */
34143ba3d0bcSCédric Le Goater     if (strcmp(value, "xics") == 0) {
34153ba3d0bcSCédric Le Goater         spapr->irq = &spapr_irq_xics;
34163ba3d0bcSCédric Le Goater     } else if (strcmp(value, "xive") == 0) {
34173ba3d0bcSCédric Le Goater         spapr->irq = &spapr_irq_xive;
341813db0cd9SCédric Le Goater     } else if (strcmp(value, "dual") == 0) {
341913db0cd9SCédric Le Goater         spapr->irq = &spapr_irq_dual;
34203ba3d0bcSCédric Le Goater     } else {
34213ba3d0bcSCédric Le Goater         error_setg(errp, "Bad value for \"ic-mode\" property");
34223ba3d0bcSCédric Le Goater     }
34233ba3d0bcSCédric Le Goater }
34243ba3d0bcSCédric Le Goater 
spapr_get_host_model(Object * obj,Error ** errp)342527461d69SPrasad J Pandit static char *spapr_get_host_model(Object *obj, Error **errp)
342627461d69SPrasad J Pandit {
3427ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
342827461d69SPrasad J Pandit 
342927461d69SPrasad J Pandit     return g_strdup(spapr->host_model);
343027461d69SPrasad J Pandit }
343127461d69SPrasad J Pandit 
spapr_set_host_model(Object * obj,const char * value,Error ** errp)343227461d69SPrasad J Pandit static void spapr_set_host_model(Object *obj, const char *value, Error **errp)
343327461d69SPrasad J Pandit {
3434ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
343527461d69SPrasad J Pandit 
343627461d69SPrasad J Pandit     g_free(spapr->host_model);
343727461d69SPrasad J Pandit     spapr->host_model = g_strdup(value);
343827461d69SPrasad J Pandit }
343927461d69SPrasad J Pandit 
spapr_get_host_serial(Object * obj,Error ** errp)344027461d69SPrasad J Pandit static char *spapr_get_host_serial(Object *obj, Error **errp)
344127461d69SPrasad J Pandit {
3442ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
344327461d69SPrasad J Pandit 
344427461d69SPrasad J Pandit     return g_strdup(spapr->host_serial);
344527461d69SPrasad J Pandit }
344627461d69SPrasad J Pandit 
spapr_set_host_serial(Object * obj,const char * value,Error ** errp)344727461d69SPrasad J Pandit static void spapr_set_host_serial(Object *obj, const char *value, Error **errp)
344827461d69SPrasad J Pandit {
3449ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
345027461d69SPrasad J Pandit 
345127461d69SPrasad J Pandit     g_free(spapr->host_serial);
345227461d69SPrasad J Pandit     spapr->host_serial = g_strdup(value);
345327461d69SPrasad J Pandit }
345427461d69SPrasad J Pandit 
spapr_instance_init(Object * obj)3455bcb5ce08SDavid Gibson static void spapr_instance_init(Object *obj)
345623825581SEduardo Habkost {
3457ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
3458ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
345955810e90SIgor Mammedov     MachineState *ms = MACHINE(spapr);
346055810e90SIgor Mammedov     MachineClass *mc = MACHINE_GET_CLASS(ms);
346155810e90SIgor Mammedov 
346255810e90SIgor Mammedov     /*
346355810e90SIgor Mammedov      * NVDIMM support went live in 5.1 without considering that, in
346455810e90SIgor Mammedov      * other archs, the user needs to enable NVDIMM support with the
346555810e90SIgor Mammedov      * 'nvdimm' machine option and the default behavior is NVDIMM
346655810e90SIgor Mammedov      * support disabled. It is too late to roll back to the standard
346755810e90SIgor Mammedov      * behavior without breaking 5.1 guests.
346855810e90SIgor Mammedov      */
346955810e90SIgor Mammedov     if (mc->nvdimm_supported) {
347055810e90SIgor Mammedov         ms->nvdimms_state->is_enabled = true;
347155810e90SIgor Mammedov     }
3472715c5407SDavid Gibson 
3473715c5407SDavid Gibson     spapr->htab_fd = -1;
3474f6229214SMichael Roth     spapr->use_hotplug_event_source = true;
347507b10bc4SDaniel Henrique Barboza     spapr->kvm_type = g_strdup(DEFAULT_KVM_TYPE);
347623825581SEduardo Habkost     object_property_add_str(obj, "kvm-type",
3477d2623129SMarkus Armbruster                             spapr_get_kvm_type, spapr_set_kvm_type);
347849d2e648SMarcel Apfelbaum     object_property_set_description(obj, "kvm-type",
347907b10bc4SDaniel Henrique Barboza                                     "Specifies the KVM virtualization mode (auto,"
348007b10bc4SDaniel Henrique Barboza                                     " hv, pr). Defaults to 'auto'. This mode will use"
348107b10bc4SDaniel Henrique Barboza                                     " any available KVM module loaded in the host,"
348207b10bc4SDaniel Henrique Barboza                                     " where kvm_hv takes precedence if both kvm_hv and"
348307b10bc4SDaniel Henrique Barboza                                     " kvm_pr are loaded.");
3484f6229214SMichael Roth     object_property_add_bool(obj, "modern-hotplug-events",
3485f6229214SMichael Roth                             spapr_get_modern_hotplug_events,
3486d2623129SMarkus Armbruster                             spapr_set_modern_hotplug_events);
3487f6229214SMichael Roth     object_property_set_description(obj, "modern-hotplug-events",
3488f6229214SMichael Roth                                     "Use dedicated hotplug event mechanism in"
3489f6229214SMichael Roth                                     " place of standard EPOW events when possible"
34907eecec7dSMarkus Armbruster                                     " (required for memory hot-unplug support)");
34917843c0d6SDavid Gibson     ppc_compat_add_property(obj, "max-cpu-compat", &spapr->max_compat_pvr,
349240c2281cSMarkus Armbruster                             "Maximum permitted CPU compatibility mode");
349330f4b05bSDavid Gibson 
349430f4b05bSDavid Gibson     object_property_add_str(obj, "resize-hpt",
3495d2623129SMarkus Armbruster                             spapr_get_resize_hpt, spapr_set_resize_hpt);
349630f4b05bSDavid Gibson     object_property_set_description(obj, "resize-hpt",
34977eecec7dSMarkus Armbruster                                     "Resizing of the Hash Page Table (enabled, disabled, required)");
349864a7b8deSFelipe Franciosi     object_property_add_uint32_ptr(obj, "vsmt",
3499d2623129SMarkus Armbruster                                    &spapr->vsmt, OBJ_PROP_FLAG_READWRITE);
3500fa98fbfcSSam Bobroff     object_property_set_description(obj, "vsmt",
3501fa98fbfcSSam Bobroff                                     "Virtual SMT: KVM behaves as if this were"
35027eecec7dSMarkus Armbruster                                     " the host's SMT mode");
350364a7b8deSFelipe Franciosi 
3504fcad0d21SAlexey Kardashevskiy     object_property_add_bool(obj, "vfio-no-msix-emulation",
3505d2623129SMarkus Armbruster                              spapr_get_msix_emulation, NULL);
35063ba3d0bcSCédric Le Goater 
350764a7b8deSFelipe Franciosi     object_property_add_uint64_ptr(obj, "kernel-addr",
3508d2623129SMarkus Armbruster                                    &spapr->kernel_addr, OBJ_PROP_FLAG_READWRITE);
350987262806SAlexey Kardashevskiy     object_property_set_description(obj, "kernel-addr",
351087262806SAlexey Kardashevskiy                                     stringify(KERNEL_LOAD_ADDR)
35117eecec7dSMarkus Armbruster                                     " for -kernel is the default");
351287262806SAlexey Kardashevskiy     spapr->kernel_addr = KERNEL_LOAD_ADDR;
3513fc8c745dSAlexey Kardashevskiy 
3514fc8c745dSAlexey Kardashevskiy     object_property_add_bool(obj, "x-vof", spapr_get_vof, spapr_set_vof);
3515fc8c745dSAlexey Kardashevskiy     object_property_set_description(obj, "x-vof",
3516fc8c745dSAlexey Kardashevskiy                                     "Enable Virtual Open Firmware (experimental)");
3517fc8c745dSAlexey Kardashevskiy 
35183ba3d0bcSCédric Le Goater     /* The machine class defines the default interrupt controller mode */
35193ba3d0bcSCédric Le Goater     spapr->irq = smc->irq;
35203ba3d0bcSCédric Le Goater     object_property_add_str(obj, "ic-mode", spapr_get_ic_mode,
3521d2623129SMarkus Armbruster                             spapr_set_ic_mode);
35223ba3d0bcSCédric Le Goater     object_property_set_description(obj, "ic-mode",
35237eecec7dSMarkus Armbruster                  "Specifies the interrupt controller mode (xics, xive, dual)");
352427461d69SPrasad J Pandit 
352527461d69SPrasad J Pandit     object_property_add_str(obj, "host-model",
3526d2623129SMarkus Armbruster         spapr_get_host_model, spapr_set_host_model);
352727461d69SPrasad J Pandit     object_property_set_description(obj, "host-model",
35287eecec7dSMarkus Armbruster         "Host model to advertise in guest device tree");
352927461d69SPrasad J Pandit     object_property_add_str(obj, "host-serial",
3530d2623129SMarkus Armbruster         spapr_get_host_serial, spapr_set_host_serial);
353127461d69SPrasad J Pandit     object_property_set_description(obj, "host-serial",
35327eecec7dSMarkus Armbruster         "Host serial number to advertise in guest device tree");
353323825581SEduardo Habkost }
353423825581SEduardo Habkost 
spapr_machine_finalizefn(Object * obj)353587bbdd9cSDavid Gibson static void spapr_machine_finalizefn(Object *obj)
353687bbdd9cSDavid Gibson {
3537ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
353887bbdd9cSDavid Gibson 
353987bbdd9cSDavid Gibson     g_free(spapr->kvm_type);
354087bbdd9cSDavid Gibson }
354187bbdd9cSDavid Gibson 
spapr_do_system_reset_on_cpu(CPUState * cs,run_on_cpu_data arg)35421c7ad77eSNicholas Piggin void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg)
354334316482SAlexey Kardashevskiy {
35440e236d34SNicholas Piggin     SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
3545794511bcSPhilippe Mathieu-Daudé     CPUPPCState *env = cpu_env(cs);
35460e236d34SNicholas Piggin 
354734316482SAlexey Kardashevskiy     cpu_synchronize_state(cs);
35480e236d34SNicholas Piggin     /* If FWNMI is inactive, addr will be -1, which will deliver to 0x100 */
35490e236d34SNicholas Piggin     if (spapr->fwnmi_system_reset_addr != -1) {
35500e236d34SNicholas Piggin         uint64_t rtas_addr, addr;
35510e236d34SNicholas Piggin 
35520e236d34SNicholas Piggin         /* get rtas addr from fdt */
35530e236d34SNicholas Piggin         rtas_addr = spapr_get_rtas_addr();
35540e236d34SNicholas Piggin         if (!rtas_addr) {
35550e236d34SNicholas Piggin             qemu_system_guest_panicked(NULL);
35560e236d34SNicholas Piggin             return;
35570e236d34SNicholas Piggin         }
35580e236d34SNicholas Piggin 
35590e236d34SNicholas Piggin         addr = rtas_addr + RTAS_ERROR_LOG_MAX + cs->cpu_index * sizeof(uint64_t)*2;
35600e236d34SNicholas Piggin         stq_be_phys(&address_space_memory, addr, env->gpr[3]);
35610e236d34SNicholas Piggin         stq_be_phys(&address_space_memory, addr + sizeof(uint64_t), 0);
35620e236d34SNicholas Piggin         env->gpr[3] = addr;
35630e236d34SNicholas Piggin     }
3564b5b7f391SNicholas Piggin     ppc_cpu_do_system_reset(cs);
3565b5b7f391SNicholas Piggin     if (spapr->fwnmi_system_reset_addr != -1) {
3566b5b7f391SNicholas Piggin         env->nip = spapr->fwnmi_system_reset_addr;
3567b5b7f391SNicholas Piggin     }
356834316482SAlexey Kardashevskiy }
356934316482SAlexey Kardashevskiy 
spapr_nmi(NMIState * n,int cpu_index,Error ** errp)357034316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp)
357134316482SAlexey Kardashevskiy {
357234316482SAlexey Kardashevskiy     CPUState *cs;
357334316482SAlexey Kardashevskiy 
357434316482SAlexey Kardashevskiy     CPU_FOREACH(cs) {
35751c7ad77eSNicholas Piggin         async_run_on_cpu(cs, spapr_do_system_reset_on_cpu, RUN_ON_CPU_NULL);
357634316482SAlexey Kardashevskiy     }
357734316482SAlexey Kardashevskiy }
357834316482SAlexey Kardashevskiy 
spapr_lmb_dt_populate(SpaprDrc * drc,SpaprMachineState * spapr,void * fdt,int * fdt_start_offset,Error ** errp)3579ce2918cbSDavid Gibson int spapr_lmb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
358062d38c9bSGreg Kurz                           void *fdt, int *fdt_start_offset, Error **errp)
358162d38c9bSGreg Kurz {
358262d38c9bSGreg Kurz     uint64_t addr;
358362d38c9bSGreg Kurz     uint32_t node;
358462d38c9bSGreg Kurz 
358562d38c9bSGreg Kurz     addr = spapr_drc_index(drc) * SPAPR_MEMORY_BLOCK_SIZE;
358662d38c9bSGreg Kurz     node = object_property_get_uint(OBJECT(drc->dev), PC_DIMM_NODE_PROP,
358762d38c9bSGreg Kurz                                     &error_abort);
3588f1aa45ffSDaniel Henrique Barboza     *fdt_start_offset = spapr_dt_memory_node(spapr, fdt, node, addr,
358962d38c9bSGreg Kurz                                              SPAPR_MEMORY_BLOCK_SIZE);
359062d38c9bSGreg Kurz     return 0;
359162d38c9bSGreg Kurz }
359262d38c9bSGreg Kurz 
spapr_add_lmbs(DeviceState * dev,uint64_t addr_start,uint64_t size,bool dedicated_hp_event_source)3593ea042c53SGreg Kurz static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
3594ea042c53SGreg Kurz                            bool dedicated_hp_event_source)
3595c20d332aSBharata B Rao {
3596ce2918cbSDavid Gibson     SpaprDrc *drc;
3597c20d332aSBharata B Rao     uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE;
359862d38c9bSGreg Kurz     int i;
359979b78a6bSMichael Roth     uint64_t addr = addr_start;
360094fd9cbaSLaurent Vivier     bool hotplugged = spapr_drc_hotplugged(dev);
3601c20d332aSBharata B Rao 
3602c20d332aSBharata B Rao     for (i = 0; i < nr_lmbs; i++) {
3603fbf55397SDavid Gibson         drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
3604c20d332aSBharata B Rao                               addr / SPAPR_MEMORY_BLOCK_SIZE);
3605c20d332aSBharata B Rao         g_assert(drc);
3606c20d332aSBharata B Rao 
3607ea042c53SGreg Kurz         /*
3608ea042c53SGreg Kurz          * memory_device_get_free_addr() provided a range of free addresses
3609ea042c53SGreg Kurz          * that doesn't overlap with any existing mapping at pre-plug. The
3610ea042c53SGreg Kurz          * corresponding LMB DRCs are thus assumed to be all attachable.
3611ea042c53SGreg Kurz          */
3612bc370a65SGreg Kurz         spapr_drc_attach(drc, dev);
361394fd9cbaSLaurent Vivier         if (!hotplugged) {
361494fd9cbaSLaurent Vivier             spapr_drc_reset(drc);
361594fd9cbaSLaurent Vivier         }
3616c20d332aSBharata B Rao         addr += SPAPR_MEMORY_BLOCK_SIZE;
3617c20d332aSBharata B Rao     }
36185dd5238cSJianjun Duan     /* send hotplug notification to the
36195dd5238cSJianjun Duan      * guest only in case of hotplugged memory
36205dd5238cSJianjun Duan      */
362194fd9cbaSLaurent Vivier     if (hotplugged) {
362279b78a6bSMichael Roth         if (dedicated_hp_event_source) {
3623fbf55397SDavid Gibson             drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
362479b78a6bSMichael Roth                                   addr_start / SPAPR_MEMORY_BLOCK_SIZE);
362573231f7cSGreg Kurz             g_assert(drc);
362679b78a6bSMichael Roth             spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB,
362779b78a6bSMichael Roth                                                    nr_lmbs,
36280b55aa91SDavid Gibson                                                    spapr_drc_index(drc));
362979b78a6bSMichael Roth         } else {
363079b78a6bSMichael Roth             spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB,
363179b78a6bSMichael Roth                                            nr_lmbs);
363279b78a6bSMichael Roth         }
3633c20d332aSBharata B Rao     }
36345dd5238cSJianjun Duan }
3635c20d332aSBharata B Rao 
spapr_memory_plug(HotplugHandler * hotplug_dev,DeviceState * dev)3636ea042c53SGreg Kurz static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
3637c20d332aSBharata B Rao {
3638ce2918cbSDavid Gibson     SpaprMachineState *ms = SPAPR_MACHINE(hotplug_dev);
3639c20d332aSBharata B Rao     PCDIMMDevice *dimm = PC_DIMM(dev);
3640581778ddSGreg Kurz     uint64_t size, addr;
3641581778ddSGreg Kurz     int64_t slot;
3642ee3a71e3SShivaprasad G Bhat     bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
364304790978SThomas Huth 
3644946d6154SDavid Hildenbrand     size = memory_device_get_region_size(MEMORY_DEVICE(dev), &error_abort);
3645df587133SThomas Huth 
364684fd5496SGreg Kurz     pc_dimm_plug(dimm, MACHINE(ms));
3647c20d332aSBharata B Rao 
3648ee3a71e3SShivaprasad G Bhat     if (!is_nvdimm) {
36499ed442b8SMarc-André Lureau         addr = object_property_get_uint(OBJECT(dimm),
3650271ced1dSGreg Kurz                                         PC_DIMM_ADDR_PROP, &error_abort);
3651ea042c53SGreg Kurz         spapr_add_lmbs(dev, addr, size,
3652ea042c53SGreg Kurz                        spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT));
3653ee3a71e3SShivaprasad G Bhat     } else {
3654581778ddSGreg Kurz         slot = object_property_get_int(OBJECT(dimm),
3655271ced1dSGreg Kurz                                        PC_DIMM_SLOT_PROP, &error_abort);
3656581778ddSGreg Kurz         /* We should have valid slot number at this point */
3657581778ddSGreg Kurz         g_assert(slot >= 0);
3658ea042c53SGreg Kurz         spapr_add_nvdimm(dev, slot);
3659160bb678SGreg Kurz     }
36606e837f98SGreg Kurz }
3661c20d332aSBharata B Rao 
spapr_memory_pre_plug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)3662c871bc70SLaurent Vivier static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
3663c871bc70SLaurent Vivier                                   Error **errp)
3664c871bc70SLaurent Vivier {
3665ce2918cbSDavid Gibson     const SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev);
3666ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
3667ee3a71e3SShivaprasad G Bhat     bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
3668c871bc70SLaurent Vivier     PCDIMMDevice *dimm = PC_DIMM(dev);
36698f1ffe5bSDavid Hildenbrand     Error *local_err = NULL;
367004790978SThomas Huth     uint64_t size;
3671123eec65SDavid Gibson     Object *memdev;
3672123eec65SDavid Gibson     hwaddr pagesize;
3673c871bc70SLaurent Vivier 
36744e8a01bdSDavid Hildenbrand     if (!smc->dr_lmb_enabled) {
36754e8a01bdSDavid Hildenbrand         error_setg(errp, "Memory hotplug not supported for this machine");
36764e8a01bdSDavid Hildenbrand         return;
36774e8a01bdSDavid Hildenbrand     }
36784e8a01bdSDavid Hildenbrand 
3679946d6154SDavid Hildenbrand     size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &local_err);
3680946d6154SDavid Hildenbrand     if (local_err) {
3681946d6154SDavid Hildenbrand         error_propagate(errp, local_err);
368204790978SThomas Huth         return;
368304790978SThomas Huth     }
368404790978SThomas Huth 
3685beb6073fSDaniel Henrique Barboza     if (is_nvdimm) {
3686451c6905SGreg Kurz         if (!spapr_nvdimm_validate(hotplug_dev, NVDIMM(dev), size, errp)) {
3687ee3a71e3SShivaprasad G Bhat             return;
3688ee3a71e3SShivaprasad G Bhat         }
3689beb6073fSDaniel Henrique Barboza     } else if (size % SPAPR_MEMORY_BLOCK_SIZE) {
3690beb6073fSDaniel Henrique Barboza         error_setg(errp, "Hotplugged memory size must be a multiple of "
3691beb6073fSDaniel Henrique Barboza                    "%" PRIu64 " MB", SPAPR_MEMORY_BLOCK_SIZE / MiB);
3692beb6073fSDaniel Henrique Barboza         return;
3693c871bc70SLaurent Vivier     }
3694c871bc70SLaurent Vivier 
3695123eec65SDavid Gibson     memdev = object_property_get_link(OBJECT(dimm), PC_DIMM_MEMDEV_PROP,
3696123eec65SDavid Gibson                                       &error_abort);
3697123eec65SDavid Gibson     pagesize = host_memory_backend_pagesize(MEMORY_BACKEND(memdev));
369835dce34fSGreg Kurz     if (!spapr_check_pagesize(spapr, pagesize, errp)) {
36998f1ffe5bSDavid Hildenbrand         return;
37008f1ffe5bSDavid Hildenbrand     }
37018f1ffe5bSDavid Hildenbrand 
3702d4fdb05bSPhilippe Mathieu-Daudé     pc_dimm_pre_plug(dimm, MACHINE(hotplug_dev), errp);
3703c871bc70SLaurent Vivier }
3704c871bc70SLaurent Vivier 
3705ce2918cbSDavid Gibson struct SpaprDimmState {
37060cffce56SDavid Gibson     PCDIMMDevice *dimm;
3707cf632463SBharata B Rao     uint32_t nr_lmbs;
3708ce2918cbSDavid Gibson     QTAILQ_ENTRY(SpaprDimmState) next;
37090cffce56SDavid Gibson };
37100cffce56SDavid Gibson 
spapr_pending_dimm_unplugs_find(SpaprMachineState * s,PCDIMMDevice * dimm)3711ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_find(SpaprMachineState *s,
37120cffce56SDavid Gibson                                                        PCDIMMDevice *dimm)
37130cffce56SDavid Gibson {
3714ce2918cbSDavid Gibson     SpaprDimmState *dimm_state = NULL;
37150cffce56SDavid Gibson 
37160cffce56SDavid Gibson     QTAILQ_FOREACH(dimm_state, &s->pending_dimm_unplugs, next) {
37170cffce56SDavid Gibson         if (dimm_state->dimm == dimm) {
37180cffce56SDavid Gibson             break;
37190cffce56SDavid Gibson         }
37200cffce56SDavid Gibson     }
37210cffce56SDavid Gibson     return dimm_state;
37220cffce56SDavid Gibson }
37230cffce56SDavid Gibson 
spapr_pending_dimm_unplugs_add(SpaprMachineState * spapr,uint32_t nr_lmbs,PCDIMMDevice * dimm)3724ce2918cbSDavid Gibson static SpaprDimmState *spapr_pending_dimm_unplugs_add(SpaprMachineState *spapr,
37258d5981c4SBharata B Rao                                                       uint32_t nr_lmbs,
37268d5981c4SBharata B Rao                                                       PCDIMMDevice *dimm)
37270cffce56SDavid Gibson {
3728ce2918cbSDavid Gibson     SpaprDimmState *ds = NULL;
37298d5981c4SBharata B Rao 
37308d5981c4SBharata B Rao     /*
37318d5981c4SBharata B Rao      * If this request is for a DIMM whose removal had failed earlier
37328d5981c4SBharata B Rao      * (due to guest's refusal to remove the LMBs), we would have this
37338d5981c4SBharata B Rao      * dimm already in the pending_dimm_unplugs list. In that
37348d5981c4SBharata B Rao      * case don't add again.
37358d5981c4SBharata B Rao      */
37368d5981c4SBharata B Rao     ds = spapr_pending_dimm_unplugs_find(spapr, dimm);
37378d5981c4SBharata B Rao     if (!ds) {
3738b21e2380SMarkus Armbruster         ds = g_new0(SpaprDimmState, 1);
37398d5981c4SBharata B Rao         ds->nr_lmbs = nr_lmbs;
37408d5981c4SBharata B Rao         ds->dimm = dimm;
37418d5981c4SBharata B Rao         QTAILQ_INSERT_HEAD(&spapr->pending_dimm_unplugs, ds, next);
37428d5981c4SBharata B Rao     }
37438d5981c4SBharata B Rao     return ds;
37440cffce56SDavid Gibson }
37450cffce56SDavid Gibson 
spapr_pending_dimm_unplugs_remove(SpaprMachineState * spapr,SpaprDimmState * dimm_state)3746ce2918cbSDavid Gibson static void spapr_pending_dimm_unplugs_remove(SpaprMachineState *spapr,
3747ce2918cbSDavid Gibson                                               SpaprDimmState *dimm_state)
37480cffce56SDavid Gibson {
37490cffce56SDavid Gibson     QTAILQ_REMOVE(&spapr->pending_dimm_unplugs, dimm_state, next);
37500cffce56SDavid Gibson     g_free(dimm_state);
37510cffce56SDavid Gibson }
3752cf632463SBharata B Rao 
spapr_recover_pending_dimm_state(SpaprMachineState * ms,PCDIMMDevice * dimm)3753ce2918cbSDavid Gibson static SpaprDimmState *spapr_recover_pending_dimm_state(SpaprMachineState *ms,
375416ee9980SDaniel Henrique Barboza                                                         PCDIMMDevice *dimm)
375516ee9980SDaniel Henrique Barboza {
3756ce2918cbSDavid Gibson     SpaprDrc *drc;
3757946d6154SDavid Hildenbrand     uint64_t size = memory_device_get_region_size(MEMORY_DEVICE(dimm),
3758946d6154SDavid Hildenbrand                                                   &error_abort);
375916ee9980SDaniel Henrique Barboza     uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE;
376016ee9980SDaniel Henrique Barboza     uint32_t avail_lmbs = 0;
376116ee9980SDaniel Henrique Barboza     uint64_t addr_start, addr;
376216ee9980SDaniel Henrique Barboza     int i;
376316ee9980SDaniel Henrique Barboza 
376465226afdSGreg Kurz     addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP,
376516ee9980SDaniel Henrique Barboza                                           &error_abort);
376616ee9980SDaniel Henrique Barboza 
376716ee9980SDaniel Henrique Barboza     addr = addr_start;
376816ee9980SDaniel Henrique Barboza     for (i = 0; i < nr_lmbs; i++) {
3769fbf55397SDavid Gibson         drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
377016ee9980SDaniel Henrique Barboza                               addr / SPAPR_MEMORY_BLOCK_SIZE);
377116ee9980SDaniel Henrique Barboza         g_assert(drc);
3772454b580aSDavid Gibson         if (drc->dev) {
377316ee9980SDaniel Henrique Barboza             avail_lmbs++;
377416ee9980SDaniel Henrique Barboza         }
377516ee9980SDaniel Henrique Barboza         addr += SPAPR_MEMORY_BLOCK_SIZE;
377616ee9980SDaniel Henrique Barboza     }
377716ee9980SDaniel Henrique Barboza 
37788d5981c4SBharata B Rao     return spapr_pending_dimm_unplugs_add(ms, avail_lmbs, dimm);
377916ee9980SDaniel Henrique Barboza }
378016ee9980SDaniel Henrique Barboza 
spapr_memory_unplug_rollback(SpaprMachineState * spapr,DeviceState * dev)3781eb7f80fdSDaniel Henrique Barboza void spapr_memory_unplug_rollback(SpaprMachineState *spapr, DeviceState *dev)
3782fe1831efSDaniel Henrique Barboza {
3783fe1831efSDaniel Henrique Barboza     SpaprDimmState *ds;
3784fe1831efSDaniel Henrique Barboza     PCDIMMDevice *dimm;
3785fe1831efSDaniel Henrique Barboza     SpaprDrc *drc;
3786fe1831efSDaniel Henrique Barboza     uint32_t nr_lmbs;
3787fe1831efSDaniel Henrique Barboza     uint64_t size, addr_start, addr;
3788fe1831efSDaniel Henrique Barboza     int i;
3789fe1831efSDaniel Henrique Barboza 
3790fe1831efSDaniel Henrique Barboza     if (!dev) {
3791fe1831efSDaniel Henrique Barboza         return;
3792fe1831efSDaniel Henrique Barboza     }
3793fe1831efSDaniel Henrique Barboza 
3794fe1831efSDaniel Henrique Barboza     dimm = PC_DIMM(dev);
3795fe1831efSDaniel Henrique Barboza     ds = spapr_pending_dimm_unplugs_find(spapr, dimm);
3796fe1831efSDaniel Henrique Barboza 
3797fe1831efSDaniel Henrique Barboza     /*
3798fe1831efSDaniel Henrique Barboza      * 'ds == NULL' would mean that the DIMM doesn't have a pending
3799fe1831efSDaniel Henrique Barboza      * unplug state, but one of its DRC is marked as unplug_requested.
3800fe1831efSDaniel Henrique Barboza      * This is bad and weird enough to g_assert() out.
3801fe1831efSDaniel Henrique Barboza      */
3802fe1831efSDaniel Henrique Barboza     g_assert(ds);
3803fe1831efSDaniel Henrique Barboza 
3804fe1831efSDaniel Henrique Barboza     spapr_pending_dimm_unplugs_remove(spapr, ds);
3805fe1831efSDaniel Henrique Barboza 
3806fe1831efSDaniel Henrique Barboza     size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &error_abort);
3807fe1831efSDaniel Henrique Barboza     nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE;
3808fe1831efSDaniel Henrique Barboza 
3809fe1831efSDaniel Henrique Barboza     addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP,
3810fe1831efSDaniel Henrique Barboza                                           &error_abort);
3811fe1831efSDaniel Henrique Barboza 
3812fe1831efSDaniel Henrique Barboza     addr = addr_start;
3813fe1831efSDaniel Henrique Barboza     for (i = 0; i < nr_lmbs; i++) {
3814fe1831efSDaniel Henrique Barboza         drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
3815fe1831efSDaniel Henrique Barboza                               addr / SPAPR_MEMORY_BLOCK_SIZE);
3816fe1831efSDaniel Henrique Barboza         g_assert(drc);
3817fe1831efSDaniel Henrique Barboza 
3818fe1831efSDaniel Henrique Barboza         drc->unplug_requested = false;
3819fe1831efSDaniel Henrique Barboza         addr += SPAPR_MEMORY_BLOCK_SIZE;
3820fe1831efSDaniel Henrique Barboza     }
3821eb7f80fdSDaniel Henrique Barboza 
3822eb7f80fdSDaniel Henrique Barboza     /*
3823eb7f80fdSDaniel Henrique Barboza      * Tell QAPI that something happened and the memory
38240f910b87SPhilippe Mathieu-Daudé      * hotunplug wasn't successful.
3825eb7f80fdSDaniel Henrique Barboza      */
3826047f2ca1SMarkus Armbruster     qapi_event_send_device_unplug_guest_error(dev->id,
38274b08cd56SDaniel Henrique Barboza                                               dev->canonical_path);
3828fe1831efSDaniel Henrique Barboza }
3829fe1831efSDaniel Henrique Barboza 
383031834723SDaniel Henrique Barboza /* Callback to be called during DRC release. */
spapr_lmb_release(DeviceState * dev)383131834723SDaniel Henrique Barboza void spapr_lmb_release(DeviceState *dev)
3832cf632463SBharata B Rao {
38333ec71474SDavid Hildenbrand     HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
3834ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl);
3835ce2918cbSDavid Gibson     SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
3836cf632463SBharata B Rao 
383716ee9980SDaniel Henrique Barboza     /* This information will get lost if a migration occurs
383816ee9980SDaniel Henrique Barboza      * during the unplug process. In this case recover it. */
383916ee9980SDaniel Henrique Barboza     if (ds == NULL) {
384016ee9980SDaniel Henrique Barboza         ds = spapr_recover_pending_dimm_state(spapr, PC_DIMM(dev));
38418d5981c4SBharata B Rao         g_assert(ds);
3842454b580aSDavid Gibson         /* The DRC being examined by the caller at least must be counted */
3843454b580aSDavid Gibson         g_assert(ds->nr_lmbs);
384416ee9980SDaniel Henrique Barboza     }
3845454b580aSDavid Gibson 
3846454b580aSDavid Gibson     if (--ds->nr_lmbs) {
3847cf632463SBharata B Rao         return;
3848cf632463SBharata B Rao     }
3849cf632463SBharata B Rao 
3850cf632463SBharata B Rao     /*
3851cf632463SBharata B Rao      * Now that all the LMBs have been removed by the guest, call the
38523ec71474SDavid Hildenbrand      * unplug handler chain. This can never fail.
3853cf632463SBharata B Rao      */
38543ec71474SDavid Hildenbrand     hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
385507578b0aSDavid Hildenbrand     object_unparent(OBJECT(dev));
38563ec71474SDavid Hildenbrand }
38573ec71474SDavid Hildenbrand 
spapr_memory_unplug(HotplugHandler * hotplug_dev,DeviceState * dev)38583ec71474SDavid Hildenbrand static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
38593ec71474SDavid Hildenbrand {
3860ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
3861ce2918cbSDavid Gibson     SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
38623ec71474SDavid Hildenbrand 
3863df2d7ca7SGreg Kurz     /* We really shouldn't get this far without anything to unplug */
3864df2d7ca7SGreg Kurz     g_assert(ds);
3865df2d7ca7SGreg Kurz 
3866fd3416f5SDavid Hildenbrand     pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev));
3867981c3dcdSMarkus Armbruster     qdev_unrealize(dev);
38682a129767SDaniel Henrique Barboza     spapr_pending_dimm_unplugs_remove(spapr, ds);
3869cf632463SBharata B Rao }
3870cf632463SBharata B Rao 
spapr_memory_unplug_request(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)3871cf632463SBharata B Rao static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
3872cf632463SBharata B Rao                                         DeviceState *dev, Error **errp)
3873cf632463SBharata B Rao {
3874ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
3875cf632463SBharata B Rao     PCDIMMDevice *dimm = PC_DIMM(dev);
387604790978SThomas Huth     uint32_t nr_lmbs;
387704790978SThomas Huth     uint64_t size, addr_start, addr;
38780cffce56SDavid Gibson     int i;
3879ce2918cbSDavid Gibson     SpaprDrc *drc;
388004790978SThomas Huth 
3881ee3a71e3SShivaprasad G Bhat     if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
3882dcfe4805SMarkus Armbruster         error_setg(errp, "nvdimm device hot unplug is not supported yet.");
3883dcfe4805SMarkus Armbruster         return;
3884ee3a71e3SShivaprasad G Bhat     }
3885ee3a71e3SShivaprasad G Bhat 
3886946d6154SDavid Hildenbrand     size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &error_abort);
388704790978SThomas Huth     nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE;
388804790978SThomas Huth 
38899ed442b8SMarc-André Lureau     addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP,
3890271ced1dSGreg Kurz                                           &error_abort);
3891cf632463SBharata B Rao 
38922a129767SDaniel Henrique Barboza     /*
38932a129767SDaniel Henrique Barboza      * An existing pending dimm state for this DIMM means that there is an
38942a129767SDaniel Henrique Barboza      * unplug operation in progress, waiting for the spapr_lmb_release
38952a129767SDaniel Henrique Barboza      * callback to complete the job (BQL can't cover that far). In this case,
38962a129767SDaniel Henrique Barboza      * bail out to avoid detaching DRCs that were already released.
38972a129767SDaniel Henrique Barboza      */
38982a129767SDaniel Henrique Barboza     if (spapr_pending_dimm_unplugs_find(spapr, dimm)) {
3899dcfe4805SMarkus Armbruster         error_setg(errp, "Memory unplug already in progress for device %s",
39002a129767SDaniel Henrique Barboza                    dev->id);
3901dcfe4805SMarkus Armbruster         return;
39022a129767SDaniel Henrique Barboza     }
39032a129767SDaniel Henrique Barboza 
39048d5981c4SBharata B Rao     spapr_pending_dimm_unplugs_add(spapr, nr_lmbs, dimm);
39050cffce56SDavid Gibson 
39060cffce56SDavid Gibson     addr = addr_start;
39070cffce56SDavid Gibson     for (i = 0; i < nr_lmbs; i++) {
3908fbf55397SDavid Gibson         drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
39090cffce56SDavid Gibson                               addr / SPAPR_MEMORY_BLOCK_SIZE);
39100cffce56SDavid Gibson         g_assert(drc);
39110cffce56SDavid Gibson 
3912a03509cdSDaniel Henrique Barboza         spapr_drc_unplug_request(drc);
39130cffce56SDavid Gibson         addr += SPAPR_MEMORY_BLOCK_SIZE;
39140cffce56SDavid Gibson     }
39150cffce56SDavid Gibson 
3916fbf55397SDavid Gibson     drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
39170cffce56SDavid Gibson                           addr_start / SPAPR_MEMORY_BLOCK_SIZE);
39180cffce56SDavid Gibson     spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB,
39190b55aa91SDavid Gibson                                               nr_lmbs, spapr_drc_index(drc));
3920cf632463SBharata B Rao }
3921cf632463SBharata B Rao 
3922765d1bddSDavid Gibson /* Callback to be called during DRC release. */
spapr_core_release(DeviceState * dev)3923765d1bddSDavid Gibson void spapr_core_release(DeviceState *dev)
3924ff9006ddSIgor Mammedov {
3925a4261be1SDavid Hildenbrand     HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
3926a4261be1SDavid Hildenbrand 
3927a4261be1SDavid Hildenbrand     /* Call the unplug handler chain. This can never fail. */
3928a4261be1SDavid Hildenbrand     hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
392907578b0aSDavid Hildenbrand     object_unparent(OBJECT(dev));
3930a4261be1SDavid Hildenbrand }
3931a4261be1SDavid Hildenbrand 
spapr_core_unplug(HotplugHandler * hotplug_dev,DeviceState * dev)3932a4261be1SDavid Hildenbrand static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
3933a4261be1SDavid Hildenbrand {
3934a4261be1SDavid Hildenbrand     MachineState *ms = MACHINE(hotplug_dev);
3935ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms);
3936ff9006ddSIgor Mammedov     CPUCore *cc = CPU_CORE(dev);
3937535455fdSIgor Mammedov     CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL);
3938ff9006ddSIgor Mammedov 
393946f7afa3SGreg Kurz     if (smc->pre_2_10_has_unused_icps) {
3940ce2918cbSDavid Gibson         SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
394146f7afa3SGreg Kurz         int i;
394246f7afa3SGreg Kurz 
394346f7afa3SGreg Kurz         for (i = 0; i < cc->nr_threads; i++) {
394494ad93bdSGreg Kurz             CPUState *cs = CPU(sc->threads[i]);
394546f7afa3SGreg Kurz 
394646f7afa3SGreg Kurz             pre_2_10_vmstate_register_dummy_icp(cs->cpu_index);
394746f7afa3SGreg Kurz         }
394846f7afa3SGreg Kurz     }
394946f7afa3SGreg Kurz 
395007572c06SGreg Kurz     assert(core_slot);
3951535455fdSIgor Mammedov     core_slot->cpu = NULL;
3952981c3dcdSMarkus Armbruster     qdev_unrealize(dev);
3953ff9006ddSIgor Mammedov }
3954ff9006ddSIgor Mammedov 
3955115debf2SIgor Mammedov static
spapr_core_unplug_request(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)3956115debf2SIgor Mammedov void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev,
3957ff9006ddSIgor Mammedov                                Error **errp)
3958ff9006ddSIgor Mammedov {
3959ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
3960535455fdSIgor Mammedov     int index;
3961ce2918cbSDavid Gibson     SpaprDrc *drc;
3962535455fdSIgor Mammedov     CPUCore *cc = CPU_CORE(dev);
3963ff9006ddSIgor Mammedov 
3964535455fdSIgor Mammedov     if (!spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index)) {
3965535455fdSIgor Mammedov         error_setg(errp, "Unable to find CPU core with core-id: %d",
3966535455fdSIgor Mammedov                    cc->core_id);
3967535455fdSIgor Mammedov         return;
3968535455fdSIgor Mammedov     }
3969ff9006ddSIgor Mammedov     if (index == 0) {
3970ff9006ddSIgor Mammedov         error_setg(errp, "Boot CPU core may not be unplugged");
3971ff9006ddSIgor Mammedov         return;
3972ff9006ddSIgor Mammedov     }
3973ff9006ddSIgor Mammedov 
39745d0fb150SGreg Kurz     drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU,
39755d0fb150SGreg Kurz                           spapr_vcpu_id(spapr, cc->core_id));
3976ff9006ddSIgor Mammedov     g_assert(drc);
3977ff9006ddSIgor Mammedov 
397847c8c915SGreg Kurz     if (!spapr_drc_unplug_requested(drc)) {
3979a03509cdSDaniel Henrique Barboza         spapr_drc_unplug_request(drc);
3980ff9006ddSIgor Mammedov     }
39812b18fc79SDaniel Henrique Barboza 
39822b18fc79SDaniel Henrique Barboza     /*
39832b18fc79SDaniel Henrique Barboza      * spapr_hotplug_req_remove_by_index is left unguarded, out of the
39842b18fc79SDaniel Henrique Barboza      * "!spapr_drc_unplug_requested" check, to allow for multiple IRQ
39852b18fc79SDaniel Henrique Barboza      * pulses removing the same CPU. Otherwise, in an failed hotunplug
39862b18fc79SDaniel Henrique Barboza      * attempt (e.g. the kernel will refuse to remove the last online
39872b18fc79SDaniel Henrique Barboza      * CPU), we will never attempt it again because unplug_requested
39882b18fc79SDaniel Henrique Barboza      * will still be 'true' in that case.
39892b18fc79SDaniel Henrique Barboza      */
39902b18fc79SDaniel Henrique Barboza     spapr_hotplug_req_remove_by_index(drc);
399147c8c915SGreg Kurz }
3992ff9006ddSIgor Mammedov 
spapr_core_dt_populate(SpaprDrc * drc,SpaprMachineState * spapr,void * fdt,int * fdt_start_offset,Error ** errp)3993ce2918cbSDavid Gibson int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
3994345b12b9SGreg Kurz                            void *fdt, int *fdt_start_offset, Error **errp)
3995345b12b9SGreg Kurz {
3996ce2918cbSDavid Gibson     SpaprCpuCore *core = SPAPR_CPU_CORE(drc->dev);
3997345b12b9SGreg Kurz     CPUState *cs = CPU(core->threads[0]);
3998345b12b9SGreg Kurz     PowerPCCPU *cpu = POWERPC_CPU(cs);
3999345b12b9SGreg Kurz     DeviceClass *dc = DEVICE_GET_CLASS(cs);
4000345b12b9SGreg Kurz     int id = spapr_get_vcpu_id(cpu);
40017265bc3eSDaniel Henrique Barboza     g_autofree char *nodename = NULL;
4002345b12b9SGreg Kurz     int offset;
4003345b12b9SGreg Kurz 
4004345b12b9SGreg Kurz     nodename = g_strdup_printf("%s@%x", dc->fw_name, id);
4005345b12b9SGreg Kurz     offset = fdt_add_subnode(fdt, 0, nodename);
4006345b12b9SGreg Kurz 
400791335a5eSDavid Gibson     spapr_dt_cpu(cs, fdt, offset, spapr);
4008345b12b9SGreg Kurz 
4009a85bb34eSDaniel Henrique Barboza     /*
4010a85bb34eSDaniel Henrique Barboza      * spapr_dt_cpu() does not fill the 'name' property in the
4011a85bb34eSDaniel Henrique Barboza      * CPU node. The function is called during boot process, before
4012a85bb34eSDaniel Henrique Barboza      * and after CAS, and overwriting the 'name' property written
4013a85bb34eSDaniel Henrique Barboza      * by SLOF is not allowed.
4014a85bb34eSDaniel Henrique Barboza      *
4015a85bb34eSDaniel Henrique Barboza      * Write it manually after spapr_dt_cpu(). This makes the hotplug
4016a85bb34eSDaniel Henrique Barboza      * CPUs more compatible with the coldplugged ones, which have
4017a85bb34eSDaniel Henrique Barboza      * the 'name' property. Linux Kernel also relies on this
4018a85bb34eSDaniel Henrique Barboza      * property to identify CPU nodes.
4019a85bb34eSDaniel Henrique Barboza      */
4020a85bb34eSDaniel Henrique Barboza     _FDT((fdt_setprop_string(fdt, offset, "name", nodename)));
4021a85bb34eSDaniel Henrique Barboza 
4022345b12b9SGreg Kurz     *fdt_start_offset = offset;
4023345b12b9SGreg Kurz     return 0;
4024345b12b9SGreg Kurz }
4025345b12b9SGreg Kurz 
spapr_core_plug(HotplugHandler * hotplug_dev,DeviceState * dev)4026f9b43958SGreg Kurz static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
4027ff9006ddSIgor Mammedov {
4028ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
4029ff9006ddSIgor Mammedov     MachineClass *mc = MACHINE_GET_CLASS(spapr);
4030ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
4031ce2918cbSDavid Gibson     SpaprCpuCore *core = SPAPR_CPU_CORE(OBJECT(dev));
4032ff9006ddSIgor Mammedov     CPUCore *cc = CPU_CORE(dev);
4033ce2918cbSDavid Gibson     SpaprDrc *drc;
4034535455fdSIgor Mammedov     CPUArchId *core_slot;
4035535455fdSIgor Mammedov     int index;
403694fd9cbaSLaurent Vivier     bool hotplugged = spapr_drc_hotplugged(dev);
4037b1e81567SGreg Kurz     int i;
4038ff9006ddSIgor Mammedov 
4039535455fdSIgor Mammedov     core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index);
4040f9b43958SGreg Kurz     g_assert(core_slot); /* Already checked in spapr_core_pre_plug() */
4041f9b43958SGreg Kurz 
40425d0fb150SGreg Kurz     drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU,
40435d0fb150SGreg Kurz                           spapr_vcpu_id(spapr, cc->core_id));
4044ff9006ddSIgor Mammedov 
4045c5514d0eSIgor Mammedov     g_assert(drc || !mc->has_hotpluggable_cpus);
4046ff9006ddSIgor Mammedov 
4047e49c63d5SGreg Kurz     if (drc) {
4048f9b43958SGreg Kurz         /*
4049f9b43958SGreg Kurz          * spapr_core_pre_plug() already buys us this is a brand new
4050f9b43958SGreg Kurz          * core being plugged into a free slot. Nothing should already
4051f9b43958SGreg Kurz          * be attached to the corresponding DRC.
4052f9b43958SGreg Kurz          */
4053bc370a65SGreg Kurz         spapr_drc_attach(drc, dev);
4054ff9006ddSIgor Mammedov 
405594fd9cbaSLaurent Vivier         if (hotplugged) {
4056ff9006ddSIgor Mammedov             /*
405794fd9cbaSLaurent Vivier              * Send hotplug notification interrupt to the guest only
405894fd9cbaSLaurent Vivier              * in case of hotplugged CPUs.
4059ff9006ddSIgor Mammedov              */
4060ff9006ddSIgor Mammedov             spapr_hotplug_req_add_by_index(drc);
406194fd9cbaSLaurent Vivier         } else {
406294fd9cbaSLaurent Vivier             spapr_drc_reset(drc);
4063ff9006ddSIgor Mammedov         }
406494fd9cbaSLaurent Vivier     }
406594fd9cbaSLaurent Vivier 
406697e03106SPhilippe Mathieu-Daudé     core_slot->cpu = CPU(dev);
406746f7afa3SGreg Kurz 
4068b1e81567SGreg Kurz     /*
4069b1e81567SGreg Kurz      * Set compatibility mode to match the boot CPU, which was either set
407037641213SGreg Kurz      * by the machine reset code or by CAS. This really shouldn't fail at
407137641213SGreg Kurz      * this point.
4072b1e81567SGreg Kurz      */
4073b1e81567SGreg Kurz     if (hotplugged) {
4074b1e81567SGreg Kurz         for (i = 0; i < cc->nr_threads; i++) {
407537641213SGreg Kurz             ppc_set_compat(core->threads[i], POWERPC_CPU(first_cpu)->compat_pvr,
407637641213SGreg Kurz                            &error_abort);
4077b1e81567SGreg Kurz         }
4078b1e81567SGreg Kurz     }
40791b4ab514SGreg Kurz 
40801b4ab514SGreg Kurz     if (smc->pre_2_10_has_unused_icps) {
40811b4ab514SGreg Kurz         for (i = 0; i < cc->nr_threads; i++) {
408297e03106SPhilippe Mathieu-Daudé             CPUState *cs = CPU(core->threads[i]);
40831b4ab514SGreg Kurz             pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index);
40841b4ab514SGreg Kurz         }
40851b4ab514SGreg Kurz     }
4086ff9006ddSIgor Mammedov }
4087ff9006ddSIgor Mammedov 
spapr_core_pre_plug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)4088ff9006ddSIgor Mammedov static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
4089ff9006ddSIgor Mammedov                                 Error **errp)
4090ff9006ddSIgor Mammedov {
4091ff9006ddSIgor Mammedov     MachineState *machine = MACHINE(OBJECT(hotplug_dev));
4092ff9006ddSIgor Mammedov     MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev);
4093ff9006ddSIgor Mammedov     CPUCore *cc = CPU_CORE(dev);
40942e9c10ebSIgor Mammedov     const char *base_core_type = spapr_get_cpu_core_type(machine->cpu_type);
4095ff9006ddSIgor Mammedov     const char *type = object_get_typename(OBJECT(dev));
4096535455fdSIgor Mammedov     CPUArchId *core_slot;
4097535455fdSIgor Mammedov     int index;
4098fe6b6346SLike Xu     unsigned int smp_threads = machine->smp.threads;
4099ff9006ddSIgor Mammedov 
4100c5514d0eSIgor Mammedov     if (dev->hotplugged && !mc->has_hotpluggable_cpus) {
4101dcfe4805SMarkus Armbruster         error_setg(errp, "CPU hotplug not supported for this machine");
4102dcfe4805SMarkus Armbruster         return;
4103ff9006ddSIgor Mammedov     }
4104ff9006ddSIgor Mammedov 
4105ff9006ddSIgor Mammedov     if (strcmp(base_core_type, type)) {
4106dcfe4805SMarkus Armbruster         error_setg(errp, "CPU core type should be %s", base_core_type);
4107dcfe4805SMarkus Armbruster         return;
4108ff9006ddSIgor Mammedov     }
4109ff9006ddSIgor Mammedov 
4110ff9006ddSIgor Mammedov     if (cc->core_id % smp_threads) {
4111dcfe4805SMarkus Armbruster         error_setg(errp, "invalid core id %d", cc->core_id);
4112dcfe4805SMarkus Armbruster         return;
4113ff9006ddSIgor Mammedov     }
4114ff9006ddSIgor Mammedov 
4115459264efSDavid Gibson     /*
4116459264efSDavid Gibson      * In general we should have homogeneous threads-per-core, but old
4117459264efSDavid Gibson      * (pre hotplug support) machine types allow the last core to have
4118459264efSDavid Gibson      * reduced threads as a compatibility hack for when we allowed
4119459264efSDavid Gibson      * total vcpus not a multiple of threads-per-core.
4120459264efSDavid Gibson      */
4121459264efSDavid Gibson     if (mc->has_hotpluggable_cpus && (cc->nr_threads != smp_threads)) {
4122dcfe4805SMarkus Armbruster         error_setg(errp, "invalid nr-threads %d, must be %d", cc->nr_threads,
4123dcfe4805SMarkus Armbruster                    smp_threads);
4124dcfe4805SMarkus Armbruster         return;
41258149e299SDavid Gibson     }
41268149e299SDavid Gibson 
4127535455fdSIgor Mammedov     core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index);
4128535455fdSIgor Mammedov     if (!core_slot) {
4129dcfe4805SMarkus Armbruster         error_setg(errp, "core id %d out of range", cc->core_id);
4130dcfe4805SMarkus Armbruster         return;
4131ff9006ddSIgor Mammedov     }
4132ff9006ddSIgor Mammedov 
4133535455fdSIgor Mammedov     if (core_slot->cpu) {
4134dcfe4805SMarkus Armbruster         error_setg(errp, "core %d already populated", cc->core_id);
4135dcfe4805SMarkus Armbruster         return;
4136ff9006ddSIgor Mammedov     }
4137ff9006ddSIgor Mammedov 
4138dcfe4805SMarkus Armbruster     numa_cpu_pre_plug(core_slot, dev, errp);
4139ff9006ddSIgor Mammedov }
4140ff9006ddSIgor Mammedov 
spapr_phb_dt_populate(SpaprDrc * drc,SpaprMachineState * spapr,void * fdt,int * fdt_start_offset,Error ** errp)4141ce2918cbSDavid Gibson int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
4142bb2bdd81SGreg Kurz                           void *fdt, int *fdt_start_offset, Error **errp)
4143bb2bdd81SGreg Kurz {
4144ce2918cbSDavid Gibson     SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(drc->dev);
4145bb2bdd81SGreg Kurz     int intc_phandle;
4146bb2bdd81SGreg Kurz 
4147bb2bdd81SGreg Kurz     intc_phandle = spapr_irq_get_phandle(spapr, spapr->fdt_blob, errp);
4148bb2bdd81SGreg Kurz     if (intc_phandle <= 0) {
4149bb2bdd81SGreg Kurz         return -1;
4150bb2bdd81SGreg Kurz     }
4151bb2bdd81SGreg Kurz 
41528cbe71ecSDavid Gibson     if (spapr_dt_phb(spapr, sphb, intc_phandle, fdt, fdt_start_offset)) {
4153bb2bdd81SGreg Kurz         error_setg(errp, "unable to create FDT node for PHB %d", sphb->index);
4154bb2bdd81SGreg Kurz         return -1;
4155bb2bdd81SGreg Kurz     }
4156bb2bdd81SGreg Kurz 
4157bb2bdd81SGreg Kurz     /* generally SLOF creates these, for hotplug it's up to QEMU */
4158bb2bdd81SGreg Kurz     _FDT(fdt_setprop_string(fdt, *fdt_start_offset, "name", "pci"));
4159bb2bdd81SGreg Kurz 
4160bb2bdd81SGreg Kurz     return 0;
4161bb2bdd81SGreg Kurz }
4162bb2bdd81SGreg Kurz 
spapr_phb_pre_plug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)4163f5598c92SGreg Kurz static bool spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
4164bb2bdd81SGreg Kurz                                Error **errp)
4165bb2bdd81SGreg Kurz {
4166ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
4167ce2918cbSDavid Gibson     SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
4168ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
4169bb2bdd81SGreg Kurz     const unsigned windows_supported = spapr_phb_windows_supported(sphb);
41709a070699SGreg Kurz     SpaprDrc *drc;
4171bb2bdd81SGreg Kurz 
4172bb2bdd81SGreg Kurz     if (dev->hotplugged && !smc->dr_phb_enabled) {
4173bb2bdd81SGreg Kurz         error_setg(errp, "PHB hotplug not supported for this machine");
4174f5598c92SGreg Kurz         return false;
4175bb2bdd81SGreg Kurz     }
4176bb2bdd81SGreg Kurz 
4177bb2bdd81SGreg Kurz     if (sphb->index == (uint32_t)-1) {
4178bb2bdd81SGreg Kurz         error_setg(errp, "\"index\" for PAPR PHB is mandatory");
4179f5598c92SGreg Kurz         return false;
4180bb2bdd81SGreg Kurz     }
4181bb2bdd81SGreg Kurz 
41829a070699SGreg Kurz     drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index);
41839a070699SGreg Kurz     if (drc && drc->dev) {
41849a070699SGreg Kurz         error_setg(errp, "PHB %d already attached", sphb->index);
41859a070699SGreg Kurz         return false;
41869a070699SGreg Kurz     }
41879a070699SGreg Kurz 
4188bb2bdd81SGreg Kurz     /*
4189bb2bdd81SGreg Kurz      * This will check that sphb->index doesn't exceed the maximum number of
4190bb2bdd81SGreg Kurz      * PHBs for the current machine type.
4191bb2bdd81SGreg Kurz      */
4192f5598c92SGreg Kurz     return
4193bb2bdd81SGreg Kurz         smc->phb_placement(spapr, sphb->index,
4194bb2bdd81SGreg Kurz                            &sphb->buid, &sphb->io_win_addr,
4195bb2bdd81SGreg Kurz                            &sphb->mem_win_addr, &sphb->mem64_win_addr,
4196ec132efaSAlexey Kardashevskiy                            windows_supported, sphb->dma_liobn,
4197ec132efaSAlexey Kardashevskiy                            errp);
4198bb2bdd81SGreg Kurz }
4199bb2bdd81SGreg Kurz 
spapr_phb_plug(HotplugHandler * hotplug_dev,DeviceState * dev)42009a070699SGreg Kurz static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
4201bb2bdd81SGreg Kurz {
4202ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
4203ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
4204ce2918cbSDavid Gibson     SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
4205ce2918cbSDavid Gibson     SpaprDrc *drc;
4206bb2bdd81SGreg Kurz     bool hotplugged = spapr_drc_hotplugged(dev);
4207bb2bdd81SGreg Kurz 
4208bb2bdd81SGreg Kurz     if (!smc->dr_phb_enabled) {
4209bb2bdd81SGreg Kurz         return;
4210bb2bdd81SGreg Kurz     }
4211bb2bdd81SGreg Kurz 
4212bb2bdd81SGreg Kurz     drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index);
4213bb2bdd81SGreg Kurz     /* hotplug hooks should check it's enabled before getting this far */
4214bb2bdd81SGreg Kurz     assert(drc);
4215bb2bdd81SGreg Kurz 
42169a070699SGreg Kurz     /* spapr_phb_pre_plug() already checked the DRC is attachable */
4217bc370a65SGreg Kurz     spapr_drc_attach(drc, dev);
4218bb2bdd81SGreg Kurz 
4219bb2bdd81SGreg Kurz     if (hotplugged) {
4220bb2bdd81SGreg Kurz         spapr_hotplug_req_add_by_index(drc);
4221bb2bdd81SGreg Kurz     } else {
4222bb2bdd81SGreg Kurz         spapr_drc_reset(drc);
4223bb2bdd81SGreg Kurz     }
4224bb2bdd81SGreg Kurz }
4225bb2bdd81SGreg Kurz 
spapr_phb_release(DeviceState * dev)4226bb2bdd81SGreg Kurz void spapr_phb_release(DeviceState *dev)
4227bb2bdd81SGreg Kurz {
4228bb2bdd81SGreg Kurz     HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
4229bb2bdd81SGreg Kurz 
4230bb2bdd81SGreg Kurz     hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
423107578b0aSDavid Hildenbrand     object_unparent(OBJECT(dev));
4232bb2bdd81SGreg Kurz }
4233bb2bdd81SGreg Kurz 
spapr_phb_unplug(HotplugHandler * hotplug_dev,DeviceState * dev)4234bb2bdd81SGreg Kurz static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
4235bb2bdd81SGreg Kurz {
4236981c3dcdSMarkus Armbruster     qdev_unrealize(dev);
4237bb2bdd81SGreg Kurz }
4238bb2bdd81SGreg Kurz 
spapr_phb_unplug_request(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)4239bb2bdd81SGreg Kurz static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev,
4240bb2bdd81SGreg Kurz                                      DeviceState *dev, Error **errp)
4241bb2bdd81SGreg Kurz {
4242ce2918cbSDavid Gibson     SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
4243ce2918cbSDavid Gibson     SpaprDrc *drc;
4244bb2bdd81SGreg Kurz 
4245bb2bdd81SGreg Kurz     drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index);
4246bb2bdd81SGreg Kurz     assert(drc);
4247bb2bdd81SGreg Kurz 
4248bb2bdd81SGreg Kurz     if (!spapr_drc_unplug_requested(drc)) {
4249a03509cdSDaniel Henrique Barboza         spapr_drc_unplug_request(drc);
4250bb2bdd81SGreg Kurz         spapr_hotplug_req_remove_by_index(drc);
42517420033eSDaniel Henrique Barboza     } else {
42527420033eSDaniel Henrique Barboza         error_setg(errp,
42537420033eSDaniel Henrique Barboza                    "PCI Host Bridge unplug already in progress for device %s",
42547420033eSDaniel Henrique Barboza                    dev->id);
4255bb2bdd81SGreg Kurz     }
4256bb2bdd81SGreg Kurz }
4257bb2bdd81SGreg Kurz 
4258ac96807bSGreg Kurz static
spapr_tpm_proxy_pre_plug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)4259ac96807bSGreg Kurz bool spapr_tpm_proxy_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
42600fb6bd07SMichael Roth                               Error **errp)
42610fb6bd07SMichael Roth {
42620fb6bd07SMichael Roth     SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
4263ac96807bSGreg Kurz 
4264ac96807bSGreg Kurz     if (spapr->tpm_proxy != NULL) {
4265ac96807bSGreg Kurz         error_setg(errp, "Only one TPM proxy can be specified for this machine");
4266ac96807bSGreg Kurz         return false;
4267ac96807bSGreg Kurz     }
4268ac96807bSGreg Kurz 
4269ac96807bSGreg Kurz     return true;
4270ac96807bSGreg Kurz }
4271ac96807bSGreg Kurz 
spapr_tpm_proxy_plug(HotplugHandler * hotplug_dev,DeviceState * dev)4272ac96807bSGreg Kurz static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
4273ac96807bSGreg Kurz {
4274ac96807bSGreg Kurz     SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
42750fb6bd07SMichael Roth     SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(dev);
42760fb6bd07SMichael Roth 
4277ac96807bSGreg Kurz     /* Already checked in spapr_tpm_proxy_pre_plug() */
4278ac96807bSGreg Kurz     g_assert(spapr->tpm_proxy == NULL);
42790fb6bd07SMichael Roth 
42800fb6bd07SMichael Roth     spapr->tpm_proxy = tpm_proxy;
42810fb6bd07SMichael Roth }
42820fb6bd07SMichael Roth 
spapr_tpm_proxy_unplug(HotplugHandler * hotplug_dev,DeviceState * dev)42830fb6bd07SMichael Roth static void spapr_tpm_proxy_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
42840fb6bd07SMichael Roth {
42850fb6bd07SMichael Roth     SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
42860fb6bd07SMichael Roth 
4287981c3dcdSMarkus Armbruster     qdev_unrealize(dev);
42880fb6bd07SMichael Roth     object_unparent(OBJECT(dev));
42890fb6bd07SMichael Roth     spapr->tpm_proxy = NULL;
42900fb6bd07SMichael Roth }
42910fb6bd07SMichael Roth 
spapr_machine_device_plug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)4292c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
4293c20d332aSBharata B Rao                                       DeviceState *dev, Error **errp)
4294c20d332aSBharata B Rao {
4295c20d332aSBharata B Rao     if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
4296ea042c53SGreg Kurz         spapr_memory_plug(hotplug_dev, dev);
4297af81cf32SBharata B Rao     } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
4298f9b43958SGreg Kurz         spapr_core_plug(hotplug_dev, dev);
4299bb2bdd81SGreg Kurz     } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
43009a070699SGreg Kurz         spapr_phb_plug(hotplug_dev, dev);
43010fb6bd07SMichael Roth     } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) {
4302ac96807bSGreg Kurz         spapr_tpm_proxy_plug(hotplug_dev, dev);
4303c20d332aSBharata B Rao     }
4304c20d332aSBharata B Rao }
4305c20d332aSBharata B Rao 
spapr_machine_device_unplug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)430688432f44SDavid Hildenbrand static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev,
430788432f44SDavid Hildenbrand                                         DeviceState *dev, Error **errp)
430888432f44SDavid Hildenbrand {
43093ec71474SDavid Hildenbrand     if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
43103ec71474SDavid Hildenbrand         spapr_memory_unplug(hotplug_dev, dev);
4311a4261be1SDavid Hildenbrand     } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
4312a4261be1SDavid Hildenbrand         spapr_core_unplug(hotplug_dev, dev);
4313bb2bdd81SGreg Kurz     } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
4314bb2bdd81SGreg Kurz         spapr_phb_unplug(hotplug_dev, dev);
43150fb6bd07SMichael Roth     } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) {
43160fb6bd07SMichael Roth         spapr_tpm_proxy_unplug(hotplug_dev, dev);
43173ec71474SDavid Hildenbrand     }
431888432f44SDavid Hildenbrand }
431988432f44SDavid Hildenbrand 
spapr_memory_hot_unplug_supported(SpaprMachineState * spapr)432073598c75SGreg Kurz bool spapr_memory_hot_unplug_supported(SpaprMachineState *spapr)
432173598c75SGreg Kurz {
432273598c75SGreg Kurz     return spapr_ovec_test(spapr->ov5_cas, OV5_HP_EVT) ||
432373598c75SGreg Kurz         /*
432473598c75SGreg Kurz          * CAS will process all pending unplug requests.
432573598c75SGreg Kurz          *
432673598c75SGreg Kurz          * HACK: a guest could theoretically have cleared all bits in OV5,
432773598c75SGreg Kurz          * but none of the guests we care for do.
432873598c75SGreg Kurz          */
432973598c75SGreg Kurz         spapr_ovec_empty(spapr->ov5_cas);
433073598c75SGreg Kurz }
433173598c75SGreg Kurz 
spapr_machine_device_unplug_request(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)4332cf632463SBharata B Rao static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev,
4333cf632463SBharata B Rao                                                 DeviceState *dev, Error **errp)
4334cf632463SBharata B Rao {
4335ce2918cbSDavid Gibson     SpaprMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev));
4336c86c1affSDaniel Henrique Barboza     MachineClass *mc = MACHINE_GET_CLASS(sms);
4337ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
4338cf632463SBharata B Rao 
4339cf632463SBharata B Rao     if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
434073598c75SGreg Kurz         if (spapr_memory_hot_unplug_supported(sms)) {
4341cf632463SBharata B Rao             spapr_memory_unplug_request(hotplug_dev, dev, errp);
4342cf632463SBharata B Rao         } else {
4343cf632463SBharata B Rao             error_setg(errp, "Memory hot unplug not supported for this guest");
4344cf632463SBharata B Rao         }
43456f4b5c3eSBharata B Rao     } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
4346c5514d0eSIgor Mammedov         if (!mc->has_hotpluggable_cpus) {
43476f4b5c3eSBharata B Rao             error_setg(errp, "CPU hot unplug not supported on this machine");
43486f4b5c3eSBharata B Rao             return;
43496f4b5c3eSBharata B Rao         }
4350115debf2SIgor Mammedov         spapr_core_unplug_request(hotplug_dev, dev, errp);
4351bb2bdd81SGreg Kurz     } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
4352bb2bdd81SGreg Kurz         if (!smc->dr_phb_enabled) {
4353bb2bdd81SGreg Kurz             error_setg(errp, "PHB hot unplug not supported on this machine");
4354bb2bdd81SGreg Kurz             return;
4355bb2bdd81SGreg Kurz         }
4356bb2bdd81SGreg Kurz         spapr_phb_unplug_request(hotplug_dev, dev, errp);
43570fb6bd07SMichael Roth     } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) {
43580fb6bd07SMichael Roth         spapr_tpm_proxy_unplug(hotplug_dev, dev);
4359c20d332aSBharata B Rao     }
4360c20d332aSBharata B Rao }
4361c20d332aSBharata B Rao 
spapr_machine_device_pre_plug(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)436294a94e4cSBharata B Rao static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev,
436394a94e4cSBharata B Rao                                           DeviceState *dev, Error **errp)
436494a94e4cSBharata B Rao {
4365c871bc70SLaurent Vivier     if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
4366c871bc70SLaurent Vivier         spapr_memory_pre_plug(hotplug_dev, dev, errp);
4367c871bc70SLaurent Vivier     } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
436894a94e4cSBharata B Rao         spapr_core_pre_plug(hotplug_dev, dev, errp);
4369bb2bdd81SGreg Kurz     } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
4370bb2bdd81SGreg Kurz         spapr_phb_pre_plug(hotplug_dev, dev, errp);
4371ac96807bSGreg Kurz     } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) {
4372ac96807bSGreg Kurz         spapr_tpm_proxy_pre_plug(hotplug_dev, dev, errp);
437394a94e4cSBharata B Rao     }
437494a94e4cSBharata B Rao }
437594a94e4cSBharata B Rao 
spapr_get_hotplug_handler(MachineState * machine,DeviceState * dev)43767ebaf795SBharata B Rao static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine,
4377c20d332aSBharata B Rao                                                  DeviceState *dev)
4378c20d332aSBharata B Rao {
437994a94e4cSBharata B Rao     if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
4380bb2bdd81SGreg Kurz         object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE) ||
43810fb6bd07SMichael Roth         object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE) ||
43820fb6bd07SMichael Roth         object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) {
4383c20d332aSBharata B Rao         return HOTPLUG_HANDLER(machine);
4384c20d332aSBharata B Rao     }
4385cb600087SDavid Gibson     if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
4386cb600087SDavid Gibson         PCIDevice *pcidev = PCI_DEVICE(dev);
4387cb600087SDavid Gibson         PCIBus *root = pci_device_root_bus(pcidev);
4388cb600087SDavid Gibson         SpaprPhbState *phb =
4389cb600087SDavid Gibson             (SpaprPhbState *)object_dynamic_cast(OBJECT(BUS(root)->parent),
4390cb600087SDavid Gibson                                                  TYPE_SPAPR_PCI_HOST_BRIDGE);
4391cb600087SDavid Gibson 
4392cb600087SDavid Gibson         if (phb) {
4393cb600087SDavid Gibson             return HOTPLUG_HANDLER(phb);
4394cb600087SDavid Gibson         }
4395cb600087SDavid Gibson     }
4396c20d332aSBharata B Rao     return NULL;
4397c20d332aSBharata B Rao }
4398c20d332aSBharata B Rao 
4399ea089eebSIgor Mammedov static CpuInstanceProperties
spapr_cpu_index_to_props(MachineState * machine,unsigned cpu_index)4400ea089eebSIgor Mammedov spapr_cpu_index_to_props(MachineState *machine, unsigned cpu_index)
440120bb648dSDavid Gibson {
4402ea089eebSIgor Mammedov     CPUArchId *core_slot;
4403ea089eebSIgor Mammedov     MachineClass *mc = MACHINE_GET_CLASS(machine);
4404ea089eebSIgor Mammedov 
4405e6a19a64SMichael Tokarev     /* make sure possible_cpu are initialized */
4406ea089eebSIgor Mammedov     mc->possible_cpu_arch_ids(machine);
4407ea089eebSIgor Mammedov     /* get CPU core slot containing thread that matches cpu_index */
4408ea089eebSIgor Mammedov     core_slot = spapr_find_cpu_slot(machine, cpu_index, NULL);
4409ea089eebSIgor Mammedov     assert(core_slot);
4410ea089eebSIgor Mammedov     return core_slot->props;
441120bb648dSDavid Gibson }
441220bb648dSDavid Gibson 
spapr_get_default_cpu_node_id(const MachineState * ms,int idx)441379e07936SIgor Mammedov static int64_t spapr_get_default_cpu_node_id(const MachineState *ms, int idx)
441479e07936SIgor Mammedov {
4415aa570207STao Xu     return idx / ms->smp.cores % ms->numa_state->num_nodes;
441679e07936SIgor Mammedov }
441779e07936SIgor Mammedov 
spapr_possible_cpu_arch_ids(MachineState * machine)4418535455fdSIgor Mammedov static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine)
4419535455fdSIgor Mammedov {
4420535455fdSIgor Mammedov     int i;
4421fe6b6346SLike Xu     unsigned int smp_threads = machine->smp.threads;
4422fe6b6346SLike Xu     unsigned int smp_cpus = machine->smp.cpus;
4423d342eb76SIgor Mammedov     const char *core_type;
4424fe6b6346SLike Xu     int spapr_max_cores = machine->smp.max_cpus / smp_threads;
4425535455fdSIgor Mammedov     MachineClass *mc = MACHINE_GET_CLASS(machine);
4426535455fdSIgor Mammedov 
4427c5514d0eSIgor Mammedov     if (!mc->has_hotpluggable_cpus) {
4428535455fdSIgor Mammedov         spapr_max_cores = QEMU_ALIGN_UP(smp_cpus, smp_threads) / smp_threads;
4429535455fdSIgor Mammedov     }
4430535455fdSIgor Mammedov     if (machine->possible_cpus) {
4431535455fdSIgor Mammedov         assert(machine->possible_cpus->len == spapr_max_cores);
4432535455fdSIgor Mammedov         return machine->possible_cpus;
4433535455fdSIgor Mammedov     }
4434535455fdSIgor Mammedov 
4435d342eb76SIgor Mammedov     core_type = spapr_get_cpu_core_type(machine->cpu_type);
4436d342eb76SIgor Mammedov     if (!core_type) {
4437d342eb76SIgor Mammedov         error_report("Unable to find sPAPR CPU Core definition");
4438d342eb76SIgor Mammedov         exit(1);
4439d342eb76SIgor Mammedov     }
4440d342eb76SIgor Mammedov 
4441535455fdSIgor Mammedov     machine->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
4442535455fdSIgor Mammedov                              sizeof(CPUArchId) * spapr_max_cores);
4443535455fdSIgor Mammedov     machine->possible_cpus->len = spapr_max_cores;
4444535455fdSIgor Mammedov     for (i = 0; i < machine->possible_cpus->len; i++) {
4445535455fdSIgor Mammedov         int core_id = i * smp_threads;
4446535455fdSIgor Mammedov 
4447d342eb76SIgor Mammedov         machine->possible_cpus->cpus[i].type = core_type;
4448f2d672c2SIgor Mammedov         machine->possible_cpus->cpus[i].vcpus_count = smp_threads;
4449535455fdSIgor Mammedov         machine->possible_cpus->cpus[i].arch_id = core_id;
4450535455fdSIgor Mammedov         machine->possible_cpus->cpus[i].props.has_core_id = true;
4451535455fdSIgor Mammedov         machine->possible_cpus->cpus[i].props.core_id = core_id;
4452535455fdSIgor Mammedov     }
4453535455fdSIgor Mammedov     return machine->possible_cpus;
4454535455fdSIgor Mammedov }
4455535455fdSIgor 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)4456f5598c92SGreg Kurz static bool spapr_phb_placement(SpaprMachineState *spapr, uint32_t index,
4457daa23699SDavid Gibson                                 uint64_t *buid, hwaddr *pio,
4458daa23699SDavid Gibson                                 hwaddr *mmio32, hwaddr *mmio64,
445944fa20c9SCédric Le Goater                                 unsigned n_dma, uint32_t *liobns, Error **errp)
44606737d9adSDavid Gibson {
4461357d1e3bSDavid Gibson     /*
4462357d1e3bSDavid Gibson      * New-style PHB window placement.
4463357d1e3bSDavid Gibson      *
4464357d1e3bSDavid Gibson      * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window
4465357d1e3bSDavid Gibson      * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO
4466357d1e3bSDavid Gibson      * windows.
4467357d1e3bSDavid Gibson      *
4468357d1e3bSDavid Gibson      * Some guest kernels can't work with MMIO windows above 1<<46
4469357d1e3bSDavid Gibson      * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB
4470357d1e3bSDavid Gibson      *
4471357d1e3bSDavid Gibson      * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each
4472357d1e3bSDavid Gibson      * PHB stacked together.  (32TiB+2GiB)..(32TiB+64GiB) contains the
4473357d1e3bSDavid Gibson      * 2GiB 32-bit MMIO windows for each PHB.  Then 33..64TiB has the
4474357d1e3bSDavid Gibson      * 1TiB 64-bit MMIO windows for each PHB.
4475357d1e3bSDavid Gibson      */
44766737d9adSDavid Gibson     const uint64_t base_buid = 0x800000020000000ULL;
44776737d9adSDavid Gibson     int i;
44786737d9adSDavid Gibson 
4479357d1e3bSDavid Gibson     /* Sanity check natural alignments */
4480357d1e3bSDavid Gibson     QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0);
4481357d1e3bSDavid Gibson     QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0);
4482357d1e3bSDavid Gibson     QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0);
4483357d1e3bSDavid Gibson     QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0);
4484357d1e3bSDavid Gibson     /* Sanity check bounds */
448525e6a118SMichael S. Tsirkin     QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_IO_WIN_SIZE) >
448625e6a118SMichael S. Tsirkin                       SPAPR_PCI_MEM32_WIN_SIZE);
448725e6a118SMichael S. Tsirkin     QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_MEM32_WIN_SIZE) >
448825e6a118SMichael S. Tsirkin                       SPAPR_PCI_MEM64_WIN_SIZE);
44892efff1c0SDavid Gibson 
449025e6a118SMichael S. Tsirkin     if (index >= SPAPR_MAX_PHBS) {
449125e6a118SMichael S. Tsirkin         error_setg(errp, "\"index\" for PAPR PHB is too large (max %llu)",
449225e6a118SMichael S. Tsirkin                    SPAPR_MAX_PHBS - 1);
4493f5598c92SGreg Kurz         return false;
44946737d9adSDavid Gibson     }
44956737d9adSDavid Gibson 
44966737d9adSDavid Gibson     *buid = base_buid + index;
44976737d9adSDavid Gibson     for (i = 0; i < n_dma; ++i) {
44986737d9adSDavid Gibson         liobns[i] = SPAPR_PCI_LIOBN(index, i);
44996737d9adSDavid Gibson     }
45006737d9adSDavid Gibson 
4501357d1e3bSDavid Gibson     *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE;
4502357d1e3bSDavid Gibson     *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE;
4503357d1e3bSDavid Gibson     *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE;
4504f5598c92SGreg Kurz     return true;
45056737d9adSDavid Gibson }
45066737d9adSDavid Gibson 
spapr_ics_get(XICSFabric * dev,int irq)45077844e12bSCédric Le Goater static ICSState *spapr_ics_get(XICSFabric *dev, int irq)
45087844e12bSCédric Le Goater {
4509ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(dev);
45107844e12bSCédric Le Goater 
45117844e12bSCédric Le Goater     return ics_valid_irq(spapr->ics, irq) ? spapr->ics : NULL;
45127844e12bSCédric Le Goater }
45137844e12bSCédric Le Goater 
spapr_ics_resend(XICSFabric * dev)45147844e12bSCédric Le Goater static void spapr_ics_resend(XICSFabric *dev)
45157844e12bSCédric Le Goater {
4516ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(dev);
45177844e12bSCédric Le Goater 
45187844e12bSCédric Le Goater     ics_resend(spapr->ics);
45197844e12bSCédric Le Goater }
45207844e12bSCédric Le Goater 
spapr_icp_get(XICSFabric * xi,int vcpu_id)452181210c20SSam Bobroff static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id)
4522b2fc59aaSCédric Le Goater {
45232e886fb3SSam Bobroff     PowerPCCPU *cpu = spapr_find_cpu(vcpu_id);
4524b2fc59aaSCédric Le Goater 
4525a28b9a5aSCédric Le Goater     return cpu ? spapr_cpu_state(cpu)->icp : NULL;
4526b2fc59aaSCédric Le Goater }
4527b2fc59aaSCédric Le Goater 
spapr_pic_print_info(InterruptStatsProvider * obj,GString * buf)4528b2580720SPhilippe Mathieu-Daudé static void spapr_pic_print_info(InterruptStatsProvider *obj, GString *buf)
45296449da45SCédric Le Goater {
4530ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
45316449da45SCédric Le Goater 
4532f50bb2a2SPhilippe Mathieu-Daudé     spapr_irq_print_info(spapr, buf);
4533f50bb2a2SPhilippe Mathieu-Daudé     g_string_append_printf(buf, "irqchip: %s\n",
4534f041d6afSGreg Kurz                            kvm_irqchip_in_kernel() ? "in-kernel" : "emulated");
45356449da45SCédric Le Goater }
45366449da45SCédric Le Goater 
4537baa45b17SCédric Le Goater /*
4538baa45b17SCédric Le Goater  * This is a XIVE only operation
4539baa45b17SCé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)4540932de7aeSCédric Le Goater static int spapr_match_nvt(XiveFabric *xfb, uint8_t format,
4541932de7aeSCédric Le Goater                            uint8_t nvt_blk, uint32_t nvt_idx,
4542932de7aeSCédric Le Goater                            bool cam_ignore, uint8_t priority,
4543932de7aeSCédric Le Goater                            uint32_t logic_serv, XiveTCTXMatch *match)
4544932de7aeSCédric Le Goater {
4545932de7aeSCédric Le Goater     SpaprMachineState *spapr = SPAPR_MACHINE(xfb);
4546baa45b17SCédric Le Goater     XivePresenter *xptr = XIVE_PRESENTER(spapr->active_intc);
4547932de7aeSCédric Le Goater     XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
4548932de7aeSCédric Le Goater     int count;
4549932de7aeSCédric Le Goater 
4550932de7aeSCédric Le Goater     count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
4551932de7aeSCédric Le Goater                            priority, logic_serv, match);
4552932de7aeSCédric Le Goater     if (count < 0) {
4553932de7aeSCédric Le Goater         return count;
4554932de7aeSCédric Le Goater     }
4555932de7aeSCédric Le Goater 
4556932de7aeSCédric Le Goater     /*
4557932de7aeSCédric Le Goater      * When we implement the save and restore of the thread interrupt
4558932de7aeSCédric Le Goater      * contexts in the enter/exit CPU handlers of the machine and the
4559932de7aeSCédric Le Goater      * escalations in QEMU, we should be able to handle non dispatched
4560932de7aeSCédric Le Goater      * vCPUs.
4561932de7aeSCédric Le Goater      *
4562932de7aeSCédric Le Goater      * Until this is done, the sPAPR machine should find at least one
4563932de7aeSCédric Le Goater      * matching context always.
4564932de7aeSCédric Le Goater      */
4565932de7aeSCédric Le Goater     if (count == 0) {
4566932de7aeSCédric Le Goater         qemu_log_mask(LOG_GUEST_ERROR, "XIVE: NVT %x/%x is not dispatched\n",
4567932de7aeSCédric Le Goater                       nvt_blk, nvt_idx);
4568932de7aeSCédric Le Goater     }
4569932de7aeSCédric Le Goater 
4570932de7aeSCédric Le Goater     return count;
4571932de7aeSCédric Le Goater }
4572932de7aeSCédric Le Goater 
spapr_get_vcpu_id(PowerPCCPU * cpu)457314bb4486SGreg Kurz int spapr_get_vcpu_id(PowerPCCPU *cpu)
45742e886fb3SSam Bobroff {
4575b1a568c1SGreg Kurz     return cpu->vcpu_id;
45762e886fb3SSam Bobroff }
45772e886fb3SSam Bobroff 
spapr_set_vcpu_id(PowerPCCPU * cpu,int cpu_index,Error ** errp)4578cfdc5274SGreg Kurz bool spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp)
4579648edb64SGreg Kurz {
4580ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
4581fe6b6346SLike Xu     MachineState *ms = MACHINE(spapr);
4582648edb64SGreg Kurz     int vcpu_id;
4583648edb64SGreg Kurz 
45845d0fb150SGreg Kurz     vcpu_id = spapr_vcpu_id(spapr, cpu_index);
4585648edb64SGreg Kurz 
4586648edb64SGreg Kurz     if (kvm_enabled() && !kvm_vcpu_id_is_valid(vcpu_id)) {
4587648edb64SGreg Kurz         error_setg(errp, "Can't create CPU with id %d in KVM", vcpu_id);
4588648edb64SGreg Kurz         error_append_hint(errp, "Adjust the number of cpus to %d "
4589648edb64SGreg Kurz                           "or try to raise the number of threads per core\n",
4590fe6b6346SLike Xu                           vcpu_id * ms->smp.threads / spapr->vsmt);
4591cfdc5274SGreg Kurz         return false;
4592648edb64SGreg Kurz     }
4593648edb64SGreg Kurz 
4594648edb64SGreg Kurz     cpu->vcpu_id = vcpu_id;
4595cfdc5274SGreg Kurz     return true;
4596648edb64SGreg Kurz }
4597648edb64SGreg Kurz 
spapr_find_cpu(int vcpu_id)45982e886fb3SSam Bobroff PowerPCCPU *spapr_find_cpu(int vcpu_id)
45992e886fb3SSam Bobroff {
46002e886fb3SSam Bobroff     CPUState *cs;
46012e886fb3SSam Bobroff 
46022e886fb3SSam Bobroff     CPU_FOREACH(cs) {
46032e886fb3SSam Bobroff         PowerPCCPU *cpu = POWERPC_CPU(cs);
46042e886fb3SSam Bobroff 
460514bb4486SGreg Kurz         if (spapr_get_vcpu_id(cpu) == vcpu_id) {
46062e886fb3SSam Bobroff             return cpu;
46072e886fb3SSam Bobroff         }
46082e886fb3SSam Bobroff     }
46092e886fb3SSam Bobroff 
46102e886fb3SSam Bobroff     return NULL;
46112e886fb3SSam Bobroff }
46122e886fb3SSam Bobroff 
spapr_cpu_in_nested(PowerPCCPU * cpu)46137cebc5dbSNicholas Piggin static bool spapr_cpu_in_nested(PowerPCCPU *cpu)
46147cebc5dbSNicholas Piggin {
4615120f738aSNicholas Piggin     SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
4616120f738aSNicholas Piggin 
4617120f738aSNicholas Piggin     return spapr_cpu->in_nested;
46187cebc5dbSNicholas Piggin }
46197cebc5dbSNicholas Piggin 
spapr_cpu_exec_enter(PPCVirtualHypervisor * vhyp,PowerPCCPU * cpu)462003ef074cSNicholas Piggin static void spapr_cpu_exec_enter(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu)
462103ef074cSNicholas Piggin {
462203ef074cSNicholas Piggin     SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
462303ef074cSNicholas Piggin 
462403ef074cSNicholas Piggin     /* These are only called by TCG, KVM maintains dispatch state */
462503ef074cSNicholas Piggin 
46263a6e6224SNicholas Piggin     spapr_cpu->prod = false;
462703ef074cSNicholas Piggin     if (spapr_cpu->vpa_addr) {
462803ef074cSNicholas Piggin         CPUState *cs = CPU(cpu);
462903ef074cSNicholas Piggin         uint32_t dispatch;
463003ef074cSNicholas Piggin 
463103ef074cSNicholas Piggin         dispatch = ldl_be_phys(cs->as,
463203ef074cSNicholas Piggin                                spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER);
463303ef074cSNicholas Piggin         dispatch++;
463403ef074cSNicholas Piggin         if ((dispatch & 1) != 0) {
463503ef074cSNicholas Piggin             qemu_log_mask(LOG_GUEST_ERROR,
463603ef074cSNicholas Piggin                           "VPA: incorrect dispatch counter value for "
463703ef074cSNicholas Piggin                           "dispatched partition %u, correcting.\n", dispatch);
463803ef074cSNicholas Piggin             dispatch++;
463903ef074cSNicholas Piggin         }
464003ef074cSNicholas Piggin         stl_be_phys(cs->as,
464103ef074cSNicholas Piggin                     spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch);
464203ef074cSNicholas Piggin     }
464303ef074cSNicholas Piggin }
464403ef074cSNicholas Piggin 
spapr_cpu_exec_exit(PPCVirtualHypervisor * vhyp,PowerPCCPU * cpu)464503ef074cSNicholas Piggin static void spapr_cpu_exec_exit(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu)
464603ef074cSNicholas Piggin {
464703ef074cSNicholas Piggin     SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
464803ef074cSNicholas Piggin 
464903ef074cSNicholas Piggin     if (spapr_cpu->vpa_addr) {
465003ef074cSNicholas Piggin         CPUState *cs = CPU(cpu);
465103ef074cSNicholas Piggin         uint32_t dispatch;
465203ef074cSNicholas Piggin 
465303ef074cSNicholas Piggin         dispatch = ldl_be_phys(cs->as,
465403ef074cSNicholas Piggin                                spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER);
465503ef074cSNicholas Piggin         dispatch++;
465603ef074cSNicholas Piggin         if ((dispatch & 1) != 1) {
465703ef074cSNicholas Piggin             qemu_log_mask(LOG_GUEST_ERROR,
465803ef074cSNicholas Piggin                           "VPA: incorrect dispatch counter value for "
465903ef074cSNicholas Piggin                           "preempted partition %u, correcting.\n", dispatch);
466003ef074cSNicholas Piggin             dispatch++;
466103ef074cSNicholas Piggin         }
466203ef074cSNicholas Piggin         stl_be_phys(cs->as,
466303ef074cSNicholas Piggin                     spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch);
466403ef074cSNicholas Piggin     }
466503ef074cSNicholas Piggin }
466603ef074cSNicholas Piggin 
spapr_machine_class_init(ObjectClass * oc,void * data)466729ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data)
466853018216SPaolo Bonzini {
466929ee3247SAlexey Kardashevskiy     MachineClass *mc = MACHINE_CLASS(oc);
4670ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(oc);
467171461b0fSAlexey Kardashevskiy     FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc);
467234316482SAlexey Kardashevskiy     NMIClass *nc = NMI_CLASS(oc);
4673c20d332aSBharata B Rao     HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
46741d1be34dSDavid Gibson     PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc);
46757844e12bSCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
46766449da45SCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
4677932de7aeSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
4678fc8c745dSAlexey Kardashevskiy     VofMachineIfClass *vmc = VOF_MACHINE_CLASS(oc);
467929ee3247SAlexey Kardashevskiy 
46800eb9054cSDavid Gibson     mc->desc = "pSeries Logical Partition (PAPR compliant)";
4681907aac2fSMark Cave-Ayland     mc->ignore_boot_device_suffixes = true;
4682fc9f38c3SDavid Gibson 
4683fc9f38c3SDavid Gibson     /*
4684fc9f38c3SDavid Gibson      * We set up the default / latest behaviour here.  The class_init
4685fc9f38c3SDavid Gibson      * functions for the specific versioned machine types can override
4686fc9f38c3SDavid Gibson      * these details for backwards compatibility
4687fc9f38c3SDavid Gibson      */
4688bcb5ce08SDavid Gibson     mc->init = spapr_machine_init;
4689bcb5ce08SDavid Gibson     mc->reset = spapr_machine_reset;
4690958db90cSMarcel Apfelbaum     mc->block_default_type = IF_SCSI;
46915642e451SDaniel Henrique Barboza 
46925642e451SDaniel Henrique Barboza     /*
4693c4f91d7bSHarsh Prateek Bora      * While KVM determines max cpus in kvm_init() using kvm_max_vcpus(),
4694c4f91d7bSHarsh Prateek Bora      * In TCG the limit is restricted by the range of CPU IPIs available.
46955642e451SDaniel Henrique Barboza      */
4696c4f91d7bSHarsh Prateek Bora     mc->max_cpus = SPAPR_IRQ_NR_IPIS;
46975642e451SDaniel Henrique Barboza 
4698958db90cSMarcel Apfelbaum     mc->no_parallel = 1;
46995b2128d2SAlexander Graf     mc->default_boot_order = "";
4700d23b6caaSPhilippe Mathieu-Daudé     mc->default_ram_size = 512 * MiB;
4701ab74e543SIgor Mammedov     mc->default_ram_id = "ppc_spapr.ram";
470229f9cef3SSebastian Bauer     mc->default_display = "std";
4703958db90cSMarcel Apfelbaum     mc->kvm_type = spapr_kvm_type;
47047da79a16SEduardo Habkost     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SPAPR_PCI_HOST_BRIDGE);
4705e4024630SLaurent Vivier     mc->pci_allow_0_address = true;
4706debbdc00SIgor Mammedov     assert(!mc->get_hotplug_handler);
47077ebaf795SBharata B Rao     mc->get_hotplug_handler = spapr_get_hotplug_handler;
470894a94e4cSBharata B Rao     hc->pre_plug = spapr_machine_device_pre_plug;
4709c20d332aSBharata B Rao     hc->plug = spapr_machine_device_plug;
4710ea089eebSIgor Mammedov     mc->cpu_index_to_instance_props = spapr_cpu_index_to_props;
471179e07936SIgor Mammedov     mc->get_default_cpu_node_id = spapr_get_default_cpu_node_id;
4712535455fdSIgor Mammedov     mc->possible_cpu_arch_ids = spapr_possible_cpu_arch_ids;
4713cf632463SBharata B Rao     hc->unplug_request = spapr_machine_device_unplug_request;
471488432f44SDavid Hildenbrand     hc->unplug = spapr_machine_device_unplug;
471500b4fbe2SMarcel Apfelbaum 
4716fc9f38c3SDavid Gibson     smc->dr_lmb_enabled = true;
4717fea35ca4SAlexey Kardashevskiy     smc->update_dt_enabled = true;
471851113013SNicholas Piggin     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
4719c5514d0eSIgor Mammedov     mc->has_hotpluggable_cpus = true;
4720ee3a71e3SShivaprasad G Bhat     mc->nvdimm_supported = true;
472152b81ab5SDavid Gibson     smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED;
472271461b0fSAlexey Kardashevskiy     fwc->get_dev_path = spapr_get_fw_dev_path;
472334316482SAlexey Kardashevskiy     nc->nmi_monitor_handler = spapr_nmi;
47246737d9adSDavid Gibson     smc->phb_placement = spapr_phb_placement;
47257cebc5dbSNicholas Piggin     vhc->cpu_in_nested = spapr_cpu_in_nested;
4726120f738aSNicholas Piggin     vhc->deliver_hv_excp = spapr_exit_nested;
47271d1be34dSDavid Gibson     vhc->hypercall = emulate_spapr_hypercall;
4728e57ca75cSDavid Gibson     vhc->hpt_mask = spapr_hpt_mask;
4729e57ca75cSDavid Gibson     vhc->map_hptes = spapr_map_hptes;
4730e57ca75cSDavid Gibson     vhc->unmap_hptes = spapr_unmap_hptes;
4731a2dd4e83SBenjamin Herrenschmidt     vhc->hpte_set_c = spapr_hpte_set_c;
4732a2dd4e83SBenjamin Herrenschmidt     vhc->hpte_set_r = spapr_hpte_set_r;
473379825f4dSBenjamin Herrenschmidt     vhc->get_pate = spapr_get_pate;
47341ec26c75SGreg Kurz     vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr;
473503ef074cSNicholas Piggin     vhc->cpu_exec_enter = spapr_cpu_exec_enter;
473603ef074cSNicholas Piggin     vhc->cpu_exec_exit = spapr_cpu_exec_exit;
47377844e12bSCédric Le Goater     xic->ics_get = spapr_ics_get;
47387844e12bSCédric Le Goater     xic->ics_resend = spapr_ics_resend;
4739b2fc59aaSCédric Le Goater     xic->icp_get = spapr_icp_get;
47406449da45SCédric Le Goater     ispc->print_info = spapr_pic_print_info;
474155641213SLaurent Vivier     /* Force NUMA node memory size to be a multiple of
474255641213SLaurent Vivier      * SPAPR_MEMORY_BLOCK_SIZE (256M) since that's the granularity
474355641213SLaurent Vivier      * in which LMBs are represented and hot-added
474455641213SLaurent Vivier      */
474555641213SLaurent Vivier     mc->numa_mem_align_shift = 28;
47460533ef5fSTao Xu     mc->auto_enable_numa = true;
474733face6bSDavid Gibson 
47484e5fe368SSuraj Jitindar Singh     smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
47494e5fe368SSuraj Jitindar Singh     smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON;
47504e5fe368SSuraj Jitindar Singh     smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON;
47512782ad4cSSuraj Jitindar Singh     smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND;
47522782ad4cSSuraj Jitindar Singh     smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND;
47532782ad4cSSuraj Jitindar Singh     smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_WORKAROUND;
47542309832aSDavid Gibson     smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
4755b9a477b7SSuraj Jitindar Singh     smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
4756e1617b84SHarsh Prateek Bora     smc->default_caps.caps[SPAPR_CAP_NESTED_PAPR] = SPAPR_CAP_OFF;
4757edaa7995SSuraj Jitindar Singh     smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON;
475837965dfeSDavid Gibson     smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_ON;
47598af7e1feSNicholas Piggin     smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_ON;
476082123b75SBharata B Rao     smc->default_caps.caps[SPAPR_CAP_RPT_INVALIDATE] = SPAPR_CAP_OFF;
4761ccc5a4c5SNicholas Piggin 
4762ccc5a4c5SNicholas Piggin     /*
4763ccc5a4c5SNicholas Piggin      * This cap specifies whether the AIL 3 mode for
4764ccc5a4c5SNicholas Piggin      * H_SET_RESOURCE is supported. The default is modified
4765ccc5a4c5SNicholas Piggin      * by default_caps_with_cpu().
4766ccc5a4c5SNicholas Piggin      */
4767ccc5a4c5SNicholas Piggin     smc->default_caps.caps[SPAPR_CAP_AIL_MODE_3] = SPAPR_CAP_ON;
476840c2281cSMarkus Armbruster     spapr_caps_add_properties(smc);
4769bd94bc06SCédric Le Goater     smc->irq = &spapr_irq_dual;
4770dae5e39aSMichael Roth     smc->dr_phb_enabled = true;
47716c3829a2SAlexey Kardashevskiy     smc->linux_pci_probe = true;
477229cb4187SGreg Kurz     smc->smp_threads_vsmt = true;
477354255c1fSDavid Gibson     smc->nr_xirqs = SPAPR_NR_XIRQS;
4774932de7aeSCédric Le Goater     xfc->match_nvt = spapr_match_nvt;
4775fc8c745dSAlexey Kardashevskiy     vmc->client_architecture_support = spapr_vof_client_architecture_support;
4776fc8c745dSAlexey Kardashevskiy     vmc->quiesce = spapr_vof_quiesce;
4777fc8c745dSAlexey Kardashevskiy     vmc->setprop = spapr_vof_setprop;
477853018216SPaolo Bonzini }
477953018216SPaolo Bonzini 
478029ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = {
478129ee3247SAlexey Kardashevskiy     .name          = TYPE_SPAPR_MACHINE,
478229ee3247SAlexey Kardashevskiy     .parent        = TYPE_MACHINE,
47834aee7362SDavid Gibson     .abstract      = true,
4784ce2918cbSDavid Gibson     .instance_size = sizeof(SpaprMachineState),
4785bcb5ce08SDavid Gibson     .instance_init = spapr_instance_init,
478687bbdd9cSDavid Gibson     .instance_finalize = spapr_machine_finalizefn,
4787ce2918cbSDavid Gibson     .class_size    = sizeof(SpaprMachineClass),
478829ee3247SAlexey Kardashevskiy     .class_init    = spapr_machine_class_init,
478971461b0fSAlexey Kardashevskiy     .interfaces = (InterfaceInfo[]) {
479071461b0fSAlexey Kardashevskiy         { TYPE_FW_PATH_PROVIDER },
479134316482SAlexey Kardashevskiy         { TYPE_NMI },
4792c20d332aSBharata B Rao         { TYPE_HOTPLUG_HANDLER },
47931d1be34dSDavid Gibson         { TYPE_PPC_VIRTUAL_HYPERVISOR },
47947844e12bSCédric Le Goater         { TYPE_XICS_FABRIC },
47956449da45SCédric Le Goater         { TYPE_INTERRUPT_STATS_PROVIDER },
4796932de7aeSCédric Le Goater         { TYPE_XIVE_FABRIC },
4797fc8c745dSAlexey Kardashevskiy         { TYPE_VOF_MACHINE_IF },
479871461b0fSAlexey Kardashevskiy         { }
479971461b0fSAlexey Kardashevskiy     },
480029ee3247SAlexey Kardashevskiy };
480129ee3247SAlexey Kardashevskiy 
spapr_machine_latest_class_options(MachineClass * mc)4802a7849268SMichael S. Tsirkin static void spapr_machine_latest_class_options(MachineClass *mc)
4803a7849268SMichael S. Tsirkin {
4804a7849268SMichael S. Tsirkin     mc->alias = "pseries";
4805ea0ac7f6SPhilippe Mathieu-Daudé     mc->is_default = true;
4806a7849268SMichael S. Tsirkin }
4807a7849268SMichael S. Tsirkin 
48088d40cc14SDaniel P. Berrangé #define DEFINE_SPAPR_MACHINE_IMPL(latest, ...)                       \
48098d40cc14SDaniel P. Berrangé     static void MACHINE_VER_SYM(class_init, spapr, __VA_ARGS__)(     \
48108d40cc14SDaniel P. Berrangé         ObjectClass *oc,                                             \
48115013c547SDavid Gibson         void *data)                                                  \
48125013c547SDavid Gibson     {                                                                \
48135013c547SDavid Gibson         MachineClass *mc = MACHINE_CLASS(oc);                        \
48148d40cc14SDaniel P. Berrangé         MACHINE_VER_SYM(class_options, spapr, __VA_ARGS__)(mc);      \
48158d3122a8SDaniel P. Berrangé         MACHINE_VER_DEPRECATION(__VA_ARGS__);                        \
4816fccbc785SDavid Gibson         if (latest) {                                                \
4817a7849268SMichael S. Tsirkin             spapr_machine_latest_class_options(mc);                  \
4818fccbc785SDavid Gibson         }                                                            \
48195013c547SDavid Gibson     }                                                                \
48208d40cc14SDaniel P. Berrangé     static const TypeInfo MACHINE_VER_SYM(info, spapr, __VA_ARGS__) = \
48215013c547SDavid Gibson     {                                                                \
48228d40cc14SDaniel P. Berrangé         .name = MACHINE_VER_TYPE_NAME("pseries", __VA_ARGS__),       \
48238d40cc14SDaniel P. Berrangé         .parent = TYPE_SPAPR_MACHINE,                                \
48248d40cc14SDaniel P. Berrangé         .class_init = MACHINE_VER_SYM(class_init, spapr, __VA_ARGS__), \
48258d40cc14SDaniel P. Berrangé     };                                                               \
48268d40cc14SDaniel P. Berrangé     static void MACHINE_VER_SYM(register, spapr, __VA_ARGS__)(void)  \
48278d40cc14SDaniel P. Berrangé     {                                                                \
4828a391eeb1SDaniel P. Berrangé         MACHINE_VER_DELETION(__VA_ARGS__);                           \
48298d40cc14SDaniel P. Berrangé         type_register(&MACHINE_VER_SYM(info, spapr, __VA_ARGS__));   \
48305013c547SDavid Gibson     }                                                                \
48318d40cc14SDaniel P. Berrangé     type_init(MACHINE_VER_SYM(register, spapr, __VA_ARGS__))
48328d40cc14SDaniel P. Berrangé 
48338d40cc14SDaniel P. Berrangé #define DEFINE_SPAPR_MACHINE_AS_LATEST(major, minor) \
48348d40cc14SDaniel P. Berrangé     DEFINE_SPAPR_MACHINE_IMPL(true, major, minor)
48358d40cc14SDaniel P. Berrangé #define DEFINE_SPAPR_MACHINE(major, minor) \
48368d40cc14SDaniel P. Berrangé     DEFINE_SPAPR_MACHINE_IMPL(false, major, minor)
48378d40cc14SDaniel P. Berrangé #define DEFINE_SPAPR_MACHINE_TAGGED(major, minor, tag) \
48388d40cc14SDaniel P. Berrangé     DEFINE_SPAPR_MACHINE_IMPL(false, major, minor, _, tag)
48395013c547SDavid Gibson 
48401c5f29bbSDavid Gibson /*
484185fa9acdSPaolo Bonzini  * pseries-9.1
48423eb74d20SCornelia Huck  */
spapr_machine_9_1_class_options(MachineClass * mc)484385fa9acdSPaolo Bonzini static void spapr_machine_9_1_class_options(MachineClass *mc)
48443eb74d20SCornelia Huck {
48453eb74d20SCornelia Huck     /* Defaults for the latest behaviour inherited from the base class */
48463eb74d20SCornelia Huck }
48473eb74d20SCornelia Huck 
48488d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE_AS_LATEST(9, 1);
484985fa9acdSPaolo Bonzini 
485085fa9acdSPaolo Bonzini /*
485185fa9acdSPaolo Bonzini  * pseries-9.0
485285fa9acdSPaolo Bonzini  */
spapr_machine_9_0_class_options(MachineClass * mc)485385fa9acdSPaolo Bonzini static void spapr_machine_9_0_class_options(MachineClass *mc)
485485fa9acdSPaolo Bonzini {
485585fa9acdSPaolo Bonzini     spapr_machine_9_1_class_options(mc);
485685fa9acdSPaolo Bonzini     compat_props_add(mc->compat_props, hw_compat_9_0, hw_compat_9_0_len);
485785fa9acdSPaolo Bonzini }
485885fa9acdSPaolo Bonzini 
48598d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(9, 0);
48602b10a676SCornelia Huck 
48612b10a676SCornelia Huck /*
48622b10a676SCornelia Huck  * pseries-8.2
48632b10a676SCornelia Huck  */
spapr_machine_8_2_class_options(MachineClass * mc)48642b10a676SCornelia Huck static void spapr_machine_8_2_class_options(MachineClass *mc)
48652b10a676SCornelia Huck {
48662b10a676SCornelia Huck     spapr_machine_9_0_class_options(mc);
48672b10a676SCornelia Huck     compat_props_add(mc->compat_props, hw_compat_8_2, hw_compat_8_2_len);
48682b10a676SCornelia Huck }
48692b10a676SCornelia Huck 
48708d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(8, 2);
487195f5c89eSCornelia Huck 
487295f5c89eSCornelia Huck /*
487395f5c89eSCornelia Huck  * pseries-8.1
487495f5c89eSCornelia Huck  */
spapr_machine_8_1_class_options(MachineClass * mc)487595f5c89eSCornelia Huck static void spapr_machine_8_1_class_options(MachineClass *mc)
487695f5c89eSCornelia Huck {
487795f5c89eSCornelia Huck     spapr_machine_8_2_class_options(mc);
487895f5c89eSCornelia Huck     compat_props_add(mc->compat_props, hw_compat_8_1, hw_compat_8_1_len);
487995f5c89eSCornelia Huck }
488095f5c89eSCornelia Huck 
48818d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(8, 1);
4882f9be4771SCornelia Huck 
4883f9be4771SCornelia Huck /*
4884f9be4771SCornelia Huck  * pseries-8.0
4885f9be4771SCornelia Huck  */
spapr_machine_8_0_class_options(MachineClass * mc)4886f9be4771SCornelia Huck static void spapr_machine_8_0_class_options(MachineClass *mc)
4887f9be4771SCornelia Huck {
4888f9be4771SCornelia Huck     spapr_machine_8_1_class_options(mc);
4889f9be4771SCornelia Huck     compat_props_add(mc->compat_props, hw_compat_8_0, hw_compat_8_0_len);
4890f9be4771SCornelia Huck }
4891f9be4771SCornelia Huck 
48928d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(8, 0);
4893db723c80SCornelia Huck 
4894db723c80SCornelia Huck /*
4895db723c80SCornelia Huck  * pseries-7.2
4896db723c80SCornelia Huck  */
spapr_machine_7_2_class_options(MachineClass * mc)4897db723c80SCornelia Huck static void spapr_machine_7_2_class_options(MachineClass *mc)
4898db723c80SCornelia Huck {
4899db723c80SCornelia Huck     spapr_machine_8_0_class_options(mc);
4900db723c80SCornelia Huck     compat_props_add(mc->compat_props, hw_compat_7_2, hw_compat_7_2_len);
4901db723c80SCornelia Huck }
4902db723c80SCornelia Huck 
49038d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(7, 2);
4904f514e147SCornelia Huck 
4905f514e147SCornelia Huck /*
4906f514e147SCornelia Huck  * pseries-7.1
4907f514e147SCornelia Huck  */
spapr_machine_7_1_class_options(MachineClass * mc)4908f514e147SCornelia Huck static void spapr_machine_7_1_class_options(MachineClass *mc)
4909f514e147SCornelia Huck {
4910f514e147SCornelia Huck     spapr_machine_7_2_class_options(mc);
4911f514e147SCornelia Huck     compat_props_add(mc->compat_props, hw_compat_7_1, hw_compat_7_1_len);
4912f514e147SCornelia Huck }
4913f514e147SCornelia Huck 
49148d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(7, 1);
49150ca70366SCornelia Huck 
49160ca70366SCornelia Huck /*
49170ca70366SCornelia Huck  * pseries-7.0
49180ca70366SCornelia Huck  */
spapr_machine_7_0_class_options(MachineClass * mc)49190ca70366SCornelia Huck static void spapr_machine_7_0_class_options(MachineClass *mc)
49200ca70366SCornelia Huck {
49210ca70366SCornelia Huck     spapr_machine_7_1_class_options(mc);
49220ca70366SCornelia Huck     compat_props_add(mc->compat_props, hw_compat_7_0, hw_compat_7_0_len);
49230ca70366SCornelia Huck }
49240ca70366SCornelia Huck 
49258d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(7, 0);
492601854af2SCornelia Huck 
492701854af2SCornelia Huck /*
492801854af2SCornelia Huck  * pseries-6.2
492901854af2SCornelia Huck  */
spapr_machine_6_2_class_options(MachineClass * mc)493001854af2SCornelia Huck static void spapr_machine_6_2_class_options(MachineClass *mc)
493101854af2SCornelia Huck {
493201854af2SCornelia Huck     spapr_machine_7_0_class_options(mc);
493301854af2SCornelia Huck     compat_props_add(mc->compat_props, hw_compat_6_2, hw_compat_6_2_len);
493401854af2SCornelia Huck }
493501854af2SCornelia Huck 
49368d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(6, 2);
493752e64f5bSYanan Wang 
493852e64f5bSYanan Wang /*
493952e64f5bSYanan Wang  * pseries-6.1
494052e64f5bSYanan Wang  */
spapr_machine_6_1_class_options(MachineClass * mc)494152e64f5bSYanan Wang static void spapr_machine_6_1_class_options(MachineClass *mc)
494252e64f5bSYanan Wang {
4943e0eb84d4SDaniel Henrique Barboza     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
4944e0eb84d4SDaniel Henrique Barboza 
494552e64f5bSYanan Wang     spapr_machine_6_2_class_options(mc);
494652e64f5bSYanan Wang     compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
4947e0eb84d4SDaniel Henrique Barboza     smc->pre_6_2_numa_affinity = true;
49482b526199SYanan Wang     mc->smp_props.prefer_sockets = true;
494952e64f5bSYanan Wang }
495052e64f5bSYanan Wang 
49518d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(6, 1);
4952da7e13c0SCornelia Huck 
4953da7e13c0SCornelia Huck /*
4954da7e13c0SCornelia Huck  * pseries-6.0
4955da7e13c0SCornelia Huck  */
spapr_machine_6_0_class_options(MachineClass * mc)4956da7e13c0SCornelia Huck static void spapr_machine_6_0_class_options(MachineClass *mc)
4957da7e13c0SCornelia Huck {
4958da7e13c0SCornelia Huck     spapr_machine_6_1_class_options(mc);
4959da7e13c0SCornelia Huck     compat_props_add(mc->compat_props, hw_compat_6_0, hw_compat_6_0_len);
4960da7e13c0SCornelia Huck }
4961da7e13c0SCornelia Huck 
49628d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(6, 0);
4963576a00bdSCornelia Huck 
4964576a00bdSCornelia Huck /*
4965576a00bdSCornelia Huck  * pseries-5.2
4966576a00bdSCornelia Huck  */
spapr_machine_5_2_class_options(MachineClass * mc)4967576a00bdSCornelia Huck static void spapr_machine_5_2_class_options(MachineClass *mc)
4968576a00bdSCornelia Huck {
4969576a00bdSCornelia Huck     spapr_machine_6_0_class_options(mc);
4970576a00bdSCornelia Huck     compat_props_add(mc->compat_props, hw_compat_5_2, hw_compat_5_2_len);
4971576a00bdSCornelia Huck }
4972576a00bdSCornelia Huck 
49738d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(5, 2);
49743ff3c5d3SCornelia Huck 
49753ff3c5d3SCornelia Huck /*
49763ff3c5d3SCornelia Huck  * pseries-5.1
49773ff3c5d3SCornelia Huck  */
spapr_machine_5_1_class_options(MachineClass * mc)49783ff3c5d3SCornelia Huck static void spapr_machine_5_1_class_options(MachineClass *mc)
49793ff3c5d3SCornelia Huck {
498029bfe52aSDaniel Henrique Barboza     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
498129bfe52aSDaniel Henrique Barboza 
49823ff3c5d3SCornelia Huck     spapr_machine_5_2_class_options(mc);
49833ff3c5d3SCornelia Huck     compat_props_add(mc->compat_props, hw_compat_5_1, hw_compat_5_1_len);
498429bfe52aSDaniel Henrique Barboza     smc->pre_5_2_numa_associativity = true;
49853ff3c5d3SCornelia Huck }
49863ff3c5d3SCornelia Huck 
49878d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(5, 1);
4988541aaa1dSCornelia Huck 
4989541aaa1dSCornelia Huck /*
4990541aaa1dSCornelia Huck  * pseries-5.0
4991541aaa1dSCornelia Huck  */
spapr_machine_5_0_class_options(MachineClass * mc)4992541aaa1dSCornelia Huck static void spapr_machine_5_0_class_options(MachineClass *mc)
4993541aaa1dSCornelia Huck {
4994a6030d7eSReza Arbab     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
4995a6030d7eSReza Arbab     static GlobalProperty compat[] = {
4996a6030d7eSReza Arbab         { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-5.1-associativity", "on" },
4997a6030d7eSReza Arbab     };
4998a6030d7eSReza Arbab 
4999541aaa1dSCornelia Huck     spapr_machine_5_1_class_options(mc);
5000541aaa1dSCornelia Huck     compat_props_add(mc->compat_props, hw_compat_5_0, hw_compat_5_0_len);
5001a6030d7eSReza Arbab     compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
500232a354dcSIgor Mammedov     mc->numa_mem_supported = true;
5003a6030d7eSReza Arbab     smc->pre_5_1_assoc_refpoints = true;
5004541aaa1dSCornelia Huck }
5005541aaa1dSCornelia Huck 
50068d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(5, 0);
50073eb74d20SCornelia Huck 
50083eb74d20SCornelia Huck /*
50099aec2e52SCornelia Huck  * pseries-4.2
5010e2676b16SGreg Kurz  */
spapr_machine_4_2_class_options(MachineClass * mc)50119aec2e52SCornelia Huck static void spapr_machine_4_2_class_options(MachineClass *mc)
5012e2676b16SGreg Kurz {
501337965dfeSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
501437965dfeSDavid Gibson 
50153eb74d20SCornelia Huck     spapr_machine_5_0_class_options(mc);
50165f258577SEvgeny Yakovlev     compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len);
501737965dfeSDavid Gibson     smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF;
50188af7e1feSNicholas Piggin     smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_OFF;
50191052ab67SDavid Gibson     smc->rma_limit = 16 * GiB;
5020ee3a71e3SShivaprasad G Bhat     mc->nvdimm_supported = false;
5021e2676b16SGreg Kurz }
5022e2676b16SGreg Kurz 
50238d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(4, 2);
50249aec2e52SCornelia Huck 
50259aec2e52SCornelia Huck /*
50269aec2e52SCornelia Huck  * pseries-4.1
50279aec2e52SCornelia Huck  */
spapr_machine_4_1_class_options(MachineClass * mc)50289aec2e52SCornelia Huck static void spapr_machine_4_1_class_options(MachineClass *mc)
50299aec2e52SCornelia Huck {
50306c3829a2SAlexey Kardashevskiy     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
5031d15d4ad6SDavid Gibson     static GlobalProperty compat[] = {
5032d15d4ad6SDavid Gibson         /* Only allow 4kiB and 64kiB IOMMU pagesizes */
5033d15d4ad6SDavid Gibson         { TYPE_SPAPR_PCI_HOST_BRIDGE, "pgsz", "0x11000" },
5034d15d4ad6SDavid Gibson     };
5035d15d4ad6SDavid Gibson 
50369aec2e52SCornelia Huck     spapr_machine_4_2_class_options(mc);
50376c3829a2SAlexey Kardashevskiy     smc->linux_pci_probe = false;
503829cb4187SGreg Kurz     smc->smp_threads_vsmt = false;
50399aec2e52SCornelia Huck     compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len);
5040d15d4ad6SDavid Gibson     compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
50419aec2e52SCornelia Huck }
50429aec2e52SCornelia Huck 
50438d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(4, 1);
50449bf2650bSCornelia Huck 
50459bf2650bSCornelia Huck /*
50469bf2650bSCornelia Huck  * pseries-4.0
50479bf2650bSCornelia 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)5048f5598c92SGreg Kurz static bool phb_placement_4_0(SpaprMachineState *spapr, uint32_t index,
5049ec132efaSAlexey Kardashevskiy                               uint64_t *buid, hwaddr *pio,
5050ec132efaSAlexey Kardashevskiy                               hwaddr *mmio32, hwaddr *mmio64,
505144fa20c9SCédric Le Goater                               unsigned n_dma, uint32_t *liobns, Error **errp)
5052ec132efaSAlexey Kardashevskiy {
5053f5598c92SGreg Kurz     if (!spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma,
505444fa20c9SCédric Le Goater                              liobns, errp)) {
5055f5598c92SGreg Kurz         return false;
5056ec132efaSAlexey Kardashevskiy     }
5057f5598c92SGreg Kurz     return true;
5058f5598c92SGreg Kurz }
spapr_machine_4_0_class_options(MachineClass * mc)5059eb3cba82SDavid Gibson static void spapr_machine_4_0_class_options(MachineClass *mc)
5060eb3cba82SDavid Gibson {
5061eb3cba82SDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
5062eb3cba82SDavid Gibson 
5063eb3cba82SDavid Gibson     spapr_machine_4_1_class_options(mc);
5064eb3cba82SDavid Gibson     compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
5065eb3cba82SDavid Gibson     smc->phb_placement = phb_placement_4_0;
5066bd94bc06SCédric Le Goater     smc->irq = &spapr_irq_xics;
50673725ef1aSGreg Kurz     smc->pre_4_1_migration = true;
5068eb3cba82SDavid Gibson }
5069eb3cba82SDavid Gibson 
50708d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(4, 0);
5071eb3cba82SDavid Gibson 
5072eb3cba82SDavid Gibson /*
5073eb3cba82SDavid Gibson  * pseries-3.1
5074eb3cba82SDavid Gibson  */
spapr_machine_3_1_class_options(MachineClass * mc)507588cbe073SMarc-André Lureau static void spapr_machine_3_1_class_options(MachineClass *mc)
507688cbe073SMarc-André Lureau {
5077ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
5078fea35ca4SAlexey Kardashevskiy 
507984e060bfSAlex Williamson     spapr_machine_4_0_class_options(mc);
5080abd93cc7SMarc-André Lureau     compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len);
508127461d69SPrasad J Pandit 
508234a6b015SCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
5083fea35ca4SAlexey Kardashevskiy     smc->update_dt_enabled = false;
5084dae5e39aSMichael Roth     smc->dr_phb_enabled = false;
50850a794529SDavid Gibson     smc->broken_host_serial_model = true;
50862782ad4cSSuraj Jitindar Singh     smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
50872782ad4cSSuraj Jitindar Singh     smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
50882782ad4cSSuraj Jitindar Singh     smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
5089edaa7995SSuraj Jitindar Singh     smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF;
509084e060bfSAlex Williamson }
509184e060bfSAlex Williamson 
50928d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(3, 1);
5093d45360d9SCédric Le Goater 
5094d45360d9SCédric Le Goater /*
5095d45360d9SCédric Le Goater  * pseries-3.0
5096d45360d9SCédric Le Goater  */
5097d45360d9SCédric Le Goater 
spapr_machine_3_0_class_options(MachineClass * mc)5098d45360d9SCédric Le Goater static void spapr_machine_3_0_class_options(MachineClass *mc)
5099d45360d9SCédric Le Goater {
5100ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
510182cffa2eSCédric Le Goater 
5102d45360d9SCédric Le Goater     spapr_machine_3_1_class_options(mc);
5103ddb3235dSMarc-André Lureau     compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len);
510482cffa2eSCédric Le Goater 
510582cffa2eSCédric Le Goater     smc->legacy_irq_allocation = true;
510654255c1fSDavid Gibson     smc->nr_xirqs = 0x400;
5107ae837402SCédric Le Goater     smc->irq = &spapr_irq_xics_legacy;
5108d45360d9SCédric Le Goater }
5109d45360d9SCédric Le Goater 
51108d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(3, 0);
51118a4fd427SDavid Gibson 
51128a4fd427SDavid Gibson /*
51138a4fd427SDavid Gibson  * pseries-2.12
51148a4fd427SDavid Gibson  */
spapr_machine_2_12_class_options(MachineClass * mc)511588cbe073SMarc-André Lureau static void spapr_machine_2_12_class_options(MachineClass *mc)
511688cbe073SMarc-André Lureau {
5117ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
511888cbe073SMarc-André Lureau     static GlobalProperty compat[] = {
51196c36bddfSEduardo Habkost         { TYPE_POWERPC_CPU, "pre-3.0-migration", "on" },
51206c36bddfSEduardo Habkost         { TYPE_SPAPR_CPU_CORE, "pre-3.0-migration", "on" },
5121fa386d98SMarc-André Lureau     };
51228a4fd427SDavid Gibson 
5123d8c0c7afSPeter Maydell     spapr_machine_3_0_class_options(mc);
51240d47310bSMarc-André Lureau     compat_props_add(mc->compat_props, hw_compat_2_12, hw_compat_2_12_len);
512588cbe073SMarc-André Lureau     compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
51262309832aSDavid Gibson 
5127e8937295SGreg Kurz     /* We depend on kvm_enabled() to choose a default value for the
5128e8937295SGreg Kurz      * hpt-max-page-size capability. Of course we can't do it here
5129e6a19a64SMichael Tokarev      * because this is too early and the HW accelerator isn't initialized
5130e8937295SGreg Kurz      * yet. Postpone this to machine init (see default_caps_with_cpu()).
5131e8937295SGreg Kurz      */
5132e8937295SGreg Kurz     smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 0;
51338a4fd427SDavid Gibson }
51348a4fd427SDavid Gibson 
51358d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(2, 12);
51362b615412SDavid Gibson 
spapr_machine_2_12_sxxm_class_options(MachineClass * mc)5137813f3cf6SSuraj Jitindar Singh static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc)
5138813f3cf6SSuraj Jitindar Singh {
5139ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
5140813f3cf6SSuraj Jitindar Singh 
5141813f3cf6SSuraj Jitindar Singh     spapr_machine_2_12_class_options(mc);
5142813f3cf6SSuraj Jitindar Singh     smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND;
5143813f3cf6SSuraj Jitindar Singh     smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND;
5144813f3cf6SSuraj Jitindar Singh     smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_FIXED_CCD;
5145813f3cf6SSuraj Jitindar Singh }
5146813f3cf6SSuraj Jitindar Singh 
51478d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE_TAGGED(2, 12, sxxm);
5148813f3cf6SSuraj Jitindar Singh 
51492b615412SDavid Gibson /*
51502b615412SDavid Gibson  * pseries-2.11
51512b615412SDavid Gibson  */
51522b615412SDavid Gibson 
spapr_machine_2_11_class_options(MachineClass * mc)51532b615412SDavid Gibson static void spapr_machine_2_11_class_options(MachineClass *mc)
51542b615412SDavid Gibson {
5155ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
5156ee76a09fSDavid Gibson 
51572b615412SDavid Gibson     spapr_machine_2_12_class_options(mc);
51584e5fe368SSuraj Jitindar Singh     smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON;
515943df70a9SMarc-André Lureau     compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len);
51602b615412SDavid Gibson }
51612b615412SDavid Gibson 
51628d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(2, 11);
5163e2676b16SGreg Kurz 
5164e2676b16SGreg Kurz /*
51653fa14fbeSDavid Gibson  * pseries-2.10
5166db800b21SDavid Gibson  */
5167e2676b16SGreg Kurz 
spapr_machine_2_10_class_options(MachineClass * mc)51683fa14fbeSDavid Gibson static void spapr_machine_2_10_class_options(MachineClass *mc)
5169db800b21SDavid Gibson {
5170e2676b16SGreg Kurz     spapr_machine_2_11_class_options(mc);
5171503224f4SMarc-André Lureau     compat_props_add(mc->compat_props, hw_compat_2_10, hw_compat_2_10_len);
5172db800b21SDavid Gibson }
5173db800b21SDavid Gibson 
51748d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(2, 10);
51753fa14fbeSDavid Gibson 
51763fa14fbeSDavid Gibson /*
51773fa14fbeSDavid Gibson  * pseries-2.9
51783fa14fbeSDavid Gibson  */
517988cbe073SMarc-André Lureau 
spapr_machine_2_9_class_options(MachineClass * mc)518088cbe073SMarc-André Lureau static void spapr_machine_2_9_class_options(MachineClass *mc)
518188cbe073SMarc-André Lureau {
5182ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
518388cbe073SMarc-André Lureau     static GlobalProperty compat[] = {
51846c36bddfSEduardo Habkost         { TYPE_POWERPC_CPU, "pre-2.10-migration", "on" },
5185fa386d98SMarc-André Lureau     };
51863fa14fbeSDavid Gibson 
51873fa14fbeSDavid Gibson     spapr_machine_2_10_class_options(mc);
51883e803152SMarc-André Lureau     compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len);
518988cbe073SMarc-André Lureau     compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
519046f7afa3SGreg Kurz     smc->pre_2_10_has_unused_icps = true;
519152b81ab5SDavid Gibson     smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED;
51923fa14fbeSDavid Gibson }
51933fa14fbeSDavid Gibson 
51948d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(2, 9);
5195fa325e6cSDavid Gibson 
5196fa325e6cSDavid Gibson /*
5197fa325e6cSDavid Gibson  * pseries-2.8
5198fa325e6cSDavid Gibson  */
519988cbe073SMarc-André Lureau 
spapr_machine_2_8_class_options(MachineClass * mc)520088cbe073SMarc-André Lureau static void spapr_machine_2_8_class_options(MachineClass *mc)
520188cbe073SMarc-André Lureau {
520288cbe073SMarc-André Lureau     static GlobalProperty compat[] = {
52036c36bddfSEduardo Habkost         { TYPE_SPAPR_PCI_HOST_BRIDGE, "pcie-extended-configuration-space", "off" },
5204fa386d98SMarc-André Lureau     };
5205fa325e6cSDavid Gibson 
5206fa325e6cSDavid Gibson     spapr_machine_2_9_class_options(mc);
5207edc24ccdSMarc-André Lureau     compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len);
520888cbe073SMarc-André Lureau     compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
520955641213SLaurent Vivier     mc->numa_mem_align_shift = 23;
5210fa325e6cSDavid Gibson }
5211fa325e6cSDavid Gibson 
52128d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(2, 8);
5213db800b21SDavid Gibson 
5214db800b21SDavid Gibson /*
52151ea1eefcSBharata B Rao  * pseries-2.7
52161ea1eefcSBharata B Rao  */
5217357d1e3bSDavid Gibson 
phb_placement_2_7(SpaprMachineState * spapr,uint32_t index,uint64_t * buid,hwaddr * pio,hwaddr * mmio32,hwaddr * mmio64,unsigned n_dma,uint32_t * liobns,Error ** errp)5218f5598c92SGreg Kurz static bool phb_placement_2_7(SpaprMachineState *spapr, uint32_t index,
5219357d1e3bSDavid Gibson                               uint64_t *buid, hwaddr *pio,
5220357d1e3bSDavid Gibson                               hwaddr *mmio32, hwaddr *mmio64,
522144fa20c9SCédric Le Goater                               unsigned n_dma, uint32_t *liobns, Error **errp)
5222357d1e3bSDavid Gibson {
5223357d1e3bSDavid Gibson     /* Legacy PHB placement for pseries-2.7 and earlier machine types */
5224357d1e3bSDavid Gibson     const uint64_t base_buid = 0x800000020000000ULL;
5225357d1e3bSDavid Gibson     const hwaddr phb_spacing = 0x1000000000ULL; /* 64 GiB */
5226357d1e3bSDavid Gibson     const hwaddr mmio_offset = 0xa0000000; /* 2 GiB + 512 MiB */
5227357d1e3bSDavid Gibson     const hwaddr pio_offset = 0x80000000; /* 2 GiB */
5228357d1e3bSDavid Gibson     const uint32_t max_index = 255;
5229357d1e3bSDavid Gibson     const hwaddr phb0_alignment = 0x10000000000ULL; /* 1 TiB */
5230357d1e3bSDavid Gibson 
5231357d1e3bSDavid Gibson     uint64_t ram_top = MACHINE(spapr)->ram_size;
5232357d1e3bSDavid Gibson     hwaddr phb0_base, phb_base;
5233357d1e3bSDavid Gibson     int i;
5234357d1e3bSDavid Gibson 
52350c9269a5SDavid Hildenbrand     /* Do we have device memory? */
5236c0ce7b4aSDavid Hildenbrand     if (MACHINE(spapr)->device_memory) {
5237357d1e3bSDavid Gibson         /* Can't just use maxram_size, because there may be an
52380c9269a5SDavid Hildenbrand          * alignment gap between normal and device memory regions
52390c9269a5SDavid Hildenbrand          */
5240b0c14ec4SDavid Hildenbrand         ram_top = MACHINE(spapr)->device_memory->base +
5241b0c14ec4SDavid Hildenbrand             memory_region_size(&MACHINE(spapr)->device_memory->mr);
5242357d1e3bSDavid Gibson     }
5243357d1e3bSDavid Gibson 
5244357d1e3bSDavid Gibson     phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment);
5245357d1e3bSDavid Gibson 
5246357d1e3bSDavid Gibson     if (index > max_index) {
5247357d1e3bSDavid Gibson         error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)",
5248357d1e3bSDavid Gibson                    max_index);
5249f5598c92SGreg Kurz         return false;
5250357d1e3bSDavid Gibson     }
5251357d1e3bSDavid Gibson 
5252357d1e3bSDavid Gibson     *buid = base_buid + index;
5253357d1e3bSDavid Gibson     for (i = 0; i < n_dma; ++i) {
5254357d1e3bSDavid Gibson         liobns[i] = SPAPR_PCI_LIOBN(index, i);
5255357d1e3bSDavid Gibson     }
5256357d1e3bSDavid Gibson 
5257357d1e3bSDavid Gibson     phb_base = phb0_base + index * phb_spacing;
5258357d1e3bSDavid Gibson     *pio = phb_base + pio_offset;
5259357d1e3bSDavid Gibson     *mmio32 = phb_base + mmio_offset;
5260357d1e3bSDavid Gibson     /*
5261357d1e3bSDavid Gibson      * We don't set the 64-bit MMIO window, relying on the PHB's
5262357d1e3bSDavid Gibson      * fallback behaviour of automatically splitting a large "32-bit"
5263357d1e3bSDavid Gibson      * window into contiguous 32-bit and 64-bit windows
5264357d1e3bSDavid Gibson      */
5265ec132efaSAlexey Kardashevskiy 
5266f5598c92SGreg Kurz     return true;
5267357d1e3bSDavid Gibson }
5268db800b21SDavid Gibson 
spapr_machine_2_7_class_options(MachineClass * mc)52691ea1eefcSBharata B Rao static void spapr_machine_2_7_class_options(MachineClass *mc)
52701ea1eefcSBharata B Rao {
5271ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
527288cbe073SMarc-André Lureau     static GlobalProperty compat[] = {
52736c36bddfSEduardo Habkost         { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0xf80000000", },
52746c36bddfSEduardo Habkost         { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem64_win_size", "0", },
52756c36bddfSEduardo Habkost         { TYPE_POWERPC_CPU, "pre-2.8-migration", "on", },
52766c36bddfSEduardo Habkost         { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-2.8-migration", "on", },
527788cbe073SMarc-André Lureau     };
52783daa4a9fSThomas Huth 
5279db800b21SDavid Gibson     spapr_machine_2_8_class_options(mc);
52802e9c10ebSIgor Mammedov     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power7_v2.3");
5281a140c199SEduardo Habkost     mc->default_machine_opts = "modern-hotplug-events=off";
52825a995064SMarc-André Lureau     compat_props_add(mc->compat_props, hw_compat_2_7, hw_compat_2_7_len);
528388cbe073SMarc-André Lureau     compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
5284357d1e3bSDavid Gibson     smc->phb_placement = phb_placement_2_7;
52851ea1eefcSBharata B Rao }
52861ea1eefcSBharata B Rao 
52878d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(2, 7);
52881ea1eefcSBharata B Rao 
52891ea1eefcSBharata B Rao /*
52904b23699cSDavid Gibson  * pseries-2.6
52914b23699cSDavid Gibson  */
529288cbe073SMarc-André Lureau 
spapr_machine_2_6_class_options(MachineClass * mc)529388cbe073SMarc-André Lureau static void spapr_machine_2_6_class_options(MachineClass *mc)
529488cbe073SMarc-André Lureau {
529588cbe073SMarc-André Lureau     static GlobalProperty compat[] = {
52966c36bddfSEduardo Habkost         { TYPE_SPAPR_PCI_HOST_BRIDGE, "ddw", "off" },
5297fa386d98SMarc-André Lureau     };
52981ea1eefcSBharata B Rao 
52991ea1eefcSBharata B Rao     spapr_machine_2_7_class_options(mc);
5300c5514d0eSIgor Mammedov     mc->has_hotpluggable_cpus = false;
5301ff8f261fSMarc-André Lureau     compat_props_add(mc->compat_props, hw_compat_2_6, hw_compat_2_6_len);
530288cbe073SMarc-André Lureau     compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
53034b23699cSDavid Gibson }
53044b23699cSDavid Gibson 
53058d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(2, 6);
53064b23699cSDavid Gibson 
53074b23699cSDavid Gibson /*
53081c5f29bbSDavid Gibson  * pseries-2.5
53091c5f29bbSDavid Gibson  */
531088cbe073SMarc-André Lureau 
spapr_machine_2_5_class_options(MachineClass * mc)531188cbe073SMarc-André Lureau static void spapr_machine_2_5_class_options(MachineClass *mc)
531288cbe073SMarc-André Lureau {
5313ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
531488cbe073SMarc-André Lureau     static GlobalProperty compat[] = {
53156c36bddfSEduardo Habkost         { "spapr-vlan", "use-rx-buffer-pools", "off" },
5316fa386d98SMarc-André Lureau     };
53174b23699cSDavid Gibson 
53184b23699cSDavid Gibson     spapr_machine_2_6_class_options(mc);
531957040d45SThomas Huth     smc->use_ohci_by_default = true;
5320fe759610SMarc-André Lureau     compat_props_add(mc->compat_props, hw_compat_2_5, hw_compat_2_5_len);
532188cbe073SMarc-André Lureau     compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
53221c5f29bbSDavid Gibson }
53231c5f29bbSDavid Gibson 
53248d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(2, 5);
53251c5f29bbSDavid Gibson 
53261c5f29bbSDavid Gibson /*
53271c5f29bbSDavid Gibson  * pseries-2.4
53281c5f29bbSDavid Gibson  */
532980fd50f9SCornelia Huck 
spapr_machine_2_4_class_options(MachineClass * mc)53305013c547SDavid Gibson static void spapr_machine_2_4_class_options(MachineClass *mc)
53315013c547SDavid Gibson {
5332ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
5333fc9f38c3SDavid Gibson 
5334fc9f38c3SDavid Gibson     spapr_machine_2_5_class_options(mc);
5335fc9f38c3SDavid Gibson     smc->dr_lmb_enabled = false;
53362f99b9c2SMarc-André Lureau     compat_props_add(mc->compat_props, hw_compat_2_4, hw_compat_2_4_len);
53371c5f29bbSDavid Gibson }
53381c5f29bbSDavid Gibson 
53398d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(2, 4);
53401c5f29bbSDavid Gibson 
53411c5f29bbSDavid Gibson /*
53421c5f29bbSDavid Gibson  * pseries-2.3
53431c5f29bbSDavid Gibson  */
534488cbe073SMarc-André Lureau 
spapr_machine_2_3_class_options(MachineClass * mc)534588cbe073SMarc-André Lureau static void spapr_machine_2_3_class_options(MachineClass *mc)
534688cbe073SMarc-André Lureau {
534788cbe073SMarc-André Lureau     static GlobalProperty compat[] = {
53486c36bddfSEduardo Habkost         { "spapr-pci-host-bridge", "dynamic-reconfiguration", "off" },
5349fa386d98SMarc-André Lureau     };
5350fc9f38c3SDavid Gibson     spapr_machine_2_4_class_options(mc);
53518995dd90SMarc-André Lureau     compat_props_add(mc->compat_props, hw_compat_2_3, hw_compat_2_3_len);
535288cbe073SMarc-André Lureau     compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
53531c5f29bbSDavid Gibson }
53548d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(2, 3);
53551c5f29bbSDavid Gibson 
53561c5f29bbSDavid Gibson /*
53571c5f29bbSDavid Gibson  * pseries-2.2
53581c5f29bbSDavid Gibson  */
535988cbe073SMarc-André Lureau 
spapr_machine_2_2_class_options(MachineClass * mc)536088cbe073SMarc-André Lureau static void spapr_machine_2_2_class_options(MachineClass *mc)
536188cbe073SMarc-André Lureau {
536288cbe073SMarc-André Lureau     static GlobalProperty compat[] = {
53636c36bddfSEduardo Habkost         { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0x20000000" },
5364fa386d98SMarc-André Lureau     };
5365b194df47SAlexey Kardashevskiy 
5366fc9f38c3SDavid Gibson     spapr_machine_2_3_class_options(mc);
53671c30044eSMarc-André Lureau     compat_props_add(mc->compat_props, hw_compat_2_2, hw_compat_2_2_len);
536888cbe073SMarc-André Lureau     compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
5369f6d0656bSEduardo Habkost     mc->default_machine_opts = "modern-hotplug-events=off,suppress-vmdesc=on";
53701c5f29bbSDavid Gibson }
53718d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(2, 2);
53721c5f29bbSDavid Gibson 
53731c5f29bbSDavid Gibson /*
53741c5f29bbSDavid Gibson  * pseries-2.1
53751c5f29bbSDavid Gibson  */
53761c5f29bbSDavid Gibson 
spapr_machine_2_1_class_options(MachineClass * mc)53775013c547SDavid Gibson static void spapr_machine_2_1_class_options(MachineClass *mc)
5378b0e966d0SJason Wang {
5379fc9f38c3SDavid Gibson     spapr_machine_2_2_class_options(mc);
5380c4fc5695SMarc-André Lureau     compat_props_add(mc->compat_props, hw_compat_2_1, hw_compat_2_1_len);
53816026db45SAlexey Kardashevskiy }
53828d40cc14SDaniel P. Berrangé DEFINE_SPAPR_MACHINE(2, 1);
53836026db45SAlexey Kardashevskiy 
spapr_machine_register_types(void)538429ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void)
538529ee3247SAlexey Kardashevskiy {
538629ee3247SAlexey Kardashevskiy     type_register_static(&spapr_machine_info);
538729ee3247SAlexey Kardashevskiy }
538829ee3247SAlexey Kardashevskiy 
538929ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types)
5390