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