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 static CpuInfoArch sysemu_target_to_cpuinfo_arch(SysEmuTarget target) 28 { 29 /* 30 * The @SysEmuTarget -> @CpuInfoArch mapping below is based on the 31 * TARGET_ARCH -> TARGET_BASE_ARCH mapping in the "configure" script. 32 */ 33 switch (target) { 34 case SYS_EMU_TARGET_I386: 35 case SYS_EMU_TARGET_X86_64: 36 return CPU_INFO_ARCH_X86; 37 38 case SYS_EMU_TARGET_PPC: 39 case SYS_EMU_TARGET_PPC64: 40 return CPU_INFO_ARCH_PPC; 41 42 case SYS_EMU_TARGET_SPARC: 43 case SYS_EMU_TARGET_SPARC64: 44 return CPU_INFO_ARCH_SPARC; 45 46 case SYS_EMU_TARGET_MIPS: 47 case SYS_EMU_TARGET_MIPSEL: 48 case SYS_EMU_TARGET_MIPS64: 49 case SYS_EMU_TARGET_MIPS64EL: 50 return CPU_INFO_ARCH_MIPS; 51 52 case SYS_EMU_TARGET_TRICORE: 53 return CPU_INFO_ARCH_TRICORE; 54 55 case SYS_EMU_TARGET_S390X: 56 return CPU_INFO_ARCH_S390; 57 58 case SYS_EMU_TARGET_RISCV32: 59 case SYS_EMU_TARGET_RISCV64: 60 return CPU_INFO_ARCH_RISCV; 61 62 default: 63 return CPU_INFO_ARCH_OTHER; 64 } 65 } 66 67 static void cpustate_to_cpuinfo_s390(CpuInfoS390 *info, const CPUState *cpu) 68 { 69 #ifdef TARGET_S390X 70 S390CPU *s390_cpu = S390_CPU(cpu); 71 CPUS390XState *env = &s390_cpu->env; 72 73 info->cpu_state = env->cpu_state; 74 #else 75 abort(); 76 #endif 77 } 78 79 /* 80 * fast means: we NEVER interrupt vCPU threads to retrieve 81 * information from KVM. 82 */ 83 CpuInfoFastList *qmp_query_cpus_fast(Error **errp) 84 { 85 MachineState *ms = MACHINE(qdev_get_machine()); 86 MachineClass *mc = MACHINE_GET_CLASS(ms); 87 CpuInfoFastList *head = NULL, **tail = &head; 88 SysEmuTarget target = qapi_enum_parse(&SysEmuTarget_lookup, TARGET_NAME, 89 -1, &error_abort); 90 CPUState *cpu; 91 92 CPU_FOREACH(cpu) { 93 CpuInfoFast *value = g_malloc0(sizeof(*value)); 94 95 value->cpu_index = cpu->cpu_index; 96 value->qom_path = object_get_canonical_path(OBJECT(cpu)); 97 value->thread_id = cpu->thread_id; 98 99 value->has_props = !!mc->cpu_index_to_instance_props; 100 if (value->has_props) { 101 CpuInstanceProperties *props; 102 props = g_malloc0(sizeof(*props)); 103 *props = mc->cpu_index_to_instance_props(ms, cpu->cpu_index); 104 value->props = props; 105 } 106 107 value->arch = sysemu_target_to_cpuinfo_arch(target); 108 value->target = target; 109 if (target == SYS_EMU_TARGET_S390X) { 110 cpustate_to_cpuinfo_s390(&value->u.s390x, cpu); 111 } 112 113 QAPI_LIST_APPEND(tail, value); 114 } 115 116 return head; 117 } 118 119 MachineInfoList *qmp_query_machines(Error **errp) 120 { 121 GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false); 122 MachineInfoList *mach_list = NULL; 123 124 for (el = machines; el; el = el->next) { 125 MachineClass *mc = el->data; 126 MachineInfo *info; 127 128 info = g_malloc0(sizeof(*info)); 129 if (mc->is_default) { 130 info->has_is_default = true; 131 info->is_default = true; 132 } 133 134 if (mc->alias) { 135 info->has_alias = true; 136 info->alias = g_strdup(mc->alias); 137 } 138 139 info->name = g_strdup(mc->name); 140 info->cpu_max = !mc->max_cpus ? 1 : mc->max_cpus; 141 info->hotpluggable_cpus = mc->has_hotpluggable_cpus; 142 info->numa_mem_supported = mc->numa_mem_supported; 143 info->deprecated = !!mc->deprecation_reason; 144 if (mc->default_cpu_type) { 145 info->default_cpu_type = g_strdup(mc->default_cpu_type); 146 info->has_default_cpu_type = true; 147 } 148 if (mc->default_ram_id) { 149 info->default_ram_id = g_strdup(mc->default_ram_id); 150 info->has_default_ram_id = true; 151 } 152 153 QAPI_LIST_PREPEND(mach_list, info); 154 } 155 156 g_slist_free(machines); 157 return mach_list; 158 } 159 160 CurrentMachineParams *qmp_query_current_machine(Error **errp) 161 { 162 CurrentMachineParams *params = g_malloc0(sizeof(*params)); 163 params->wakeup_suspend_support = qemu_wakeup_suspend_enabled(); 164 165 return params; 166 } 167 168 TargetInfo *qmp_query_target(Error **errp) 169 { 170 TargetInfo *info = g_malloc0(sizeof(*info)); 171 172 info->arch = qapi_enum_parse(&SysEmuTarget_lookup, TARGET_NAME, -1, 173 &error_abort); 174 175 return info; 176 } 177 178 HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp) 179 { 180 MachineState *ms = MACHINE(qdev_get_machine()); 181 MachineClass *mc = MACHINE_GET_CLASS(ms); 182 183 if (!mc->has_hotpluggable_cpus) { 184 error_setg(errp, QERR_FEATURE_DISABLED, "query-hotpluggable-cpus"); 185 return NULL; 186 } 187 188 return machine_query_hotpluggable_cpus(ms); 189 } 190 191 void qmp_set_numa_node(NumaOptions *cmd, Error **errp) 192 { 193 if (phase_check(PHASE_MACHINE_INITIALIZED)) { 194 error_setg(errp, "The command is permitted only before the machine has been created"); 195 return; 196 } 197 198 set_numa_options(MACHINE(qdev_get_machine()), cmd, errp); 199 } 200 201 static int query_memdev(Object *obj, void *opaque) 202 { 203 MemdevList **list = opaque; 204 Memdev *m; 205 QObject *host_nodes; 206 Visitor *v; 207 208 if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) { 209 m = g_malloc0(sizeof(*m)); 210 211 m->id = g_strdup(object_get_canonical_path_component(obj)); 212 m->has_id = !!m->id; 213 214 m->size = object_property_get_uint(obj, "size", &error_abort); 215 m->merge = object_property_get_bool(obj, "merge", &error_abort); 216 m->dump = object_property_get_bool(obj, "dump", &error_abort); 217 m->prealloc = object_property_get_bool(obj, "prealloc", &error_abort); 218 m->policy = object_property_get_enum(obj, "policy", "HostMemPolicy", 219 &error_abort); 220 host_nodes = object_property_get_qobject(obj, 221 "host-nodes", 222 &error_abort); 223 v = qobject_input_visitor_new(host_nodes); 224 visit_type_uint16List(v, NULL, &m->host_nodes, &error_abort); 225 visit_free(v); 226 qobject_unref(host_nodes); 227 228 QAPI_LIST_PREPEND(*list, m); 229 } 230 231 return 0; 232 } 233 234 MemdevList *qmp_query_memdev(Error **errp) 235 { 236 Object *obj = object_get_objects_root(); 237 MemdevList *list = NULL; 238 239 object_child_foreach(obj, query_memdev, &list); 240 return list; 241 } 242