hw/mips/malta: Fix the malta machine on big endian hosts
[qemu/ar7.git] / hw / ppc / spapr_vof.c
blob09f29be0b9de02e02fc482b2a79228c2f6cd5b9a
1 /*
2 * SPAPR machine hooks to Virtual Open Firmware,
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 #include "qemu/osdep.h"
7 #include "qapi/error.h"
8 #include "hw/ppc/spapr.h"
9 #include "hw/ppc/spapr_vio.h"
10 #include "hw/ppc/spapr_cpu_core.h"
11 #include "hw/ppc/fdt.h"
12 #include "hw/ppc/vof.h"
13 #include "sysemu/sysemu.h"
14 #include "qom/qom-qobject.h"
15 #include "trace.h"
17 target_ulong spapr_h_vof_client(PowerPCCPU *cpu, SpaprMachineState *spapr,
18 target_ulong opcode, target_ulong *_args)
20 int ret = vof_client_call(MACHINE(spapr), spapr->vof, spapr->fdt_blob,
21 ppc64_phys_to_real(_args[0]));
23 if (ret) {
24 return H_PARAMETER;
26 return H_SUCCESS;
29 void spapr_vof_client_dt_finalize(SpaprMachineState *spapr, void *fdt)
31 char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus);
33 vof_build_dt(fdt, spapr->vof);
35 if (spapr->vof->bootargs) {
36 int chosen;
38 _FDT(chosen = fdt_path_offset(fdt, "/chosen"));
40 * If the client did not change "bootargs", spapr_dt_chosen() must have
41 * stored machine->kernel_cmdline in it before getting here.
43 _FDT(fdt_setprop_string(fdt, chosen, "bootargs", spapr->vof->bootargs));
47 * SLOF-less setup requires an open instance of stdout for early
48 * kernel printk. By now all phandles are settled so we can open
49 * the default serial console.
51 if (stdout_path) {
52 _FDT(vof_client_open_store(fdt, spapr->vof, "/chosen", "stdout",
53 stdout_path));
57 void spapr_vof_reset(SpaprMachineState *spapr, void *fdt, Error **errp)
59 target_ulong stack_ptr;
60 Vof *vof = spapr->vof;
61 PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu);
63 vof_init(vof, spapr->rma_size, errp);
65 stack_ptr = vof_claim(vof, 0, VOF_STACK_SIZE, VOF_STACK_SIZE);
66 if (stack_ptr == -1) {
67 error_setg(errp, "Memory allocation for stack failed");
68 return;
70 /* Stack grows downwards plus reserve space for the minimum stack frame */
71 stack_ptr += VOF_STACK_SIZE - 0x20;
73 if (spapr->kernel_size &&
74 vof_claim(vof, spapr->kernel_addr, spapr->kernel_size, 0) == -1) {
75 error_setg(errp, "Memory for kernel is in use");
76 return;
79 if (spapr->initrd_size &&
80 vof_claim(vof, spapr->initrd_base, spapr->initrd_size, 0) == -1) {
81 error_setg(errp, "Memory for initramdisk is in use");
82 return;
85 spapr_vof_client_dt_finalize(spapr, fdt);
87 spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT,
88 stack_ptr, spapr->initrd_base,
89 spapr->initrd_size);
92 * At this point the expected allocation map is:
94 * 0..c38 - the initial firmware
95 * 8000..10000 - stack
96 * 400000.. - kernel
97 * 3ea0000.. - initramdisk
99 * We skip writing FDT as nothing expects it; OF client interface is
100 * going to be used for reading the device tree.
104 void spapr_vof_quiesce(MachineState *ms)
106 SpaprMachineState *spapr = SPAPR_MACHINE(ms);
108 spapr->fdt_size = fdt_totalsize(spapr->fdt_blob);
109 spapr->fdt_initial_size = spapr->fdt_size;
112 bool spapr_vof_setprop(MachineState *ms, const char *path, const char *propname,
113 void *val, int vallen)
115 SpaprMachineState *spapr = SPAPR_MACHINE(ms);
118 * We only allow changing properties which we know how to update in QEMU
119 * OR
120 * the ones which we know that they need to survive during "quiesce".
123 if (strcmp(path, "/rtas") == 0) {
124 if (strcmp(propname, "linux,rtas-base") == 0 ||
125 strcmp(propname, "linux,rtas-entry") == 0) {
126 /* These need to survive quiesce so let them store in the FDT */
127 return true;
131 if (strcmp(path, "/chosen") == 0) {
132 if (strcmp(propname, "bootargs") == 0) {
133 Vof *vof = spapr->vof;
135 g_free(vof->bootargs);
136 vof->bootargs = g_strndup(val, vallen);
137 return true;
139 if (strcmp(propname, "linux,initrd-start") == 0) {
140 if (vallen == sizeof(uint32_t)) {
141 spapr->initrd_base = ldl_be_p(val);
142 return true;
144 if (vallen == sizeof(uint64_t)) {
145 spapr->initrd_base = ldq_be_p(val);
146 return true;
148 return false;
150 if (strcmp(propname, "linux,initrd-end") == 0) {
151 if (vallen == sizeof(uint32_t)) {
152 spapr->initrd_size = ldl_be_p(val) - spapr->initrd_base;
153 return true;
155 if (vallen == sizeof(uint64_t)) {
156 spapr->initrd_size = ldq_be_p(val) - spapr->initrd_base;
157 return true;
159 return false;
163 return true;