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