#include "hw/hw.h"
#include "monitor/qdev.h"
#include "hw/usb.h"
-#include "hw/pcmcia.h"
#include "hw/i386/pc.h"
#include "hw/pci/pci.h"
#include "sysemu/watchdog.h"
#include "qmp-commands.h"
#include "hmp.h"
#include "qemu/thread.h"
+#include "block/qapi.h"
+#include "qapi/qmp-event.h"
+#include "qapi-event.h"
/* for pic/irq_info */
#if defined(TARGET_SPARC)
* throttling is calculated globally, rather than per-Monitor
* instance.
*/
-typedef struct MonitorEventState {
- MonitorEvent event; /* Event being tracked */
- int64_t rate; /* Period over which to throttle. 0 to disable */
- int64_t last; /* Time at which event was last emitted */
+typedef struct MonitorQAPIEventState {
+ QAPIEvent event; /* Event being tracked */
+ int64_t rate; /* Minimum time (in ns) between two events */
+ int64_t last; /* QEMU_CLOCK_REALTIME value at last emission */
QEMUTimer *timer; /* Timer for handling delayed events */
QObject *data; /* Event pending delayed dispatch */
-} MonitorEventState;
+} MonitorQAPIEventState;
struct Monitor {
CharDriverState *chr;
- int mux_out;
int reset_seen;
int flags;
int suspend_cnt;
bool skip_flush;
+
+ QemuMutex out_lock;
QString *outbuf;
- guint watch;
+ guint out_watch;
+
+ /* Read under either BQL or out_lock, written with BQL+out_lock. */
+ int mux_out;
+
ReadLineState *rs;
MonitorControl *mc;
CPUState *mon_cpu;
- BlockDriverCompletionFunc *password_completion_cb;
+ BlockCompletionFunc *password_completion_cb;
void *password_opaque;
mon_cmd_t *cmd_table;
QError *error;
/* QMP checker flags */
#define QMP_ACCEPT_UNKNOWNS 1
+/* Protects mon_list, monitor_event_state. */
+static QemuMutex monitor_lock;
+
static QLIST_HEAD(mon_list, Monitor) mon_list;
static QLIST_HEAD(mon_fdsets, MonFdset) mon_fdsets;
static int mon_refcount;
}
}
+static void monitor_flush_locked(Monitor *mon);
+
static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond,
void *opaque)
{
Monitor *mon = opaque;
- mon->watch = 0;
- monitor_flush(mon);
+ qemu_mutex_lock(&mon->out_lock);
+ mon->out_watch = 0;
+ monitor_flush_locked(mon);
+ qemu_mutex_unlock(&mon->out_lock);
return FALSE;
}
-void monitor_flush(Monitor *mon)
+/* Called with mon->out_lock held. */
+static void monitor_flush_locked(Monitor *mon)
{
int rc;
size_t len;
QDECREF(mon->outbuf);
mon->outbuf = tmp;
}
- if (mon->watch == 0) {
- mon->watch = qemu_chr_fe_add_watch(mon->chr, G_IO_OUT,
- monitor_unblocked, mon);
+ if (mon->out_watch == 0) {
+ mon->out_watch = qemu_chr_fe_add_watch(mon->chr, G_IO_OUT|G_IO_HUP,
+ monitor_unblocked, mon);
}
}
}
+void monitor_flush(Monitor *mon)
+{
+ qemu_mutex_lock(&mon->out_lock);
+ monitor_flush_locked(mon);
+ qemu_mutex_unlock(&mon->out_lock);
+}
+
/* flush at every end of line */
static void monitor_puts(Monitor *mon, const char *str)
{
char c;
+ qemu_mutex_lock(&mon->out_lock);
for(;;) {
c = *str++;
if (c == '\0')
}
qstring_append_chr(mon->outbuf, c);
if (c == '\n') {
- monitor_flush(mon);
+ monitor_flush_locked(mon);
}
}
+ qemu_mutex_unlock(&mon->out_lock);
}
void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
QDECREF(qmp);
}
-static void timestamp_put(QDict *qdict)
-{
- int err;
- QObject *obj;
- qemu_timeval tv;
-
- err = qemu_gettimeofday(&tv);
- if (err < 0)
- return;
-
- obj = qobject_from_jsonf("{ 'seconds': %" PRId64 ", "
- "'microseconds': %" PRId64 " }",
- (int64_t) tv.tv_sec, (int64_t) tv.tv_usec);
- qdict_put_obj(qdict, "timestamp", obj);
-}
-
-
-static const char *monitor_event_names[] = {
- [QEVENT_SHUTDOWN] = "SHUTDOWN",
- [QEVENT_RESET] = "RESET",
- [QEVENT_POWERDOWN] = "POWERDOWN",
- [QEVENT_STOP] = "STOP",
- [QEVENT_RESUME] = "RESUME",
- [QEVENT_VNC_CONNECTED] = "VNC_CONNECTED",
- [QEVENT_VNC_INITIALIZED] = "VNC_INITIALIZED",
- [QEVENT_VNC_DISCONNECTED] = "VNC_DISCONNECTED",
- [QEVENT_BLOCK_IO_ERROR] = "BLOCK_IO_ERROR",
- [QEVENT_RTC_CHANGE] = "RTC_CHANGE",
- [QEVENT_WATCHDOG] = "WATCHDOG",
- [QEVENT_SPICE_CONNECTED] = "SPICE_CONNECTED",
- [QEVENT_SPICE_INITIALIZED] = "SPICE_INITIALIZED",
- [QEVENT_SPICE_DISCONNECTED] = "SPICE_DISCONNECTED",
- [QEVENT_BLOCK_JOB_COMPLETED] = "BLOCK_JOB_COMPLETED",
- [QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED",
- [QEVENT_BLOCK_JOB_ERROR] = "BLOCK_JOB_ERROR",
- [QEVENT_BLOCK_JOB_READY] = "BLOCK_JOB_READY",
- [QEVENT_DEVICE_DELETED] = "DEVICE_DELETED",
- [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED",
- [QEVENT_NIC_RX_FILTER_CHANGED] = "NIC_RX_FILTER_CHANGED",
- [QEVENT_SUSPEND] = "SUSPEND",
- [QEVENT_SUSPEND_DISK] = "SUSPEND_DISK",
- [QEVENT_WAKEUP] = "WAKEUP",
- [QEVENT_BALLOON_CHANGE] = "BALLOON_CHANGE",
- [QEVENT_SPICE_MIGRATE_COMPLETED] = "SPICE_MIGRATE_COMPLETED",
- [QEVENT_GUEST_PANICKED] = "GUEST_PANICKED",
- [QEVENT_BLOCK_IMAGE_CORRUPTED] = "BLOCK_IMAGE_CORRUPTED",
- [QEVENT_QUORUM_FAILURE] = "QUORUM_FAILURE",
- [QEVENT_QUORUM_REPORT_BAD] = "QUORUM_REPORT_BAD",
-};
-QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX)
-static MonitorEventState monitor_event_state[QEVENT_MAX];
+static MonitorQAPIEventState monitor_qapi_event_state[QAPI_EVENT_MAX];
/*
- * Emits the event to every monitor instance
+ * Emits the event to every monitor instance, @event is only used for trace
+ * Called with monitor_lock held.
*/
-static void
-monitor_protocol_event_emit(MonitorEvent event,
- QObject *data)
+static void monitor_qapi_event_emit(QAPIEvent event, QObject *data)
{
Monitor *mon;
}
}
-
/*
* Queue a new event for emission to Monitor instances,
* applying any rate limiting if required.
*/
static void
-monitor_protocol_event_queue(MonitorEvent event,
- QObject *data)
+monitor_qapi_event_queue(QAPIEvent event, QDict *data, Error **errp)
{
- MonitorEventState *evstate;
+ MonitorQAPIEventState *evstate;
+ assert(event < QAPI_EVENT_MAX);
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
- assert(event < QEVENT_MAX);
- evstate = &(monitor_event_state[event]);
+ evstate = &(monitor_qapi_event_state[event]);
trace_monitor_protocol_event_queue(event,
data,
evstate->rate,
now);
/* Rate limit of 0 indicates no throttling */
+ qemu_mutex_lock(&monitor_lock);
if (!evstate->rate) {
- monitor_protocol_event_emit(event, data);
+ monitor_qapi_event_emit(event, QOBJECT(data));
evstate->last = now;
} else {
int64_t delta = now - evstate->last;
int64_t then = evstate->last + evstate->rate;
timer_mod_ns(evstate->timer, then);
}
- evstate->data = data;
+ evstate->data = QOBJECT(data);
qobject_incref(evstate->data);
} else {
- monitor_protocol_event_emit(event, data);
+ monitor_qapi_event_emit(event, QOBJECT(data));
evstate->last = now;
}
}
+ qemu_mutex_unlock(&monitor_lock);
}
-
/*
* The callback invoked by QemuTimer when a delayed
* event is ready to be emitted
*/
-static void monitor_protocol_event_handler(void *opaque)
+static void monitor_qapi_event_handler(void *opaque)
{
- MonitorEventState *evstate = opaque;
+ MonitorQAPIEventState *evstate = opaque;
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
-
trace_monitor_protocol_event_handler(evstate->event,
evstate->data,
evstate->last,
now);
+ qemu_mutex_lock(&monitor_lock);
if (evstate->data) {
- monitor_protocol_event_emit(evstate->event, evstate->data);
+ monitor_qapi_event_emit(evstate->event, evstate->data);
qobject_decref(evstate->data);
evstate->data = NULL;
}
evstate->last = now;
+ qemu_mutex_unlock(&monitor_lock);
}
-
/*
* @event: the event ID to be limited
* @rate: the rate limit in milliseconds
* milliseconds
*/
static void
-monitor_protocol_event_throttle(MonitorEvent event,
- int64_t rate)
+monitor_qapi_event_throttle(QAPIEvent event, int64_t rate)
{
- MonitorEventState *evstate;
- assert(event < QEVENT_MAX);
+ MonitorQAPIEventState *evstate;
+ assert(event < QAPI_EVENT_MAX);
- evstate = &(monitor_event_state[event]);
+ evstate = &(monitor_qapi_event_state[event]);
trace_monitor_protocol_event_throttle(event, rate);
evstate->event = event;
+ assert(rate * SCALE_MS <= INT64_MAX);
evstate->rate = rate * SCALE_MS;
- evstate->timer = timer_new(QEMU_CLOCK_REALTIME,
- SCALE_MS,
- monitor_protocol_event_handler,
- evstate);
evstate->last = 0;
evstate->data = NULL;
+ evstate->timer = timer_new(QEMU_CLOCK_REALTIME,
+ SCALE_MS,
+ monitor_qapi_event_handler,
+ evstate);
}
-
-/* Global, one-time initializer to configure the rate limiting
- * and initialize state */
-static void monitor_protocol_event_init(void)
+static void monitor_qapi_event_init(void)
{
- /* Limit RTC & BALLOON events to 1 per second */
- monitor_protocol_event_throttle(QEVENT_RTC_CHANGE, 1000);
- monitor_protocol_event_throttle(QEVENT_BALLOON_CHANGE, 1000);
- monitor_protocol_event_throttle(QEVENT_WATCHDOG, 1000);
- /* limit the rate of quorum events to avoid hammering the management */
- monitor_protocol_event_throttle(QEVENT_QUORUM_REPORT_BAD, 1000);
- monitor_protocol_event_throttle(QEVENT_QUORUM_FAILURE, 1000);
-}
+ /* Limit guest-triggerable events to 1 per second */
+ monitor_qapi_event_throttle(QAPI_EVENT_RTC_CHANGE, 1000);
+ monitor_qapi_event_throttle(QAPI_EVENT_WATCHDOG, 1000);
+ monitor_qapi_event_throttle(QAPI_EVENT_BALLOON_CHANGE, 1000);
+ monitor_qapi_event_throttle(QAPI_EVENT_QUORUM_REPORT_BAD, 1000);
+ monitor_qapi_event_throttle(QAPI_EVENT_QUORUM_FAILURE, 1000);
+ monitor_qapi_event_throttle(QAPI_EVENT_VSERPORT_CHANGE, 1000);
-/**
- * monitor_protocol_event(): Generate a Monitor event
- *
- * Event-specific data can be emitted through the (optional) 'data' parameter.
- */
-void monitor_protocol_event(MonitorEvent event, QObject *data)
-{
- QDict *qmp;
- const char *event_name;
-
- assert(event < QEVENT_MAX);
-
- event_name = monitor_event_names[event];
- assert(event_name != NULL);
-
- qmp = qdict_new();
- timestamp_put(qmp);
- qdict_put(qmp, "event", qstring_from_str(event_name));
- if (data) {
- qobject_incref(data);
- qdict_put_obj(qmp, "data", data);
- }
-
- trace_monitor_protocol_event(event, event_name, qmp);
- monitor_protocol_event_queue(event, QOBJECT(qmp));
- QDECREF(qmp);
+ qmp_event_set_func_emit(monitor_qapi_event_queue);
}
static int do_qmp_capabilities(Monitor *mon, const QDict *params,
static void monitor_data_init(Monitor *mon)
{
memset(mon, 0, sizeof(Monitor));
+ qemu_mutex_init(&mon->out_lock);
mon->outbuf = qstring_new();
/* Use *mon_cmds by default. */
mon->cmd_table = mon_cmds;
static void monitor_data_destroy(Monitor *mon)
{
QDECREF(mon->outbuf);
+ qemu_mutex_destroy(&mon->out_lock);
}
char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
handle_user_command(&hmp, command_line);
cur_mon = old_mon;
+ qemu_mutex_lock(&hmp.out_lock);
if (qstring_get_length(hmp.outbuf) > 0) {
output = g_strdup(qstring_get_str(hmp.outbuf));
} else {
output = g_strdup("");
}
+ qemu_mutex_unlock(&hmp.out_lock);
out:
monitor_data_destroy(&hmp);
{
const char *tp_name = qdict_get_str(qdict, "name");
bool new_state = qdict_get_bool(qdict, "option");
+ Error *local_err = NULL;
- bool found = false;
- TraceEvent *ev = NULL;
- while ((ev = trace_event_pattern(tp_name, ev)) != NULL) {
- found = true;
- if (!trace_event_get_state_static(ev)) {
- monitor_printf(mon, "event \"%s\" is not traceable\n", tp_name);
- } else {
- trace_event_set_state_dynamic(ev, new_state);
- }
- }
- if (!trace_event_is_pattern(tp_name) && !found) {
- monitor_printf(mon, "unknown event name \"%s\"\n", tp_name);
+ qmp_trace_event_set_state(tp_name, new_state, true, true, &local_err);
+ if (local_err) {
+ qerror_report_err(local_err);
+ error_free(local_err);
}
}
EventInfoList *qmp_query_events(Error **errp)
{
EventInfoList *info, *ev_list = NULL;
- MonitorEvent e;
+ QAPIEvent e;
- for (e = 0 ; e < QEVENT_MAX ; e++) {
- const char *event_name = monitor_event_names[e];
+ for (e = 0 ; e < QAPI_EVENT_MAX ; e++) {
+ const char *event_name = QAPIEvent_lookup[e];
assert(event_name != NULL);
info = g_malloc0(sizeof(*info));
info->value = g_malloc0(sizeof(*info->value));
static void do_info_jit(Monitor *mon, const QDict *qdict)
{
dump_exec_info((FILE *)mon, monitor_fprintf);
+ dump_drift_info((FILE *)mon, monitor_fprintf);
+}
+
+static void do_info_opcount(Monitor *mon, const QDict *qdict)
+{
+ dump_opcount_info((FILE *)mon, monitor_fprintf);
}
static void do_info_history(Monitor *mon, const QDict *qdict)
static void do_trace_print_events(Monitor *mon, const QDict *qdict)
{
- trace_print_events((FILE *)mon, &monitor_fprintf);
+ TraceEventInfoList *events = qmp_trace_event_get_state("*", NULL);
+ TraceEventInfoList *elem;
+
+ for (elem = events; elem != NULL; elem = elem->next) {
+ monitor_printf(mon, "%s : state %u\n",
+ elem->value->name,
+ elem->value->state == TRACE_EVENT_STATE_ENABLED ? 1 : 0);
+ }
+ qapi_free_TraceEventInfoList(events);
}
static int client_migrate_info(Monitor *mon, const QDict *qdict,
flags = 1;
}
}
+#endif
+#ifdef TARGET_PPC
+ flags = msr_le << 16;
+ flags |= env->bfd_mach;
#endif
monitor_disas(mon, env, addr, count, is_physical, flags);
return;
static void do_boot_set(Monitor *mon, const QDict *qdict)
{
- int res;
+ Error *local_err = NULL;
const char *bootdevice = qdict_get_str(qdict, "bootdevice");
- res = qemu_boot_set(bootdevice);
- if (res == 0) {
- monitor_printf(mon, "boot device list now set to %s\n", bootdevice);
- } else if (res > 0) {
- monitor_printf(mon, "setting boot device list failed\n");
+ qemu_boot_set(bootdevice, &local_err);
+ if (local_err) {
+ monitor_printf(mon, "%s\n", error_get_pretty(local_err));
+ error_free(local_err);
} else {
- monitor_printf(mon, "no function defined to set boot device list for "
- "this architecture\n");
+ monitor_printf(mon, "boot device list now set to %s\n", bootdevice);
}
}
{
int i;
CPUState *cpu;
+ uint64_t *node_mem;
+ node_mem = g_new0(uint64_t, nb_numa_nodes);
+ query_numa_node_mem(node_mem);
monitor_printf(mon, "%d nodes\n", nb_numa_nodes);
for (i = 0; i < nb_numa_nodes; i++) {
monitor_printf(mon, "node %d cpus:", i);
}
monitor_printf(mon, "\n");
monitor_printf(mon, "node %d size: %" PRId64 " MB\n", i,
- node_mem[i] >> 20);
+ node_mem[i] >> 20);
}
+ g_free(node_mem);
}
#ifdef CONFIG_PROFILER
if (QLIST_EMPTY(&mon_fdset->dup_fds)) {
monitor_fdset_cleanup(mon_fdset);
}
+ return -1;
+ } else {
+ return mon_fdset->id;
}
- return mon_fdset->id;
}
}
}
return monitor_fdset_dup_fd_find_remove(dup_fd, false);
}
-int monitor_fdset_dup_fd_remove(int dup_fd)
+void monitor_fdset_dup_fd_remove(int dup_fd)
{
- return monitor_fdset_dup_fd_find_remove(dup_fd, true);
+ monitor_fdset_dup_fd_find_remove(dup_fd, true);
}
int monitor_handle_fd_param(Monitor *mon, const char *fdname)
},
{
.name = "block",
- .args_type = "verbose:-v,device:B?",
- .params = "[-v] [device]",
+ .args_type = "nodes:-n,verbose:-v,device:B?",
+ .params = "[-n] [-v] [device]",
.help = "show info of one block device or all block devices "
- "(and details of images with -v option)",
+ "(-n: show named nodes; -v: show details)",
.mhandler.cmd = hmp_info_block,
},
{
.help = "show dynamic compiler info",
.mhandler.cmd = do_info_jit,
},
+ {
+ .name = "opcount",
+ .args_type = "",
+ .params = "",
+ .help = "show dynamic compiler opcode counters",
+ .mhandler.cmd = do_info_opcount,
+ },
{
.name = "kvm",
.args_type = "",
.help = "show the current VM status (running|paused)",
.mhandler.cmd = hmp_info_status,
},
- {
- .name = "pcmcia",
- .args_type = "",
- .params = "",
- .help = "show guest PCMCIA status",
- .mhandler.cmd = pcmcia_info,
- },
{
.name = "mice",
.args_type = "",
.help = "show the TPM device",
.mhandler.cmd = hmp_info_tpm,
},
+ {
+ .name = "memdev",
+ .args_type = "",
+ .params = "",
+ .help = "show memory backends",
+ .mhandler.cmd = hmp_info_memdev,
+ },
+ {
+ .name = "memory-devices",
+ .args_type = "",
+ .params = "",
+ .help = "show memory devices",
+ .mhandler.cmd = hmp_info_memory_devices,
+ },
{
.name = NULL,
},
u = 0;
for (i = 0; i < 8; i++)
- u |= env->crf[i] << (32 - (4 * i));
+ u |= env->crf[i] << (32 - (4 * (i + 1)));
return u;
}
closedir(ffs);
}
-typedef struct MonitorBlockComplete {
- Monitor *mon;
- const char *input;
-} MonitorBlockComplete;
-
-static void block_completion_it(void *opaque, BlockDriverState *bs)
-{
- const char *name = bdrv_get_device_name(bs);
- MonitorBlockComplete *mbc = opaque;
- Monitor *mon = mbc->mon;
- const char *input = mbc->input;
-
- if (input[0] == '\0' ||
- !strncmp(name, (char *)input, strlen(input))) {
- readline_add_completion(mon->rs, name);
- }
-}
-
static const char *next_arg_type(const char *typestr)
{
const char *p = strchr(typestr, ':');
g_slist_free(list);
}
-static void device_del_bus_completion(ReadLineState *rs, BusState *bus,
- const char *str, size_t len)
+static void peripheral_device_del_completion(ReadLineState *rs,
+ const char *str, size_t len)
{
- BusChild *kid;
+ Object *peripheral = container_get(qdev_get_machine(), "/peripheral");
+ GSList *list, *item;
+
+ list = qdev_build_hotpluggable_device_list(peripheral);
+ if (!list) {
+ return;
+ }
- QTAILQ_FOREACH(kid, &bus->children, sibling) {
- DeviceState *dev = kid->child;
- BusState *dev_child;
+ for (item = list; item; item = g_slist_next(item)) {
+ DeviceState *dev = item->data;
if (dev->id && !strncmp(str, dev->id, len)) {
readline_add_completion(rs, dev->id);
}
-
- QLIST_FOREACH(dev_child, &dev->child_bus, sibling) {
- device_del_bus_completion(rs, dev_child, str, len);
- }
}
+
+ g_slist_free(list);
}
void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str)
len = strlen(str);
readline_set_completion_index(rs, len);
- device_del_bus_completion(rs, sysbus_get_default(), str, len);
+ peripheral_device_del_completion(rs, str, len);
}
void object_del_completion(ReadLineState *rs, int nb_args, const char *str)
}
}
+void watchdog_action_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+ int i;
+
+ if (nb_args != 2) {
+ return;
+ }
+ readline_set_completion_index(rs, strlen(str));
+ for (i = 0; WatchdogExpirationAction_lookup[i]; i++) {
+ add_completion_option(rs, str, WatchdogExpirationAction_lookup[i]);
+ }
+}
+
+void migrate_set_capability_completion(ReadLineState *rs, int nb_args,
+ const char *str)
+{
+ size_t len;
+
+ len = strlen(str);
+ readline_set_completion_index(rs, len);
+ if (nb_args == 2) {
+ int i;
+ for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
+ const char *name = MigrationCapability_lookup[i];
+ if (!strncmp(str, name, len)) {
+ readline_add_completion(rs, name);
+ }
+ }
+ } else if (nb_args == 3) {
+ add_completion_option(rs, str, "on");
+ add_completion_option(rs, str, "off");
+ }
+}
+
+void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+ int i;
+ size_t len;
+ if (nb_args != 2) {
+ return;
+ }
+ len = strlen(str);
+ readline_set_completion_index(rs, len);
+ for (i = 0; host_net_devices[i]; i++) {
+ if (!strncmp(host_net_devices[i], str, len)) {
+ readline_add_completion(rs, host_net_devices[i]);
+ }
+ }
+}
+
+void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+ NetClientState *ncs[255];
+ int count, i, len;
+
+ len = strlen(str);
+ readline_set_completion_index(rs, len);
+ if (nb_args == 2) {
+ count = qemu_find_net_clients_except(NULL, ncs,
+ NET_CLIENT_OPTIONS_KIND_NONE, 255);
+ for (i = 0; i < count; i++) {
+ int id;
+ char name[16];
+
+ if (net_hub_id_for_client(ncs[i], &id)) {
+ continue;
+ }
+ snprintf(name, sizeof(name), "%d", id);
+ if (!strncmp(str, name, len)) {
+ readline_add_completion(rs, name);
+ }
+ }
+ return;
+ } else if (nb_args == 3) {
+ count = qemu_find_net_clients_except(NULL, ncs,
+ NET_CLIENT_OPTIONS_KIND_NIC, 255);
+ for (i = 0; i < count; i++) {
+ const char *name;
+
+ name = ncs[i]->name;
+ if (!strncmp(str, name, len)) {
+ readline_add_completion(rs, name);
+ }
+ }
+ return;
+ }
+}
+
+static void vm_completion(ReadLineState *rs, const char *str)
+{
+ size_t len;
+ BlockDriverState *bs = NULL;
+
+ len = strlen(str);
+ readline_set_completion_index(rs, len);
+ while ((bs = bdrv_next(bs))) {
+ SnapshotInfoList *snapshots, *snapshot;
+
+ if (!bdrv_can_snapshot(bs)) {
+ continue;
+ }
+ if (bdrv_query_snapshot_info_list(bs, &snapshots, NULL)) {
+ continue;
+ }
+ snapshot = snapshots;
+ while (snapshot) {
+ char *completion = snapshot->value->name;
+ if (!strncmp(str, completion, len)) {
+ readline_add_completion(rs, completion);
+ }
+ completion = snapshot->value->id;
+ if (!strncmp(str, completion, len)) {
+ readline_add_completion(rs, completion);
+ }
+ snapshot = snapshot->next;
+ }
+ qapi_free_SnapshotInfoList(snapshots);
+ }
+
+}
+
+void delvm_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+ if (nb_args == 2) {
+ vm_completion(rs, str);
+ }
+}
+
+void loadvm_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+ if (nb_args == 2) {
+ vm_completion(rs, str);
+ }
+}
+
static void monitor_find_completion_by_table(Monitor *mon,
const mon_cmd_t *cmd_table,
char **args,
{
const char *cmdname;
int i;
- const char *ptype, *str;
+ const char *ptype, *str, *name;
const mon_cmd_t *cmd;
- MonitorBlockComplete mbs;
+ BlockDriverState *bs;
if (nb_args <= 1) {
/* command completion */
}
}
str = args[nb_args - 1];
- if (*ptype == '-' && ptype[1] != '\0') {
+ while (*ptype == '-' && ptype[1] != '\0') {
ptype = next_arg_type(ptype);
}
switch(*ptype) {
break;
case 'B':
/* block device name completion */
- mbs.mon = mon;
- mbs.input = str;
readline_set_completion_index(mon->rs, strlen(str));
- bdrv_iterate(block_completion_it, &mbs);
+ for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
+ name = bdrv_get_device_name(bs);
+ if (str[0] == '\0' ||
+ !strncmp(name, str, strlen(str))) {
+ readline_add_completion(mon->rs, name);
+ }
+ }
break;
case 's':
case 'S':
return;
}
#ifdef DEBUG_COMPLETION
- for (i = 0; i < nb_args; i++) {
- monitor_printf(mon, "arg%d = '%s'\n", i, args[i]);
+ {
+ int i;
+ for (i = 0; i < nb_args; i++) {
+ monitor_printf(mon, "arg%d = '%s'\n", i, args[i]);
+ }
}
#endif
switch (event) {
case CHR_EVENT_MUX_IN:
+ qemu_mutex_lock(&mon->out_lock);
mon->mux_out = 0;
+ qemu_mutex_unlock(&mon->out_lock);
if (mon->reset_seen) {
readline_restart(mon->rs);
monitor_resume(mon);
} else {
mon->suspend_cnt++;
}
+ qemu_mutex_lock(&mon->out_lock);
mon->mux_out = 1;
+ qemu_mutex_unlock(&mon->out_lock);
break;
case CHR_EVENT_OPENED:
monitor_printf(mon, "QEMU %s monitor - type 'help' for more "
"information\n", QEMU_VERSION);
if (!mon->mux_out) {
+ readline_restart(mon->rs);
readline_show_prompt(mon->rs);
}
mon->reset_seen = 1;
monitor_flush(opaque);
}
+static void __attribute__((constructor)) monitor_lock_init(void)
+{
+ qemu_mutex_init(&monitor_lock);
+}
+
void monitor_init(CharDriverState *chr, int flags)
{
static int is_first_init = 1;
Monitor *mon;
if (is_first_init) {
- monitor_protocol_event_init();
+ monitor_qapi_event_init();
sortcmdlist();
is_first_init = 0;
}
monitor_event, mon);
}
+ qemu_mutex_lock(&monitor_lock);
QLIST_INSERT_HEAD(&mon_list, mon, entry);
+ qemu_mutex_unlock(&monitor_lock);
+
if (!default_mon || (flags & MONITOR_IS_DEFAULT))
default_mon = mon;
}
}
int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
- BlockDriverCompletionFunc *completion_cb,
+ BlockCompletionFunc *completion_cb,
void *opaque)
{
int err;
}
int monitor_read_block_device_key(Monitor *mon, const char *device,
- BlockDriverCompletionFunc *completion_cb,
+ BlockCompletionFunc *completion_cb,
void *opaque)
{
BlockDriverState *bs;
{ /* end of list */ }
},
};
+
+#ifndef TARGET_I386
+void qmp_rtc_reset_reinjection(Error **errp)
+{
+ error_set(errp, QERR_FEATURE_DISABLED, "rtc-reset-reinjection");
+}
+#endif