qmp.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. /*
  2. * QEMU Management Protocol
  3. *
  4. * Copyright IBM, Corp. 2011
  5. *
  6. * Authors:
  7. * Anthony Liguori <aliguori@us.ibm.com>
  8. *
  9. * This work is licensed under the terms of the GNU GPL, version 2. See
  10. * the COPYING file in the top-level directory.
  11. *
  12. * Contributions after 2012-01-13 are licensed under the terms of the
  13. * GNU GPL, version 2 or (at your option) any later version.
  14. */
  15. #include "qemu/osdep.h"
  16. #include "qemu-version.h"
  17. #include "qemu/cutils.h"
  18. #include "qemu/option.h"
  19. #include "monitor/monitor.h"
  20. #include "sysemu/sysemu.h"
  21. #include "qemu/config-file.h"
  22. #include "qemu/uuid.h"
  23. #include "chardev/char.h"
  24. #include "ui/qemu-spice.h"
  25. #include "ui/vnc.h"
  26. #include "sysemu/kvm.h"
  27. #include "sysemu/arch_init.h"
  28. #include "hw/qdev.h"
  29. #include "sysemu/blockdev.h"
  30. #include "sysemu/block-backend.h"
  31. #include "qom/qom-qobject.h"
  32. #include "qapi/error.h"
  33. #include "qapi/qapi-commands-block-core.h"
  34. #include "qapi/qapi-commands-misc.h"
  35. #include "qapi/qapi-commands-ui.h"
  36. #include "qapi/qmp/qdict.h"
  37. #include "qapi/qmp/qerror.h"
  38. #include "qapi/qobject-input-visitor.h"
  39. #include "hw/boards.h"
  40. #include "qom/object_interfaces.h"
  41. #include "hw/mem/pc-dimm.h"
  42. #include "hw/acpi/acpi_dev_interface.h"
  43. NameInfo *qmp_query_name(Error **errp)
  44. {
  45. NameInfo *info = g_malloc0(sizeof(*info));
  46. if (qemu_name) {
  47. info->has_name = true;
  48. info->name = g_strdup(qemu_name);
  49. }
  50. return info;
  51. }
  52. VersionInfo *qmp_query_version(Error **errp)
  53. {
  54. VersionInfo *info = g_new0(VersionInfo, 1);
  55. info->qemu = g_new0(VersionTriple, 1);
  56. info->qemu->major = QEMU_VERSION_MAJOR;
  57. info->qemu->minor = QEMU_VERSION_MINOR;
  58. info->qemu->micro = QEMU_VERSION_MICRO;
  59. info->package = g_strdup(QEMU_PKGVERSION);
  60. return info;
  61. }
  62. KvmInfo *qmp_query_kvm(Error **errp)
  63. {
  64. KvmInfo *info = g_malloc0(sizeof(*info));
  65. info->enabled = kvm_enabled();
  66. info->present = kvm_available();
  67. return info;
  68. }
  69. UuidInfo *qmp_query_uuid(Error **errp)
  70. {
  71. UuidInfo *info = g_malloc0(sizeof(*info));
  72. info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid);
  73. return info;
  74. }
  75. void qmp_quit(Error **errp)
  76. {
  77. no_shutdown = 0;
  78. qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP);
  79. }
  80. void qmp_stop(Error **errp)
  81. {
  82. /* if there is a dump in background, we should wait until the dump
  83. * finished */
  84. if (dump_in_progress()) {
  85. error_setg(errp, "There is a dump in process, please wait.");
  86. return;
  87. }
  88. if (runstate_check(RUN_STATE_INMIGRATE)) {
  89. autostart = 0;
  90. } else {
  91. vm_stop(RUN_STATE_PAUSED);
  92. }
  93. }
  94. void qmp_system_reset(Error **errp)
  95. {
  96. qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP);
  97. }
  98. void qmp_system_powerdown(Error **erp)
  99. {
  100. qemu_system_powerdown_request();
  101. }
  102. void qmp_cpu_add(int64_t id, Error **errp)
  103. {
  104. MachineClass *mc;
  105. mc = MACHINE_GET_CLASS(current_machine);
  106. if (mc->hot_add_cpu) {
  107. mc->hot_add_cpu(id, errp);
  108. } else {
  109. error_setg(errp, "Not supported");
  110. }
  111. }
  112. #ifndef CONFIG_VNC
  113. /* If VNC support is enabled, the "true" query-vnc command is
  114. defined in the VNC subsystem */
  115. VncInfo *qmp_query_vnc(Error **errp)
  116. {
  117. error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
  118. return NULL;
  119. };
  120. VncInfo2List *qmp_query_vnc_servers(Error **errp)
  121. {
  122. error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
  123. return NULL;
  124. };
  125. #endif
  126. #ifndef CONFIG_SPICE
  127. /*
  128. * qmp_unregister_commands_hack() ensures that QMP command query-spice
  129. * exists only #ifdef CONFIG_SPICE. Necessary for an accurate
  130. * query-commands result. However, the QAPI schema is blissfully
  131. * unaware of that, and the QAPI code generator happily generates a
  132. * dead qmp_marshal_query_spice() that calls qmp_query_spice().
  133. * Provide it one, or else linking fails. FIXME Educate the QAPI
  134. * schema on CONFIG_SPICE.
  135. */
  136. SpiceInfo *qmp_query_spice(Error **errp)
  137. {
  138. abort();
  139. };
  140. #endif
  141. void qmp_cont(Error **errp)
  142. {
  143. BlockBackend *blk;
  144. Error *local_err = NULL;
  145. /* if there is a dump in background, we should wait until the dump
  146. * finished */
  147. if (dump_in_progress()) {
  148. error_setg(errp, "There is a dump in process, please wait.");
  149. return;
  150. }
  151. if (runstate_needs_reset()) {
  152. error_setg(errp, "Resetting the Virtual Machine is required");
  153. return;
  154. } else if (runstate_check(RUN_STATE_SUSPENDED)) {
  155. return;
  156. }
  157. for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
  158. blk_iostatus_reset(blk);
  159. }
  160. /* Continuing after completed migration. Images have been inactivated to
  161. * allow the destination to take control. Need to get control back now.
  162. *
  163. * If there are no inactive block nodes (e.g. because the VM was just
  164. * paused rather than completing a migration), bdrv_inactivate_all() simply
  165. * doesn't do anything. */
  166. bdrv_invalidate_cache_all(&local_err);
  167. if (local_err) {
  168. error_propagate(errp, local_err);
  169. return;
  170. }
  171. if (runstate_check(RUN_STATE_INMIGRATE)) {
  172. autostart = 1;
  173. } else {
  174. vm_start();
  175. }
  176. }
  177. void qmp_system_wakeup(Error **errp)
  178. {
  179. qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
  180. }
  181. ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
  182. {
  183. Object *obj;
  184. bool ambiguous = false;
  185. ObjectPropertyInfoList *props = NULL;
  186. ObjectProperty *prop;
  187. ObjectPropertyIterator iter;
  188. obj = object_resolve_path(path, &ambiguous);
  189. if (obj == NULL) {
  190. if (ambiguous) {
  191. error_setg(errp, "Path '%s' is ambiguous", path);
  192. } else {
  193. error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
  194. "Device '%s' not found", path);
  195. }
  196. return NULL;
  197. }
  198. object_property_iter_init(&iter, obj);
  199. while ((prop = object_property_iter_next(&iter))) {
  200. ObjectPropertyInfoList *entry = g_malloc0(sizeof(*entry));
  201. entry->value = g_malloc0(sizeof(ObjectPropertyInfo));
  202. entry->next = props;
  203. props = entry;
  204. entry->value->name = g_strdup(prop->name);
  205. entry->value->type = g_strdup(prop->type);
  206. }
  207. return props;
  208. }
  209. void qmp_qom_set(const char *path, const char *property, QObject *value,
  210. Error **errp)
  211. {
  212. Object *obj;
  213. obj = object_resolve_path(path, NULL);
  214. if (!obj) {
  215. error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
  216. "Device '%s' not found", path);
  217. return;
  218. }
  219. object_property_set_qobject(obj, value, property, errp);
  220. }
  221. QObject *qmp_qom_get(const char *path, const char *property, Error **errp)
  222. {
  223. Object *obj;
  224. obj = object_resolve_path(path, NULL);
  225. if (!obj) {
  226. error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
  227. "Device '%s' not found", path);
  228. return NULL;
  229. }
  230. return object_property_get_qobject(obj, property, errp);
  231. }
  232. void qmp_set_password(const char *protocol, const char *password,
  233. bool has_connected, const char *connected, Error **errp)
  234. {
  235. int disconnect_if_connected = 0;
  236. int fail_if_connected = 0;
  237. int rc;
  238. if (has_connected) {
  239. if (strcmp(connected, "fail") == 0) {
  240. fail_if_connected = 1;
  241. } else if (strcmp(connected, "disconnect") == 0) {
  242. disconnect_if_connected = 1;
  243. } else if (strcmp(connected, "keep") == 0) {
  244. /* nothing */
  245. } else {
  246. error_setg(errp, QERR_INVALID_PARAMETER, "connected");
  247. return;
  248. }
  249. }
  250. if (strcmp(protocol, "spice") == 0) {
  251. if (!qemu_using_spice(errp)) {
  252. return;
  253. }
  254. rc = qemu_spice_set_passwd(password, fail_if_connected,
  255. disconnect_if_connected);
  256. if (rc != 0) {
  257. error_setg(errp, QERR_SET_PASSWD_FAILED);
  258. }
  259. return;
  260. }
  261. if (strcmp(protocol, "vnc") == 0) {
  262. if (fail_if_connected || disconnect_if_connected) {
  263. /* vnc supports "connected=keep" only */
  264. error_setg(errp, QERR_INVALID_PARAMETER, "connected");
  265. return;
  266. }
  267. /* Note that setting an empty password will not disable login through
  268. * this interface. */
  269. rc = vnc_display_password(NULL, password);
  270. if (rc < 0) {
  271. error_setg(errp, QERR_SET_PASSWD_FAILED);
  272. }
  273. return;
  274. }
  275. error_setg(errp, QERR_INVALID_PARAMETER, "protocol");
  276. }
  277. void qmp_expire_password(const char *protocol, const char *whenstr,
  278. Error **errp)
  279. {
  280. time_t when;
  281. int rc;
  282. if (strcmp(whenstr, "now") == 0) {
  283. when = 0;
  284. } else if (strcmp(whenstr, "never") == 0) {
  285. when = TIME_MAX;
  286. } else if (whenstr[0] == '+') {
  287. when = time(NULL) + strtoull(whenstr+1, NULL, 10);
  288. } else {
  289. when = strtoull(whenstr, NULL, 10);
  290. }
  291. if (strcmp(protocol, "spice") == 0) {
  292. if (!qemu_using_spice(errp)) {
  293. return;
  294. }
  295. rc = qemu_spice_set_pw_expire(when);
  296. if (rc != 0) {
  297. error_setg(errp, QERR_SET_PASSWD_FAILED);
  298. }
  299. return;
  300. }
  301. if (strcmp(protocol, "vnc") == 0) {
  302. rc = vnc_display_pw_expire(NULL, when);
  303. if (rc != 0) {
  304. error_setg(errp, QERR_SET_PASSWD_FAILED);
  305. }
  306. return;
  307. }
  308. error_setg(errp, QERR_INVALID_PARAMETER, "protocol");
  309. }
  310. #ifdef CONFIG_VNC
  311. void qmp_change_vnc_password(const char *password, Error **errp)
  312. {
  313. if (vnc_display_password(NULL, password) < 0) {
  314. error_setg(errp, QERR_SET_PASSWD_FAILED);
  315. }
  316. }
  317. static void qmp_change_vnc_listen(const char *target, Error **errp)
  318. {
  319. QemuOptsList *olist = qemu_find_opts("vnc");
  320. QemuOpts *opts;
  321. if (strstr(target, "id=")) {
  322. error_setg(errp, "id not supported");
  323. return;
  324. }
  325. opts = qemu_opts_find(olist, "default");
  326. if (opts) {
  327. qemu_opts_del(opts);
  328. }
  329. opts = vnc_parse(target, errp);
  330. if (!opts) {
  331. return;
  332. }
  333. vnc_display_open("default", errp);
  334. }
  335. static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
  336. Error **errp)
  337. {
  338. if (strcmp(target, "passwd") == 0 || strcmp(target, "password") == 0) {
  339. if (!has_arg) {
  340. error_setg(errp, QERR_MISSING_PARAMETER, "password");
  341. } else {
  342. qmp_change_vnc_password(arg, errp);
  343. }
  344. } else {
  345. qmp_change_vnc_listen(target, errp);
  346. }
  347. }
  348. #else
  349. void qmp_change_vnc_password(const char *password, Error **errp)
  350. {
  351. error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
  352. }
  353. static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
  354. Error **errp)
  355. {
  356. error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
  357. }
  358. #endif /* !CONFIG_VNC */
  359. void qmp_change(const char *device, const char *target,
  360. bool has_arg, const char *arg, Error **errp)
  361. {
  362. if (strcmp(device, "vnc") == 0) {
  363. qmp_change_vnc(target, has_arg, arg, errp);
  364. } else {
  365. qmp_blockdev_change_medium(true, device, false, NULL, target,
  366. has_arg, arg, false, 0, errp);
  367. }
  368. }
  369. static void qom_list_types_tramp(ObjectClass *klass, void *data)
  370. {
  371. ObjectTypeInfoList *e, **pret = data;
  372. ObjectTypeInfo *info;
  373. ObjectClass *parent = object_class_get_parent(klass);
  374. info = g_malloc0(sizeof(*info));
  375. info->name = g_strdup(object_class_get_name(klass));
  376. info->has_abstract = info->abstract = object_class_is_abstract(klass);
  377. if (parent) {
  378. info->has_parent = true;
  379. info->parent = g_strdup(object_class_get_name(parent));
  380. }
  381. e = g_malloc0(sizeof(*e));
  382. e->value = info;
  383. e->next = *pret;
  384. *pret = e;
  385. }
  386. ObjectTypeInfoList *qmp_qom_list_types(bool has_implements,
  387. const char *implements,
  388. bool has_abstract,
  389. bool abstract,
  390. Error **errp)
  391. {
  392. ObjectTypeInfoList *ret = NULL;
  393. object_class_foreach(qom_list_types_tramp, implements, abstract, &ret);
  394. return ret;
  395. }
  396. /* Return a DevicePropertyInfo for a qdev property.
  397. *
  398. * If a qdev property with the given name does not exist, use the given default
  399. * type. If the qdev property info should not be shown, return NULL.
  400. *
  401. * The caller must free the return value.
  402. */
  403. static ObjectPropertyInfo *make_device_property_info(ObjectClass *klass,
  404. const char *name,
  405. const char *default_type,
  406. const char *description)
  407. {
  408. ObjectPropertyInfo *info;
  409. Property *prop;
  410. do {
  411. for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) {
  412. if (strcmp(name, prop->name) != 0) {
  413. continue;
  414. }
  415. /*
  416. * TODO Properties without a parser are just for dirty hacks.
  417. * qdev_prop_ptr is the only such PropertyInfo. It's marked
  418. * for removal. This conditional should be removed along with
  419. * it.
  420. */
  421. if (!prop->info->set && !prop->info->create) {
  422. return NULL; /* no way to set it, don't show */
  423. }
  424. info = g_malloc0(sizeof(*info));
  425. info->name = g_strdup(prop->name);
  426. info->type = default_type ? g_strdup(default_type)
  427. : g_strdup(prop->info->name);
  428. info->has_description = !!prop->info->description;
  429. info->description = g_strdup(prop->info->description);
  430. return info;
  431. }
  432. klass = object_class_get_parent(klass);
  433. } while (klass != object_class_by_name(TYPE_DEVICE));
  434. /* Not a qdev property, use the default type */
  435. info = g_malloc0(sizeof(*info));
  436. info->name = g_strdup(name);
  437. info->type = g_strdup(default_type);
  438. info->has_description = !!description;
  439. info->description = g_strdup(description);
  440. return info;
  441. }
  442. ObjectPropertyInfoList *qmp_device_list_properties(const char *typename,
  443. Error **errp)
  444. {
  445. ObjectClass *klass;
  446. Object *obj;
  447. ObjectProperty *prop;
  448. ObjectPropertyIterator iter;
  449. ObjectPropertyInfoList *prop_list = NULL;
  450. klass = object_class_by_name(typename);
  451. if (klass == NULL) {
  452. error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
  453. "Device '%s' not found", typename);
  454. return NULL;
  455. }
  456. klass = object_class_dynamic_cast(klass, TYPE_DEVICE);
  457. if (klass == NULL) {
  458. error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", TYPE_DEVICE);
  459. return NULL;
  460. }
  461. if (object_class_is_abstract(klass)) {
  462. error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename",
  463. "non-abstract device type");
  464. return NULL;
  465. }
  466. obj = object_new(typename);
  467. object_property_iter_init(&iter, obj);
  468. while ((prop = object_property_iter_next(&iter))) {
  469. ObjectPropertyInfo *info;
  470. ObjectPropertyInfoList *entry;
  471. /* Skip Object and DeviceState properties */
  472. if (strcmp(prop->name, "type") == 0 ||
  473. strcmp(prop->name, "realized") == 0 ||
  474. strcmp(prop->name, "hotpluggable") == 0 ||
  475. strcmp(prop->name, "hotplugged") == 0 ||
  476. strcmp(prop->name, "parent_bus") == 0) {
  477. continue;
  478. }
  479. /* Skip legacy properties since they are just string versions of
  480. * properties that we already list.
  481. */
  482. if (strstart(prop->name, "legacy-", NULL)) {
  483. continue;
  484. }
  485. info = make_device_property_info(klass, prop->name, prop->type,
  486. prop->description);
  487. if (!info) {
  488. continue;
  489. }
  490. entry = g_malloc0(sizeof(*entry));
  491. entry->value = info;
  492. entry->next = prop_list;
  493. prop_list = entry;
  494. }
  495. object_unref(obj);
  496. return prop_list;
  497. }
  498. ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename,
  499. Error **errp)
  500. {
  501. ObjectClass *klass;
  502. Object *obj = NULL;
  503. ObjectProperty *prop;
  504. ObjectPropertyIterator iter;
  505. ObjectPropertyInfoList *prop_list = NULL;
  506. klass = object_class_by_name(typename);
  507. if (klass == NULL) {
  508. error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
  509. "Class '%s' not found", typename);
  510. return NULL;
  511. }
  512. klass = object_class_dynamic_cast(klass, TYPE_OBJECT);
  513. if (klass == NULL) {
  514. error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", TYPE_OBJECT);
  515. return NULL;
  516. }
  517. if (object_class_is_abstract(klass)) {
  518. object_class_property_iter_init(&iter, klass);
  519. } else {
  520. obj = object_new(typename);
  521. object_property_iter_init(&iter, obj);
  522. }
  523. while ((prop = object_property_iter_next(&iter))) {
  524. ObjectPropertyInfo *info;
  525. ObjectPropertyInfoList *entry;
  526. info = g_malloc0(sizeof(*info));
  527. info->name = g_strdup(prop->name);
  528. info->type = g_strdup(prop->type);
  529. info->has_description = !!prop->description;
  530. info->description = g_strdup(prop->description);
  531. entry = g_malloc0(sizeof(*entry));
  532. entry->value = info;
  533. entry->next = prop_list;
  534. prop_list = entry;
  535. }
  536. object_unref(obj);
  537. return prop_list;
  538. }
  539. CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
  540. {
  541. return arch_query_cpu_definitions(errp);
  542. }
  543. CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
  544. CpuModelInfo *model,
  545. Error **errp)
  546. {
  547. return arch_query_cpu_model_expansion(type, model, errp);
  548. }
  549. CpuModelCompareInfo *qmp_query_cpu_model_comparison(CpuModelInfo *modela,
  550. CpuModelInfo *modelb,
  551. Error **errp)
  552. {
  553. return arch_query_cpu_model_comparison(modela, modelb, errp);
  554. }
  555. CpuModelBaselineInfo *qmp_query_cpu_model_baseline(CpuModelInfo *modela,
  556. CpuModelInfo *modelb,
  557. Error **errp)
  558. {
  559. return arch_query_cpu_model_baseline(modela, modelb, errp);
  560. }
  561. void qmp_add_client(const char *protocol, const char *fdname,
  562. bool has_skipauth, bool skipauth, bool has_tls, bool tls,
  563. Error **errp)
  564. {
  565. Chardev *s;
  566. int fd;
  567. fd = monitor_get_fd(cur_mon, fdname, errp);
  568. if (fd < 0) {
  569. return;
  570. }
  571. if (strcmp(protocol, "spice") == 0) {
  572. if (!qemu_using_spice(errp)) {
  573. close(fd);
  574. return;
  575. }
  576. skipauth = has_skipauth ? skipauth : false;
  577. tls = has_tls ? tls : false;
  578. if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) {
  579. error_setg(errp, "spice failed to add client");
  580. close(fd);
  581. }
  582. return;
  583. #ifdef CONFIG_VNC
  584. } else if (strcmp(protocol, "vnc") == 0) {
  585. skipauth = has_skipauth ? skipauth : false;
  586. vnc_display_add_client(NULL, fd, skipauth);
  587. return;
  588. #endif
  589. } else if ((s = qemu_chr_find(protocol)) != NULL) {
  590. if (qemu_chr_add_client(s, fd) < 0) {
  591. error_setg(errp, "failed to add client");
  592. close(fd);
  593. return;
  594. }
  595. return;
  596. }
  597. error_setg(errp, "protocol '%s' is invalid", protocol);
  598. close(fd);
  599. }
  600. void qmp_object_add(const char *type, const char *id,
  601. bool has_props, QObject *props, Error **errp)
  602. {
  603. QDict *pdict;
  604. Visitor *v;
  605. Object *obj;
  606. if (props) {
  607. pdict = qobject_to(QDict, props);
  608. if (!pdict) {
  609. error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
  610. return;
  611. }
  612. QINCREF(pdict);
  613. } else {
  614. pdict = qdict_new();
  615. }
  616. v = qobject_input_visitor_new(QOBJECT(pdict));
  617. obj = user_creatable_add_type(type, id, pdict, v, errp);
  618. visit_free(v);
  619. if (obj) {
  620. object_unref(obj);
  621. }
  622. QDECREF(pdict);
  623. }
  624. void qmp_object_del(const char *id, Error **errp)
  625. {
  626. user_creatable_del(id, errp);
  627. }
  628. MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
  629. {
  630. return qmp_pc_dimm_device_list();
  631. }
  632. ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp)
  633. {
  634. bool ambig;
  635. ACPIOSTInfoList *head = NULL;
  636. ACPIOSTInfoList **prev = &head;
  637. Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, &ambig);
  638. if (obj) {
  639. AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj);
  640. AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj);
  641. adevc->ospm_status(adev, &prev);
  642. } else {
  643. error_setg(errp, "command is not supported, missing ACPI device");
  644. }
  645. return head;
  646. }
  647. MemoryInfo *qmp_query_memory_size_summary(Error **errp)
  648. {
  649. MemoryInfo *mem_info = g_malloc0(sizeof(MemoryInfo));
  650. mem_info->base_memory = ram_size;
  651. mem_info->plugged_memory = get_plugged_memory_size();
  652. mem_info->has_plugged_memory =
  653. mem_info->plugged_memory != (uint64_t)-1;
  654. return mem_info;
  655. }
  656. static QemuSemaphore x_oob_test_sem;
  657. static void __attribute__((constructor)) x_oob_test_init(void)
  658. {
  659. qemu_sem_init(&x_oob_test_sem, 0);
  660. }
  661. void qmp_x_oob_test(bool lock, Error **errp)
  662. {
  663. if (lock) {
  664. qemu_sem_wait(&x_oob_test_sem);
  665. } else {
  666. qemu_sem_post(&x_oob_test_sem);
  667. }
  668. }