| 
									
										
										
										
											2011-09-02 12:34:48 -05:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2019-06-13 17:33:58 +02:00
										 |  |  |  * QEMU Management Protocol commands | 
					
						
							| 
									
										
										
										
											2011-09-02 12:34:48 -05:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Copyright IBM, Corp. 2011 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Authors: | 
					
						
							|  |  |  |  *  Anthony Liguori   <aliguori@us.ibm.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This work is licensed under the terms of the GNU GPL, version 2.  See | 
					
						
							|  |  |  |  * the COPYING file in the top-level directory. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2012-01-13 17:44:23 +01:00
										 |  |  |  * Contributions after 2012-01-13 are licensed under the terms of the | 
					
						
							|  |  |  |  * GNU GPL, version 2 or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2011-09-02 12:34:48 -05:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-29 17:50:05 +00:00
										 |  |  | #include "qemu/osdep.h"
 | 
					
						
							| 
									
										
										
										
											2023-03-06 16:27:45 +04:00
										 |  |  | #include "qemu/sockets.h"
 | 
					
						
							| 
									
										
										
										
											2023-01-24 13:19:44 +01:00
										 |  |  | #include "monitor-internal.h"
 | 
					
						
							|  |  |  | #include "monitor/qdev.h"
 | 
					
						
							| 
									
										
										
										
											2023-01-09 20:03:14 +01:00
										 |  |  | #include "monitor/qmp-helpers.h"
 | 
					
						
							| 
									
										
										
										
											2012-12-17 18:20:04 +01:00
										 |  |  | #include "sysemu/sysemu.h"
 | 
					
						
							|  |  |  | #include "sysemu/kvm.h"
 | 
					
						
							| 
									
										
										
										
											2019-08-12 07:23:59 +02:00
										 |  |  | #include "sysemu/runstate.h"
 | 
					
						
							| 
									
										
										
										
											2020-12-11 11:52:43 -05:00
										 |  |  | #include "sysemu/runstate-action.h"
 | 
					
						
							| 
									
										
										
										
											2015-10-19 17:53:22 +02:00
										 |  |  | #include "sysemu/block-backend.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-01 12:18:31 +01:00
										 |  |  | #include "qapi/error.h"
 | 
					
						
							| 
									
										
										
										
											2023-01-24 13:19:44 +01:00
										 |  |  | #include "qapi/qapi-init-commands.h"
 | 
					
						
							| 
									
										
										
										
											2020-01-29 11:22:37 +01:00
										 |  |  | #include "qapi/qapi-commands-control.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-26 17:13:27 -06:00
										 |  |  | #include "qapi/qapi-commands-misc.h"
 | 
					
						
							| 
									
										
										
										
											2023-01-24 13:19:44 +01:00
										 |  |  | #include "qapi/qmp/qerror.h"
 | 
					
						
							| 
									
										
										
										
											2021-09-08 10:35:43 +01:00
										 |  |  | #include "qapi/type-helpers.h"
 | 
					
						
							| 
									
										
										
										
											2018-04-23 18:51:16 +02:00
										 |  |  | #include "hw/mem/memory-device.h"
 | 
					
						
							| 
									
										
										
										
											2021-09-08 10:35:43 +01:00
										 |  |  | #include "hw/intc/intc.h"
 | 
					
						
							| 
									
										
										
										
											2021-09-08 10:35:43 +01:00
										 |  |  | #include "hw/rdma/rdma.h"
 | 
					
						
							| 
									
										
										
										
											2011-09-02 12:34:48 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | NameInfo *qmp_query_name(Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     NameInfo *info = g_malloc0(sizeof(*info)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-04 17:06:59 +01:00
										 |  |  |     info->name = g_strdup(qemu_name); | 
					
						
							| 
									
										
										
										
											2011-09-02 12:34:48 -05:00
										 |  |  |     return info; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-08-26 17:38:13 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-02 13:26:31 +02:00
										 |  |  | void qmp_quit(Error **errp) | 
					
						
							| 
									
										
										
										
											2011-09-15 14:20:28 -03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-12-11 11:52:43 -05:00
										 |  |  |     shutdown_action = SHUTDOWN_ACTION_POWEROFF; | 
					
						
							| 
									
										
										
										
											2018-12-05 12:01:31 +01:00
										 |  |  |     qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT); | 
					
						
							| 
									
										
										
										
											2011-09-15 14:20:28 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-15 14:34:39 -03:00
										 |  |  | void qmp_stop(Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-02-18 13:16:49 +08:00
										 |  |  |     /* if there is a dump in background, we should wait until the dump
 | 
					
						
							|  |  |  |      * finished */ | 
					
						
							| 
									
										
										
										
											2022-03-23 19:57:31 +04:00
										 |  |  |     if (qemu_system_dump_in_progress()) { | 
					
						
							| 
									
										
										
										
											2016-02-18 13:16:49 +08:00
										 |  |  |         error_setg(errp, "There is a dump in process, please wait."); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 14:54:21 +02:00
										 |  |  |     if (runstate_check(RUN_STATE_INMIGRATE)) { | 
					
						
							|  |  |  |         autostart = 0; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         vm_stop(RUN_STATE_PAUSED); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-09-15 14:34:39 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 17:58:31 -02:00
										 |  |  | void qmp_cont(Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-10-19 17:53:22 +02:00
										 |  |  |     BlockBackend *blk; | 
					
						
							| 
									
										
										
										
											2019-06-06 18:41:30 +03:00
										 |  |  |     BlockJob *job; | 
					
						
							| 
									
										
										
										
											2017-06-23 17:24:15 +01:00
										 |  |  |     Error *local_err = NULL; | 
					
						
							| 
									
										
										
										
											2011-11-22 17:58:31 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-18 13:16:49 +08:00
										 |  |  |     /* if there is a dump in background, we should wait until the dump
 | 
					
						
							|  |  |  |      * finished */ | 
					
						
							| 
									
										
										
										
											2022-03-23 19:57:31 +04:00
										 |  |  |     if (qemu_system_dump_in_progress()) { | 
					
						
							| 
									
										
										
										
											2016-02-18 13:16:49 +08:00
										 |  |  |         error_setg(errp, "There is a dump in process, please wait."); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-26 11:24:40 +08:00
										 |  |  |     if (runstate_needs_reset()) { | 
					
						
							| 
									
										
										
										
											2014-03-21 19:42:26 -04:00
										 |  |  |         error_setg(errp, "Resetting the Virtual Machine is required"); | 
					
						
							| 
									
										
										
										
											2011-11-22 17:58:31 -02:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2012-04-27 13:33:36 -03:00
										 |  |  |     } else if (runstate_check(RUN_STATE_SUSPENDED)) { | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2019-01-24 15:25:24 +03:00
										 |  |  |     } else if (runstate_check(RUN_STATE_FINISH_MIGRATE)) { | 
					
						
							|  |  |  |         error_setg(errp, "Migration is not finalized yet"); | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2011-11-22 17:58:31 -02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-19 17:53:22 +02:00
										 |  |  |     for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { | 
					
						
							|  |  |  |         blk_iostatus_reset(blk); | 
					
						
							| 
									
										
										
										
											2014-05-02 13:26:42 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-03-22 18:58:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-26 05:32:04 -04:00
										 |  |  |     WITH_JOB_LOCK_GUARD() { | 
					
						
							|  |  |  |         for (job = block_job_next_locked(NULL); job; | 
					
						
							|  |  |  |              job = block_job_next_locked(job)) { | 
					
						
							|  |  |  |             block_job_iostatus_reset_locked(job); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-06-06 18:41:30 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-22 14:07:08 +01:00
										 |  |  |     /* Continuing after completed migration. Images have been inactivated to
 | 
					
						
							| 
									
										
										
										
											2017-05-04 18:52:36 +02:00
										 |  |  |      * allow the destination to take control. Need to get control back now. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * If there are no inactive block nodes (e.g. because the VM was just | 
					
						
							|  |  |  |      * paused rather than completing a migration), bdrv_inactivate_all() simply | 
					
						
							|  |  |  |      * doesn't do anything. */ | 
					
						
							| 
									
										
										
										
											2022-02-09 05:54:51 -05:00
										 |  |  |     bdrv_activate_all(&local_err); | 
					
						
							| 
									
										
										
										
											2017-05-04 18:52:36 +02:00
										 |  |  |     if (local_err) { | 
					
						
							|  |  |  |         error_propagate(errp, local_err); | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2015-12-22 14:07:08 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 14:54:21 +02:00
										 |  |  |     if (runstate_check(RUN_STATE_INMIGRATE)) { | 
					
						
							|  |  |  |         autostart = 1; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         vm_start(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-11-22 17:58:31 -02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2011-12-12 14:29:34 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-13 16:52:20 -03:00
										 |  |  | void qmp_add_client(const char *protocol, const char *fdname, | 
					
						
							|  |  |  |                     bool has_skipauth, bool skipauth, bool has_tls, bool tls, | 
					
						
							|  |  |  |                     Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-01-09 20:03:17 +01:00
										 |  |  |     static const struct { | 
					
						
							| 
									
										
										
										
											2023-01-09 20:03:14 +01:00
										 |  |  |         const char *name; | 
					
						
							|  |  |  |         bool (*add_client)(int fd, bool has_skipauth, bool skipauth, | 
					
						
							|  |  |  |                            bool has_tls, bool tls, Error **errp); | 
					
						
							|  |  |  |     } protocol_table[] = { | 
					
						
							|  |  |  |         { "spice", qmp_add_client_spice }, | 
					
						
							|  |  |  | #ifdef CONFIG_VNC
 | 
					
						
							|  |  |  |         { "vnc", qmp_add_client_vnc }, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifdef CONFIG_DBUS_DISPLAY
 | 
					
						
							|  |  |  |         { "@dbus-display", qmp_add_client_dbus_display }, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     int fd, i; | 
					
						
							| 
									
										
										
										
											2012-09-13 16:52:20 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-05 17:58:44 +02:00
										 |  |  |     fd = monitor_get_fd(monitor_cur(), fdname, errp); | 
					
						
							| 
									
										
										
										
											2012-09-13 16:52:20 -03:00
										 |  |  |     if (fd < 0) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-06 16:27:45 +04:00
										 |  |  |     if (!fd_is_socket(fd)) { | 
					
						
							|  |  |  |         error_setg(errp, "parameter @fdname must name a socket"); | 
					
						
							|  |  |  |         close(fd); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 20:03:14 +01:00
										 |  |  |     for (i = 0; i < ARRAY_SIZE(protocol_table); i++) { | 
					
						
							|  |  |  |         if (!strcmp(protocol, protocol_table[i].name)) { | 
					
						
							|  |  |  |             if (!protocol_table[i].add_client(fd, has_skipauth, skipauth, | 
					
						
							|  |  |  |                                               has_tls, tls, errp)) { | 
					
						
							|  |  |  |                 close(fd); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2012-09-13 16:52:20 -03:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-09 20:03:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-24 13:19:18 +01:00
										 |  |  |     if (!qmp_add_client_char(fd, has_skipauth, skipauth, has_tls, tls, | 
					
						
							|  |  |  |                              protocol, errp)) { | 
					
						
							| 
									
										
										
										
											2023-01-09 20:03:14 +01:00
										 |  |  |         close(fd); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-09-13 16:52:20 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2023-01-24 13:19:44 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index, | 
					
						
							|  |  |  |                                 int64_t cpu_index, Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     char *output = NULL; | 
					
						
							|  |  |  |     MonitorHMP hmp = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     monitor_data_init(&hmp.common, false, true, false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (has_cpu_index) { | 
					
						
							|  |  |  |         int ret = monitor_set_cpu(&hmp.common, cpu_index); | 
					
						
							|  |  |  |         if (ret < 0) { | 
					
						
							|  |  |  |             error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index", | 
					
						
							|  |  |  |                        "a CPU number"); | 
					
						
							|  |  |  |             goto out; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     handle_hmp_command(&hmp, command_line); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     WITH_QEMU_LOCK_GUARD(&hmp.common.mon_lock) { | 
					
						
							|  |  |  |         output = g_strdup(hmp.common.outbuf->str); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  |     monitor_data_destroy(&hmp.common); | 
					
						
							|  |  |  |     return output; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void __attribute__((__constructor__)) monitor_init_qmp_commands(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Two command lists: | 
					
						
							|  |  |  |      * - qmp_commands contains all QMP commands | 
					
						
							|  |  |  |      * - qmp_cap_negotiation_commands contains just | 
					
						
							|  |  |  |      *   "qmp_capabilities", to enforce capability negotiation | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     qmp_init_marshal(&qmp_commands); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     qmp_register_command(&qmp_commands, "device_add", | 
					
						
							|  |  |  |                          qmp_device_add, 0, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTAILQ_INIT(&qmp_cap_negotiation_commands); | 
					
						
							|  |  |  |     qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities", | 
					
						
							|  |  |  |                          qmp_marshal_qmp_capabilities, | 
					
						
							|  |  |  |                          QCO_ALLOW_PRECONFIG, 0); | 
					
						
							|  |  |  | } |