#include "qemu/osdep.h"
#include <dirent.h>
+#include "hw/qdev-core.h"
#include "monitor-internal.h"
-#include "qapi/error.h"
+#include "monitor/hmp.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qnum.h"
#include "qemu/config-file.h"
#include "qemu/option.h"
#include "qemu/units.h"
#include "sysemu/block-backend.h"
-#include "sysemu/runstate.h"
#include "trace.h"
static void monitor_command_cb(void *opaque, const char *cmdline,
return strchr(cmd->flags, 'p');
}
+static bool cmd_available(const HMPCommand *cmd)
+{
+ return phase_check(PHASE_MACHINE_READY) || cmd_can_preconfig(cmd);
+}
+
static void help_cmd_dump_one(Monitor *mon,
const HMPCommand *cmd,
char **prefix_args,
{
int i;
- if (runstate_check(RUN_STATE_PRECONFIG) && !cmd_can_preconfig(cmd)) {
+ if (!cmd_available(cmd)) {
return;
}
/* Find one entry to dump */
for (cmd = cmds; cmd->name != NULL; cmd++) {
if (hmp_compare_cmd(args[arg_index], cmd->name) &&
- ((!runstate_check(RUN_STATE_PRECONFIG) ||
- cmd_can_preconfig(cmd)))) {
+ cmd_available(cmd)) {
if (cmd->sub_table) {
/* continue with next arg */
help_cmd_dump(mon, cmd->sub_table,
}
}
-void help_cmd(Monitor *mon, const char *name)
+void hmp_help_cmd(Monitor *mon, const char *name)
{
char *args[MAX_ARGS];
int nb_args = 0;
if (!strcmp(name, "log")) {
const QEMULogItem *item;
monitor_printf(mon, "Log items (comma separated):\n");
- monitor_printf(mon, "%-10s %s\n", "none", "remove all logs");
+ monitor_printf(mon, "%-15s %s\n", "none", "remove all logs");
for (item = qemu_log_items; item->mask != 0; item++) {
- monitor_printf(mon, "%-10s %s\n", item->name, item->help);
+ monitor_printf(mon, "%-15s %s\n", item->name, item->help);
}
+#ifdef CONFIG_TRACE_LOG
+ monitor_printf(mon, "trace:PATTERN enable trace events\n");
+ monitor_printf(mon, "\nUse \"log trace:help\" to get a list of "
+ "trace events.\n\n");
+#endif
return;
}
static const char *pch;
static sigjmp_buf expr_env;
-static void GCC_FMT_ATTR(2, 3) QEMU_NORETURN
-expr_error(Monitor *mon, const char *fmt, ...)
+static G_NORETURN G_GNUC_PRINTF(2, 3)
+void expr_error(Monitor *mon, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
pch++;
}
*q = 0;
- ret = get_monitor_def(®, buf);
+ ret = get_monitor_def(mon, ®, buf);
if (ret < 0) {
expr_error(mon, "unknown register");
}
(int)(p - cmdp_start), cmdp_start);
return NULL;
}
- if (runstate_check(RUN_STATE_PRECONFIG) && !cmd_can_preconfig(cmd)) {
- monitor_printf(mon, "Command '%.*s' not available with -preconfig "
- "until after exit_preconfig.\n",
+ if (!cmd_available(cmd)) {
+ monitor_printf(mon, "Command '%.*s' not available "
+ "until machine initialization has completed.\n",
(int)(p - cmdp_start), cmdp_start);
return NULL;
}
{
const char *tmp = p;
int skip_key = 0;
+ int ret;
/* option */
c = *typestr++;
}
if (skip_key) {
p = tmp;
+ } else if (*typestr == 's') {
+ /* has option with string value */
+ typestr++;
+ tmp = p++;
+ while (qemu_isspace(*p)) {
+ p++;
+ }
+ ret = get_str(buf, sizeof(buf), &p);
+ if (ret < 0) {
+ monitor_printf(mon, "%s: value expected for -%c\n",
+ cmd->name, *tmp);
+ goto fail;
+ }
+ qdict_put_str(qdict, key, buf);
} else {
- /* has option */
+ /* has boolean option */
p++;
qdict_put_bool(qdict, key, true);
}
+ } else if (*typestr == 's') {
+ typestr++;
}
}
break;
return NULL;
}
+static void hmp_info_human_readable_text(Monitor *mon,
+ HumanReadableText *(*handler)(Error **))
+{
+ Error *err = NULL;
+ g_autoptr(HumanReadableText) info = handler(&err);
+
+ if (hmp_handle_error(mon, err)) {
+ return;
+ }
+
+ monitor_puts(mon, info->human_readable_text);
+}
+
+static void handle_hmp_command_exec(Monitor *mon,
+ const HMPCommand *cmd,
+ QDict *qdict)
+{
+ if (cmd->cmd_info_hrt) {
+ hmp_info_human_readable_text(mon,
+ cmd->cmd_info_hrt);
+ } else {
+ cmd->cmd(mon, qdict);
+ }
+}
+
typedef struct HandleHmpCommandCo {
Monitor *mon;
const HMPCommand *cmd;
static void handle_hmp_command_co(void *opaque)
{
HandleHmpCommandCo *data = opaque;
- data->cmd->cmd(data->mon, data->qdict);
+ handle_hmp_command_exec(data->mon, data->cmd, data->qdict);
monitor_set_cur(qemu_coroutine_self(), NULL);
data->done = true;
}
return;
}
+ if (!cmd->cmd && !cmd->cmd_info_hrt) {
+ /* FIXME: is it useful to try autoload modules here ??? */
+ monitor_printf(&mon->common, "Command \"%.*s\" is not available.\n",
+ (int)(cmdline - cmd_start), cmd_start);
+ return;
+ }
+
qdict = monitor_parse_arguments(&mon->common, &cmdline, cmd);
if (!qdict) {
while (cmdline > cmd_start && qemu_isspace(cmdline[-1])) {
if (!cmd->coroutine) {
/* old_mon is non-NULL when called from qmp_human_monitor_command() */
Monitor *old_mon = monitor_set_cur(qemu_coroutine_self(), &mon->common);
- cmd->cmd(&mon->common, qdict);
+ handle_hmp_command_exec(&mon->common, cmd, qdict);
monitor_set_cur(qemu_coroutine_self(), old_mon);
} else {
HandleHmpCommandCo data = {
Coroutine *co = qemu_coroutine_create(handle_hmp_command_co, &data);
monitor_set_cur(co, &mon->common);
aio_co_enter(qemu_get_aio_context(), co);
- AIO_WAIT_WHILE(qemu_get_aio_context(), !data.done);
+ AIO_WAIT_WHILE_UNLOCKED(NULL, !data.done);
}
qobject_unref(qdict);
}
memcpy(cmd, pstart, len);
cmd[len] = '\0';
- if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) {
- readline_add_completion(mon->rs, cmd);
- }
+ readline_add_completion_of(mon->rs, name, cmd);
if (*p == '\0') {
break;
}
{
const char *cmdname;
int i;
- const char *ptype, *old_ptype, *str, *name;
+ const char *ptype, *old_ptype, *str;
const HMPCommand *cmd;
BlockBackend *blk = NULL;
}
readline_set_completion_index(mon->rs, strlen(cmdname));
for (cmd = cmd_table; cmd->name != NULL; cmd++) {
- if (!runstate_check(RUN_STATE_PRECONFIG) ||
- cmd_can_preconfig(cmd)) {
+ if (cmd_available(cmd)) {
cmd_completion(mon, cmdname, cmd->name);
}
}
/* find the command */
for (cmd = cmd_table; cmd->name != NULL; cmd++) {
if (hmp_compare_cmd(args[0], cmd->name) &&
- (!runstate_check(RUN_STATE_PRECONFIG) ||
- cmd_can_preconfig(cmd))) {
+ cmd_available(cmd)) {
break;
}
}
/* block device name completion */
readline_set_completion_index(mon->rs, strlen(str));
while ((blk = blk_next(blk)) != NULL) {
- name = blk_name(blk);
- if (str[0] == '\0' ||
- !strncmp(name, str, strlen(str))) {
- readline_add_completion(mon->rs, name);
- }
+ readline_add_completion_of(mon->rs, str, blk_name(blk));
}
break;
case 's':
static void monitor_event(void *opaque, QEMUChrEvent event)
{
Monitor *mon = opaque;
- MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
switch (event) {
case CHR_EVENT_MUX_IN:
qemu_mutex_lock(&mon->mon_lock);
- mon->mux_out = 0;
- qemu_mutex_unlock(&mon->mon_lock);
- if (mon->reset_seen) {
- readline_restart(hmp_mon->rs);
+ if (mon->mux_out) {
+ mon->mux_out = 0;
monitor_resume(mon);
- monitor_flush(mon);
- } else {
- qatomic_mb_set(&mon->suspend_cnt, 0);
}
+ qemu_mutex_unlock(&mon->mon_lock);
break;
case CHR_EVENT_MUX_OUT:
- if (mon->reset_seen) {
- if (qatomic_mb_read(&mon->suspend_cnt) == 0) {
- monitor_printf(mon, "\n");
+ qemu_mutex_lock(&mon->mon_lock);
+ if (!mon->mux_out) {
+ if (mon->reset_seen && !mon->suspend_cnt) {
+ monitor_puts_locked(mon, "\n");
+ } else {
+ monitor_flush_locked(mon);
}
- monitor_flush(mon);
monitor_suspend(mon);
- } else {
- qatomic_inc(&mon->suspend_cnt);
+ mon->mux_out = 1;
}
- qemu_mutex_lock(&mon->mon_lock);
- mon->mux_out = 1;
qemu_mutex_unlock(&mon->mon_lock);
break;
case CHR_EVENT_OPENED:
monitor_printf(mon, "QEMU %s monitor - type 'help' for more "
"information\n", QEMU_VERSION);
+ qemu_mutex_lock(&mon->mon_lock);
+ mon->reset_seen = 1;
if (!mon->mux_out) {
- readline_restart(hmp_mon->rs);
- readline_show_prompt(hmp_mon->rs);
+ /* Suspend-resume forces the prompt to be printed. */
+ monitor_suspend(mon);
+ monitor_resume(mon);
}
- mon->reset_seen = 1;
+ qemu_mutex_unlock(&mon->mon_lock);
mon_refcount++;
break;
* These functions just adapt the readline interface in a typesafe way. We
* could cast function pointers but that discards compiler checks.
*/
-static void GCC_FMT_ATTR(2, 3) monitor_readline_printf(void *opaque,
+static void G_GNUC_PRINTF(2, 3) monitor_readline_printf(void *opaque,
const char *fmt, ...)
{
MonitorHMP *mon = opaque;