xref: /openbmc/qemu/hw/core/machine-qmp-cmds.c (revision c2387413)
1 /*
2  * QMP commands related to machines and CPUs
3  *
4  * Copyright (C) 2014 Red Hat Inc
5  *
6  * This work is licensed under the terms of the GNU GPL, version 2 or later.
7  * See the COPYING file in the top-level directory.
8  */
9 
10 #include "qemu/osdep.h"
11 #include "cpu.h"
12 #include "hw/boards.h"
13 #include "qapi/error.h"
14 #include "qapi/qapi-builtin-visit.h"
15 #include "qapi/qapi-commands-machine.h"
16 #include "qapi/qmp/qerror.h"
17 #include "qapi/qmp/qobject.h"
18 #include "qapi/qobject-input-visitor.h"
19 #include "qemu/main-loop.h"
20 #include "qom/qom-qobject.h"
21 #include "sysemu/hostmem.h"
22 #include "sysemu/hw_accel.h"
23 #include "sysemu/numa.h"
24 #include "sysemu/runstate.h"
25 #include "sysemu/sysemu.h"
26 
27 CpuInfoList *qmp_query_cpus(Error **errp)
28 {
29     MachineState *ms = MACHINE(qdev_get_machine());
30     MachineClass *mc = MACHINE_GET_CLASS(ms);
31     CpuInfoList *head = NULL, **tail = &head;
32     CPUState *cpu;
33 
34     CPU_FOREACH(cpu) {
35         CpuInfo *value;
36 #if defined(TARGET_I386)
37         X86CPU *x86_cpu = X86_CPU(cpu);
38         CPUX86State *env = &x86_cpu->env;
39 #elif defined(TARGET_PPC)
40         PowerPCCPU *ppc_cpu = POWERPC_CPU(cpu);
41         CPUPPCState *env = &ppc_cpu->env;
42 #elif defined(TARGET_SPARC)
43         SPARCCPU *sparc_cpu = SPARC_CPU(cpu);
44         CPUSPARCState *env = &sparc_cpu->env;
45 #elif defined(TARGET_RISCV)
46         RISCVCPU *riscv_cpu = RISCV_CPU(cpu);
47         CPURISCVState *env = &riscv_cpu->env;
48 #elif defined(TARGET_MIPS)
49         MIPSCPU *mips_cpu = MIPS_CPU(cpu);
50         CPUMIPSState *env = &mips_cpu->env;
51 #elif defined(TARGET_TRICORE)
52         TriCoreCPU *tricore_cpu = TRICORE_CPU(cpu);
53         CPUTriCoreState *env = &tricore_cpu->env;
54 #elif defined(TARGET_S390X)
55         S390CPU *s390_cpu = S390_CPU(cpu);
56         CPUS390XState *env = &s390_cpu->env;
57 #endif
58 
59         cpu_synchronize_state(cpu);
60 
61         value = g_malloc0(sizeof(*value));
62         value->CPU = cpu->cpu_index;
63         value->current = (cpu == first_cpu);
64         value->halted = cpu->halted;
65         value->qom_path = object_get_canonical_path(OBJECT(cpu));
66         value->thread_id = cpu->thread_id;
67 #if defined(TARGET_I386)
68         value->arch = CPU_INFO_ARCH_X86;
69         value->u.x86.pc = env->eip + env->segs[R_CS].base;
70 #elif defined(TARGET_PPC)
71         value->arch = CPU_INFO_ARCH_PPC;
72         value->u.ppc.nip = env->nip;
73 #elif defined(TARGET_SPARC)
74         value->arch = CPU_INFO_ARCH_SPARC;
75         value->u.q_sparc.pc = env->pc;
76         value->u.q_sparc.npc = env->npc;
77 #elif defined(TARGET_MIPS)
78         value->arch = CPU_INFO_ARCH_MIPS;
79         value->u.q_mips.PC = env->active_tc.PC;
80 #elif defined(TARGET_TRICORE)
81         value->arch = CPU_INFO_ARCH_TRICORE;
82         value->u.tricore.PC = env->PC;
83 #elif defined(TARGET_S390X)
84         value->arch = CPU_INFO_ARCH_S390;
85         value->u.s390.cpu_state = env->cpu_state;
86 #elif defined(TARGET_RISCV)
87         value->arch = CPU_INFO_ARCH_RISCV;
88         value->u.riscv.pc = env->pc;
89 #else
90         value->arch = CPU_INFO_ARCH_OTHER;
91 #endif
92         value->has_props = !!mc->cpu_index_to_instance_props;
93         if (value->has_props) {
94             CpuInstanceProperties *props;
95             props = g_malloc0(sizeof(*props));
96             *props = mc->cpu_index_to_instance_props(ms, cpu->cpu_index);
97             value->props = props;
98         }
99 
100         QAPI_LIST_APPEND(tail, value);
101     }
102 
103     return head;
104 }
105 
106 static CpuInfoArch sysemu_target_to_cpuinfo_arch(SysEmuTarget target)
107 {
108     /*
109      * The @SysEmuTarget -> @CpuInfoArch mapping below is based on the
110      * TARGET_ARCH -> TARGET_BASE_ARCH mapping in the "configure" script.
111      */
112     switch (target) {
113     case SYS_EMU_TARGET_I386:
114     case SYS_EMU_TARGET_X86_64:
115         return CPU_INFO_ARCH_X86;
116 
117     case SYS_EMU_TARGET_PPC:
118     case SYS_EMU_TARGET_PPC64:
119         return CPU_INFO_ARCH_PPC;
120 
121     case SYS_EMU_TARGET_SPARC:
122     case SYS_EMU_TARGET_SPARC64:
123         return CPU_INFO_ARCH_SPARC;
124 
125     case SYS_EMU_TARGET_MIPS:
126     case SYS_EMU_TARGET_MIPSEL:
127     case SYS_EMU_TARGET_MIPS64:
128     case SYS_EMU_TARGET_MIPS64EL:
129         return CPU_INFO_ARCH_MIPS;
130 
131     case SYS_EMU_TARGET_TRICORE:
132         return CPU_INFO_ARCH_TRICORE;
133 
134     case SYS_EMU_TARGET_S390X:
135         return CPU_INFO_ARCH_S390;
136 
137     case SYS_EMU_TARGET_RISCV32:
138     case SYS_EMU_TARGET_RISCV64:
139         return CPU_INFO_ARCH_RISCV;
140 
141     default:
142         return CPU_INFO_ARCH_OTHER;
143     }
144 }
145 
146 static void cpustate_to_cpuinfo_s390(CpuInfoS390 *info, const CPUState *cpu)
147 {
148 #ifdef TARGET_S390X
149     S390CPU *s390_cpu = S390_CPU(cpu);
150     CPUS390XState *env = &s390_cpu->env;
151 
152     info->cpu_state = env->cpu_state;
153 #else
154     abort();
155 #endif
156 }
157 
158 /*
159  * fast means: we NEVER interrupt vCPU threads to retrieve
160  * information from KVM.
161  */
162 CpuInfoFastList *qmp_query_cpus_fast(Error **errp)
163 {
164     MachineState *ms = MACHINE(qdev_get_machine());
165     MachineClass *mc = MACHINE_GET_CLASS(ms);
166     CpuInfoFastList *head = NULL, **tail = &head;
167     SysEmuTarget target = qapi_enum_parse(&SysEmuTarget_lookup, TARGET_NAME,
168                                           -1, &error_abort);
169     CPUState *cpu;
170 
171     CPU_FOREACH(cpu) {
172         CpuInfoFast *value = g_malloc0(sizeof(*value));
173 
174         value->cpu_index = cpu->cpu_index;
175         value->qom_path = object_get_canonical_path(OBJECT(cpu));
176         value->thread_id = cpu->thread_id;
177 
178         value->has_props = !!mc->cpu_index_to_instance_props;
179         if (value->has_props) {
180             CpuInstanceProperties *props;
181             props = g_malloc0(sizeof(*props));
182             *props = mc->cpu_index_to_instance_props(ms, cpu->cpu_index);
183             value->props = props;
184         }
185 
186         value->arch = sysemu_target_to_cpuinfo_arch(target);
187         value->target = target;
188         if (target == SYS_EMU_TARGET_S390X) {
189             cpustate_to_cpuinfo_s390(&value->u.s390x, cpu);
190         }
191 
192         QAPI_LIST_APPEND(tail, value);
193     }
194 
195     return head;
196 }
197 
198 MachineInfoList *qmp_query_machines(Error **errp)
199 {
200     GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false);
201     MachineInfoList *mach_list = NULL;
202 
203     for (el = machines; el; el = el->next) {
204         MachineClass *mc = el->data;
205         MachineInfo *info;
206 
207         info = g_malloc0(sizeof(*info));
208         if (mc->is_default) {
209             info->has_is_default = true;
210             info->is_default = true;
211         }
212 
213         if (mc->alias) {
214             info->has_alias = true;
215             info->alias = g_strdup(mc->alias);
216         }
217 
218         info->name = g_strdup(mc->name);
219         info->cpu_max = !mc->max_cpus ? 1 : mc->max_cpus;
220         info->hotpluggable_cpus = mc->has_hotpluggable_cpus;
221         info->numa_mem_supported = mc->numa_mem_supported;
222         info->deprecated = !!mc->deprecation_reason;
223         if (mc->default_cpu_type) {
224             info->default_cpu_type = g_strdup(mc->default_cpu_type);
225             info->has_default_cpu_type = true;
226         }
227         if (mc->default_ram_id) {
228             info->default_ram_id = g_strdup(mc->default_ram_id);
229             info->has_default_ram_id = true;
230         }
231 
232         QAPI_LIST_PREPEND(mach_list, info);
233     }
234 
235     g_slist_free(machines);
236     return mach_list;
237 }
238 
239 CurrentMachineParams *qmp_query_current_machine(Error **errp)
240 {
241     CurrentMachineParams *params = g_malloc0(sizeof(*params));
242     params->wakeup_suspend_support = qemu_wakeup_suspend_enabled();
243 
244     return params;
245 }
246 
247 TargetInfo *qmp_query_target(Error **errp)
248 {
249     TargetInfo *info = g_malloc0(sizeof(*info));
250 
251     info->arch = qapi_enum_parse(&SysEmuTarget_lookup, TARGET_NAME, -1,
252                                  &error_abort);
253 
254     return info;
255 }
256 
257 HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp)
258 {
259     MachineState *ms = MACHINE(qdev_get_machine());
260     MachineClass *mc = MACHINE_GET_CLASS(ms);
261 
262     if (!mc->has_hotpluggable_cpus) {
263         error_setg(errp, QERR_FEATURE_DISABLED, "query-hotpluggable-cpus");
264         return NULL;
265     }
266 
267     return machine_query_hotpluggable_cpus(ms);
268 }
269 
270 void qmp_set_numa_node(NumaOptions *cmd, Error **errp)
271 {
272     if (phase_check(PHASE_MACHINE_INITIALIZED)) {
273         error_setg(errp, "The command is permitted only before the machine has been created");
274         return;
275     }
276 
277     set_numa_options(MACHINE(qdev_get_machine()), cmd, errp);
278 }
279 
280 static int query_memdev(Object *obj, void *opaque)
281 {
282     MemdevList **list = opaque;
283     Memdev *m;
284     QObject *host_nodes;
285     Visitor *v;
286 
287     if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) {
288         m = g_malloc0(sizeof(*m));
289 
290         m->id = g_strdup(object_get_canonical_path_component(obj));
291         m->has_id = !!m->id;
292 
293         m->size = object_property_get_uint(obj, "size", &error_abort);
294         m->merge = object_property_get_bool(obj, "merge", &error_abort);
295         m->dump = object_property_get_bool(obj, "dump", &error_abort);
296         m->prealloc = object_property_get_bool(obj, "prealloc", &error_abort);
297         m->policy = object_property_get_enum(obj, "policy", "HostMemPolicy",
298                                              &error_abort);
299         host_nodes = object_property_get_qobject(obj,
300                                                  "host-nodes",
301                                                  &error_abort);
302         v = qobject_input_visitor_new(host_nodes);
303         visit_type_uint16List(v, NULL, &m->host_nodes, &error_abort);
304         visit_free(v);
305         qobject_unref(host_nodes);
306 
307         QAPI_LIST_PREPEND(*list, m);
308     }
309 
310     return 0;
311 }
312 
313 MemdevList *qmp_query_memdev(Error **errp)
314 {
315     Object *obj = object_get_objects_root();
316     MemdevList *list = NULL;
317 
318     object_child_foreach(obj, query_memdev, &list);
319     return list;
320 }
321