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