mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'qmp/queue/qmp' into staging
Conflicts: ui/spice-core.c
This commit is contained in:
@@ -25,12 +25,11 @@
|
||||
*/
|
||||
|
||||
#include "monitor.h"
|
||||
#include "qjson.h"
|
||||
#include "qint.h"
|
||||
#include "cpu-common.h"
|
||||
#include "kvm.h"
|
||||
#include "balloon.h"
|
||||
#include "trace.h"
|
||||
#include "qmp-commands.h"
|
||||
|
||||
static QEMUBalloonEvent *balloon_event_fn;
|
||||
static QEMUBalloonStatus *balloon_stat_fn;
|
||||
@@ -72,76 +71,33 @@ static int qemu_balloon(ram_addr_t target)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int qemu_balloon_status(MonitorCompletion cb, void *opaque)
|
||||
static int qemu_balloon_status(BalloonInfo *info)
|
||||
{
|
||||
if (!balloon_stat_fn) {
|
||||
return 0;
|
||||
}
|
||||
balloon_stat_fn(balloon_opaque, cb, opaque);
|
||||
balloon_stat_fn(balloon_opaque, info);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void print_balloon_stat(const char *key, QObject *obj, void *opaque)
|
||||
BalloonInfo *qmp_query_balloon(Error **errp)
|
||||
{
|
||||
Monitor *mon = opaque;
|
||||
|
||||
if (strcmp(key, "actual")) {
|
||||
monitor_printf(mon, ",%s=%" PRId64, key,
|
||||
qint_get_int(qobject_to_qint(obj)));
|
||||
}
|
||||
}
|
||||
|
||||
void monitor_print_balloon(Monitor *mon, const QObject *data)
|
||||
{
|
||||
QDict *qdict;
|
||||
|
||||
qdict = qobject_to_qdict(data);
|
||||
if (!qdict_haskey(qdict, "actual")) {
|
||||
return;
|
||||
}
|
||||
monitor_printf(mon, "balloon: actual=%" PRId64,
|
||||
qdict_get_int(qdict, "actual") >> 20);
|
||||
qdict_iter(qdict, print_balloon_stat, mon);
|
||||
monitor_printf(mon, "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* do_info_balloon(): Balloon information
|
||||
*
|
||||
* Make an asynchronous request for balloon info. When the request completes
|
||||
* a QDict will be returned according to the following specification:
|
||||
*
|
||||
* - "actual": current balloon value in bytes
|
||||
* The following fields may or may not be present:
|
||||
* - "mem_swapped_in": Amount of memory swapped in (bytes)
|
||||
* - "mem_swapped_out": Amount of memory swapped out (bytes)
|
||||
* - "major_page_faults": Number of major faults
|
||||
* - "minor_page_faults": Number of minor faults
|
||||
* - "free_mem": Total amount of free and unused memory (bytes)
|
||||
* - "total_mem": Total amount of available memory (bytes)
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* { "actual": 1073741824, "mem_swapped_in": 0, "mem_swapped_out": 0,
|
||||
* "major_page_faults": 142, "minor_page_faults": 239245,
|
||||
* "free_mem": 1014185984, "total_mem": 1044668416 }
|
||||
*/
|
||||
int do_info_balloon(Monitor *mon, MonitorCompletion cb, void *opaque)
|
||||
{
|
||||
int ret;
|
||||
BalloonInfo *info;
|
||||
|
||||
if (kvm_enabled() && !kvm_has_sync_mmu()) {
|
||||
qerror_report(QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
|
||||
return -1;
|
||||
error_set(errp, QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = qemu_balloon_status(cb, opaque);
|
||||
if (!ret) {
|
||||
qerror_report(QERR_DEVICE_NOT_ACTIVE, "balloon");
|
||||
return -1;
|
||||
info = g_malloc0(sizeof(*info));
|
||||
|
||||
if (qemu_balloon_status(info) == 0) {
|
||||
error_set(errp, QERR_DEVICE_NOT_ACTIVE, "balloon");
|
||||
qapi_free_BalloonInfo(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,17 +15,15 @@
|
||||
#define _QEMU_BALLOON_H
|
||||
|
||||
#include "monitor.h"
|
||||
#include "qapi-types.h"
|
||||
|
||||
typedef void (QEMUBalloonEvent)(void *opaque, ram_addr_t target);
|
||||
typedef void (QEMUBalloonStatus)(void *opaque, MonitorCompletion cb,
|
||||
void *cb_data);
|
||||
typedef void (QEMUBalloonStatus)(void *opaque, BalloonInfo *info);
|
||||
|
||||
int qemu_add_balloon_handler(QEMUBalloonEvent *event_func,
|
||||
QEMUBalloonStatus *stat_func, void *opaque);
|
||||
void qemu_remove_balloon_handler(void *opaque);
|
||||
|
||||
void monitor_print_balloon(Monitor *mon, const QObject *data);
|
||||
int do_info_balloon(Monitor *mon, MonitorCompletion cb, void *opaque);
|
||||
int do_balloon(Monitor *mon, const QDict *params,
|
||||
MonitorCompletion cb, void *opaque);
|
||||
|
||||
|
||||
@@ -27,8 +27,9 @@
|
||||
#include "monitor.h"
|
||||
#include "block_int.h"
|
||||
#include "module.h"
|
||||
#include "qemu-objects.h"
|
||||
#include "qjson.h"
|
||||
#include "qemu-coroutine.h"
|
||||
#include "qmp-commands.h"
|
||||
|
||||
#ifdef CONFIG_BSD
|
||||
#include <sys/types.h>
|
||||
@@ -1824,195 +1825,105 @@ void bdrv_mon_event(const BlockDriverState *bdrv,
|
||||
qobject_decref(data);
|
||||
}
|
||||
|
||||
static void bdrv_print_dict(QObject *obj, void *opaque)
|
||||
BlockInfoList *qmp_query_block(Error **errp)
|
||||
{
|
||||
QDict *bs_dict;
|
||||
Monitor *mon = opaque;
|
||||
|
||||
bs_dict = qobject_to_qdict(obj);
|
||||
|
||||
monitor_printf(mon, "%s: removable=%d",
|
||||
qdict_get_str(bs_dict, "device"),
|
||||
qdict_get_bool(bs_dict, "removable"));
|
||||
|
||||
if (qdict_get_bool(bs_dict, "removable")) {
|
||||
monitor_printf(mon, " locked=%d", qdict_get_bool(bs_dict, "locked"));
|
||||
monitor_printf(mon, " tray-open=%d",
|
||||
qdict_get_bool(bs_dict, "tray-open"));
|
||||
}
|
||||
|
||||
if (qdict_haskey(bs_dict, "io-status")) {
|
||||
monitor_printf(mon, " io-status=%s", qdict_get_str(bs_dict, "io-status"));
|
||||
}
|
||||
|
||||
if (qdict_haskey(bs_dict, "inserted")) {
|
||||
QDict *qdict = qobject_to_qdict(qdict_get(bs_dict, "inserted"));
|
||||
|
||||
monitor_printf(mon, " file=");
|
||||
monitor_print_filename(mon, qdict_get_str(qdict, "file"));
|
||||
if (qdict_haskey(qdict, "backing_file")) {
|
||||
monitor_printf(mon, " backing_file=");
|
||||
monitor_print_filename(mon, qdict_get_str(qdict, "backing_file"));
|
||||
}
|
||||
monitor_printf(mon, " ro=%d drv=%s encrypted=%d",
|
||||
qdict_get_bool(qdict, "ro"),
|
||||
qdict_get_str(qdict, "drv"),
|
||||
qdict_get_bool(qdict, "encrypted"));
|
||||
} else {
|
||||
monitor_printf(mon, " [not inserted]");
|
||||
}
|
||||
|
||||
monitor_printf(mon, "\n");
|
||||
}
|
||||
|
||||
void bdrv_info_print(Monitor *mon, const QObject *data)
|
||||
{
|
||||
qlist_iter(qobject_to_qlist(data), bdrv_print_dict, mon);
|
||||
}
|
||||
|
||||
static const char *const io_status_name[BDRV_IOS_MAX] = {
|
||||
[BDRV_IOS_OK] = "ok",
|
||||
[BDRV_IOS_FAILED] = "failed",
|
||||
[BDRV_IOS_ENOSPC] = "nospace",
|
||||
};
|
||||
|
||||
void bdrv_info(Monitor *mon, QObject **ret_data)
|
||||
{
|
||||
QList *bs_list;
|
||||
BlockInfoList *head = NULL, *cur_item = NULL;
|
||||
BlockDriverState *bs;
|
||||
|
||||
bs_list = qlist_new();
|
||||
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, list) {
|
||||
QObject *bs_obj;
|
||||
QDict *bs_dict;
|
||||
BlockInfoList *info = g_malloc0(sizeof(*info));
|
||||
|
||||
bs_obj = qobject_from_jsonf("{ 'device': %s, 'type': 'unknown', "
|
||||
"'removable': %i, 'locked': %i }",
|
||||
bs->device_name,
|
||||
bdrv_dev_has_removable_media(bs),
|
||||
bdrv_dev_is_medium_locked(bs));
|
||||
bs_dict = qobject_to_qdict(bs_obj);
|
||||
info->value = g_malloc0(sizeof(*info->value));
|
||||
info->value->device = g_strdup(bs->device_name);
|
||||
info->value->type = g_strdup("unknown");
|
||||
info->value->locked = bdrv_dev_is_medium_locked(bs);
|
||||
info->value->removable = bdrv_dev_has_removable_media(bs);
|
||||
|
||||
if (bdrv_dev_has_removable_media(bs)) {
|
||||
qdict_put(bs_dict, "tray-open",
|
||||
qbool_from_int(bdrv_dev_is_tray_open(bs)));
|
||||
info->value->has_tray_open = true;
|
||||
info->value->tray_open = bdrv_dev_is_tray_open(bs);
|
||||
}
|
||||
|
||||
if (bdrv_iostatus_is_enabled(bs)) {
|
||||
qdict_put(bs_dict, "io-status",
|
||||
qstring_from_str(io_status_name[bs->iostatus]));
|
||||
info->value->has_io_status = true;
|
||||
info->value->io_status = bs->iostatus;
|
||||
}
|
||||
|
||||
if (bs->drv) {
|
||||
QObject *obj;
|
||||
|
||||
obj = qobject_from_jsonf("{ 'file': %s, 'ro': %i, 'drv': %s, "
|
||||
"'encrypted': %i }",
|
||||
bs->filename, bs->read_only,
|
||||
bs->drv->format_name,
|
||||
bdrv_is_encrypted(bs));
|
||||
if (bs->backing_file[0] != '\0') {
|
||||
QDict *qdict = qobject_to_qdict(obj);
|
||||
qdict_put(qdict, "backing_file",
|
||||
qstring_from_str(bs->backing_file));
|
||||
info->value->has_inserted = true;
|
||||
info->value->inserted = g_malloc0(sizeof(*info->value->inserted));
|
||||
info->value->inserted->file = g_strdup(bs->filename);
|
||||
info->value->inserted->ro = bs->read_only;
|
||||
info->value->inserted->drv = g_strdup(bs->drv->format_name);
|
||||
info->value->inserted->encrypted = bs->encrypted;
|
||||
if (bs->backing_file[0]) {
|
||||
info->value->inserted->has_backing_file = true;
|
||||
info->value->inserted->backing_file = g_strdup(bs->backing_file);
|
||||
}
|
||||
|
||||
qdict_put_obj(bs_dict, "inserted", obj);
|
||||
}
|
||||
qlist_append_obj(bs_list, bs_obj);
|
||||
|
||||
/* XXX: waiting for the qapi to support GSList */
|
||||
if (!cur_item) {
|
||||
head = cur_item = info;
|
||||
} else {
|
||||
cur_item->next = info;
|
||||
cur_item = info;
|
||||
}
|
||||
}
|
||||
|
||||
*ret_data = QOBJECT(bs_list);
|
||||
return head;
|
||||
}
|
||||
|
||||
static void bdrv_stats_iter(QObject *data, void *opaque)
|
||||
/* Consider exposing this as a full fledged QMP command */
|
||||
static BlockStats *qmp_query_blockstat(const BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
QDict *qdict;
|
||||
Monitor *mon = opaque;
|
||||
BlockStats *s;
|
||||
|
||||
qdict = qobject_to_qdict(data);
|
||||
monitor_printf(mon, "%s:", qdict_get_str(qdict, "device"));
|
||||
s = g_malloc0(sizeof(*s));
|
||||
|
||||
qdict = qobject_to_qdict(qdict_get(qdict, "stats"));
|
||||
monitor_printf(mon, " rd_bytes=%" PRId64
|
||||
" wr_bytes=%" PRId64
|
||||
" rd_operations=%" PRId64
|
||||
" wr_operations=%" PRId64
|
||||
" flush_operations=%" PRId64
|
||||
" wr_total_time_ns=%" PRId64
|
||||
" rd_total_time_ns=%" PRId64
|
||||
" flush_total_time_ns=%" PRId64
|
||||
"\n",
|
||||
qdict_get_int(qdict, "rd_bytes"),
|
||||
qdict_get_int(qdict, "wr_bytes"),
|
||||
qdict_get_int(qdict, "rd_operations"),
|
||||
qdict_get_int(qdict, "wr_operations"),
|
||||
qdict_get_int(qdict, "flush_operations"),
|
||||
qdict_get_int(qdict, "wr_total_time_ns"),
|
||||
qdict_get_int(qdict, "rd_total_time_ns"),
|
||||
qdict_get_int(qdict, "flush_total_time_ns"));
|
||||
}
|
||||
|
||||
void bdrv_stats_print(Monitor *mon, const QObject *data)
|
||||
{
|
||||
qlist_iter(qobject_to_qlist(data), bdrv_stats_iter, mon);
|
||||
}
|
||||
|
||||
static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
|
||||
{
|
||||
QObject *res;
|
||||
QDict *dict;
|
||||
|
||||
res = qobject_from_jsonf("{ 'stats': {"
|
||||
"'rd_bytes': %" PRId64 ","
|
||||
"'wr_bytes': %" PRId64 ","
|
||||
"'rd_operations': %" PRId64 ","
|
||||
"'wr_operations': %" PRId64 ","
|
||||
"'wr_highest_offset': %" PRId64 ","
|
||||
"'flush_operations': %" PRId64 ","
|
||||
"'wr_total_time_ns': %" PRId64 ","
|
||||
"'rd_total_time_ns': %" PRId64 ","
|
||||
"'flush_total_time_ns': %" PRId64
|
||||
"} }",
|
||||
bs->nr_bytes[BDRV_ACCT_READ],
|
||||
bs->nr_bytes[BDRV_ACCT_WRITE],
|
||||
bs->nr_ops[BDRV_ACCT_READ],
|
||||
bs->nr_ops[BDRV_ACCT_WRITE],
|
||||
bs->wr_highest_sector *
|
||||
(uint64_t)BDRV_SECTOR_SIZE,
|
||||
bs->nr_ops[BDRV_ACCT_FLUSH],
|
||||
bs->total_time_ns[BDRV_ACCT_WRITE],
|
||||
bs->total_time_ns[BDRV_ACCT_READ],
|
||||
bs->total_time_ns[BDRV_ACCT_FLUSH]);
|
||||
dict = qobject_to_qdict(res);
|
||||
|
||||
if (*bs->device_name) {
|
||||
qdict_put(dict, "device", qstring_from_str(bs->device_name));
|
||||
if (bs->device_name[0]) {
|
||||
s->has_device = true;
|
||||
s->device = g_strdup(bs->device_name);
|
||||
}
|
||||
|
||||
s->stats = g_malloc0(sizeof(*s->stats));
|
||||
s->stats->rd_bytes = bs->nr_bytes[BDRV_ACCT_READ];
|
||||
s->stats->wr_bytes = bs->nr_bytes[BDRV_ACCT_WRITE];
|
||||
s->stats->rd_operations = bs->nr_ops[BDRV_ACCT_READ];
|
||||
s->stats->wr_operations = bs->nr_ops[BDRV_ACCT_WRITE];
|
||||
s->stats->wr_highest_offset = bs->wr_highest_sector * BDRV_SECTOR_SIZE;
|
||||
s->stats->flush_operations = bs->nr_ops[BDRV_ACCT_FLUSH];
|
||||
s->stats->wr_total_time_ns = bs->total_time_ns[BDRV_ACCT_WRITE];
|
||||
s->stats->rd_total_time_ns = bs->total_time_ns[BDRV_ACCT_READ];
|
||||
s->stats->flush_total_time_ns = bs->total_time_ns[BDRV_ACCT_FLUSH];
|
||||
|
||||
if (bs->file) {
|
||||
QObject *parent = bdrv_info_stats_bs(bs->file);
|
||||
qdict_put_obj(dict, "parent", parent);
|
||||
s->has_parent = true;
|
||||
s->parent = qmp_query_blockstat(bs->file, NULL);
|
||||
}
|
||||
|
||||
return res;
|
||||
return s;
|
||||
}
|
||||
|
||||
void bdrv_info_stats(Monitor *mon, QObject **ret_data)
|
||||
BlockStatsList *qmp_query_blockstats(Error **errp)
|
||||
{
|
||||
QObject *obj;
|
||||
QList *devices;
|
||||
BlockStatsList *head = NULL, *cur_item = NULL;
|
||||
BlockDriverState *bs;
|
||||
|
||||
devices = qlist_new();
|
||||
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, list) {
|
||||
obj = bdrv_info_stats_bs(bs);
|
||||
qlist_append_obj(devices, obj);
|
||||
BlockStatsList *info = g_malloc0(sizeof(*info));
|
||||
info->value = qmp_query_blockstat(bs, NULL);
|
||||
|
||||
/* XXX: waiting for the qapi to support GSList */
|
||||
if (!cur_item) {
|
||||
head = cur_item = info;
|
||||
} else {
|
||||
cur_item->next = info;
|
||||
cur_item = info;
|
||||
}
|
||||
}
|
||||
|
||||
*ret_data = QOBJECT(devices);
|
||||
return head;
|
||||
}
|
||||
|
||||
const char *bdrv_get_encrypted_filename(BlockDriverState *bs)
|
||||
@@ -3139,14 +3050,15 @@ int bdrv_in_use(BlockDriverState *bs)
|
||||
|
||||
void bdrv_iostatus_enable(BlockDriverState *bs)
|
||||
{
|
||||
bs->iostatus = BDRV_IOS_OK;
|
||||
bs->iostatus_enabled = true;
|
||||
bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
|
||||
}
|
||||
|
||||
/* The I/O status is only enabled if the drive explicitly
|
||||
* enables it _and_ the VM is configured to stop on errors */
|
||||
bool bdrv_iostatus_is_enabled(const BlockDriverState *bs)
|
||||
{
|
||||
return (bs->iostatus != BDRV_IOS_INVAL &&
|
||||
return (bs->iostatus_enabled &&
|
||||
(bs->on_write_error == BLOCK_ERR_STOP_ENOSPC ||
|
||||
bs->on_write_error == BLOCK_ERR_STOP_ANY ||
|
||||
bs->on_read_error == BLOCK_ERR_STOP_ANY));
|
||||
@@ -3154,13 +3066,13 @@ bool bdrv_iostatus_is_enabled(const BlockDriverState *bs)
|
||||
|
||||
void bdrv_iostatus_disable(BlockDriverState *bs)
|
||||
{
|
||||
bs->iostatus = BDRV_IOS_INVAL;
|
||||
bs->iostatus_enabled = false;
|
||||
}
|
||||
|
||||
void bdrv_iostatus_reset(BlockDriverState *bs)
|
||||
{
|
||||
if (bdrv_iostatus_is_enabled(bs)) {
|
||||
bs->iostatus = BDRV_IOS_OK;
|
||||
bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3169,9 +3081,11 @@ void bdrv_iostatus_reset(BlockDriverState *bs)
|
||||
possible to implement this without device models being involved */
|
||||
void bdrv_iostatus_set_err(BlockDriverState *bs, int error)
|
||||
{
|
||||
if (bdrv_iostatus_is_enabled(bs) && bs->iostatus == BDRV_IOS_OK) {
|
||||
if (bdrv_iostatus_is_enabled(bs) &&
|
||||
bs->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
|
||||
assert(error >= 0);
|
||||
bs->iostatus = error == ENOSPC ? BDRV_IOS_ENOSPC : BDRV_IOS_FAILED;
|
||||
bs->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
|
||||
BLOCK_DEVICE_IO_STATUS_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,11 +77,6 @@ typedef enum {
|
||||
BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP
|
||||
} BlockMonEventAction;
|
||||
|
||||
typedef enum {
|
||||
BDRV_IOS_INVAL, BDRV_IOS_OK, BDRV_IOS_FAILED, BDRV_IOS_ENOSPC,
|
||||
BDRV_IOS_MAX
|
||||
} BlockIOStatus;
|
||||
|
||||
void bdrv_iostatus_enable(BlockDriverState *bs);
|
||||
void bdrv_iostatus_reset(BlockDriverState *bs);
|
||||
void bdrv_iostatus_disable(BlockDriverState *bs);
|
||||
|
||||
+3
-1
@@ -29,6 +29,7 @@
|
||||
#include "qemu-queue.h"
|
||||
#include "qemu-coroutine.h"
|
||||
#include "qemu-timer.h"
|
||||
#include "qapi-types.h"
|
||||
|
||||
#define BLOCK_FLAG_ENCRYPT 1
|
||||
#define BLOCK_FLAG_COMPAT6 4
|
||||
@@ -202,7 +203,8 @@ struct BlockDriverState {
|
||||
drivers. They are not used by the block driver */
|
||||
int cyls, heads, secs, translation;
|
||||
BlockErrorAction on_read_error, on_write_error;
|
||||
BlockIOStatus iostatus;
|
||||
bool iostatus_enabled;
|
||||
BlockDeviceIoStatus iostatus;
|
||||
char device_name[32];
|
||||
unsigned long *dirty_bitmap;
|
||||
int64_t dirty_count;
|
||||
|
||||
@@ -383,8 +383,6 @@ char *vnc_display_local_addr(DisplayState *ds);
|
||||
#ifdef CONFIG_VNC
|
||||
int vnc_display_password(DisplayState *ds, const char *password);
|
||||
int vnc_display_pw_expire(DisplayState *ds, time_t expires);
|
||||
void do_info_vnc_print(Monitor *mon, const QObject *data);
|
||||
void do_info_vnc(Monitor *mon, QObject **ret_data);
|
||||
#else
|
||||
static inline int vnc_display_password(DisplayState *ds, const char *password)
|
||||
{
|
||||
@@ -396,13 +394,6 @@ static inline int vnc_display_pw_expire(DisplayState *ds, time_t expires)
|
||||
qerror_report(QERR_FEATURE_DISABLED, "vnc");
|
||||
return -ENODEV;
|
||||
};
|
||||
static inline void do_info_vnc(Monitor *mon, QObject **ret_data)
|
||||
{
|
||||
};
|
||||
static inline void do_info_vnc_print(Monitor *mon, const QObject *data)
|
||||
{
|
||||
monitor_printf(mon, "VNC support disabled\n");
|
||||
};
|
||||
#endif
|
||||
|
||||
/* curses.c */
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "gdbstub.h"
|
||||
#include "dma.h"
|
||||
#include "kvm.h"
|
||||
#include "qmp-commands.h"
|
||||
|
||||
#include "qemu-thread.h"
|
||||
#include "cpus.h"
|
||||
@@ -1094,3 +1095,47 @@ void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
|
||||
cpu_list(f, cpu_fprintf); /* deprecated */
|
||||
#endif
|
||||
}
|
||||
|
||||
CpuInfoList *qmp_query_cpus(Error **errp)
|
||||
{
|
||||
CpuInfoList *head = NULL, *cur_item = NULL;
|
||||
CPUState *env;
|
||||
|
||||
for(env = first_cpu; env != NULL; env = env->next_cpu) {
|
||||
CpuInfoList *info;
|
||||
|
||||
cpu_synchronize_state(env);
|
||||
|
||||
info = g_malloc0(sizeof(*info));
|
||||
info->value = g_malloc0(sizeof(*info->value));
|
||||
info->value->CPU = env->cpu_index;
|
||||
info->value->current = (env == first_cpu);
|
||||
info->value->halted = env->halted;
|
||||
info->value->thread_id = env->thread_id;
|
||||
#if defined(TARGET_I386)
|
||||
info->value->has_pc = true;
|
||||
info->value->pc = env->eip + env->segs[R_CS].base;
|
||||
#elif defined(TARGET_PPC)
|
||||
info->value->has_nip = true;
|
||||
info->value->nip = env->nip;
|
||||
#elif defined(TARGET_SPARC)
|
||||
info->value->has_pc = true;
|
||||
info->value->pc = env->pc;
|
||||
info->value->has_npc = true;
|
||||
info->value->npc = env->npc;
|
||||
#elif defined(TARGET_MIPS)
|
||||
info->value->has_PC = true;
|
||||
info->value->PC = env->active_tc.PC;
|
||||
#endif
|
||||
|
||||
/* XXX: waiting for the qapi to support GSList */
|
||||
if (!cur_item) {
|
||||
head = cur_item = info;
|
||||
} else {
|
||||
cur_item->next = info;
|
||||
cur_item = info;
|
||||
}
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
@@ -12,8 +12,9 @@
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "error.h"
|
||||
#include "qjson.h"
|
||||
#include "qdict.h"
|
||||
#include "error_int.h"
|
||||
#include "qemu-objects.h"
|
||||
#include "qerror.h"
|
||||
|
||||
struct Error
|
||||
|
||||
+1
-2
@@ -587,8 +587,7 @@ ETEXI
|
||||
.args_type = "index:i",
|
||||
.params = "index",
|
||||
.help = "set the default CPU",
|
||||
.user_print = monitor_user_noop,
|
||||
.mhandler.cmd_new = do_cpu_set,
|
||||
.mhandler.cmd = hmp_cpu,
|
||||
},
|
||||
|
||||
STEXI
|
||||
|
||||
@@ -94,6 +94,401 @@ void hmp_info_chardev(Monitor *mon)
|
||||
qapi_free_ChardevInfoList(char_info);
|
||||
}
|
||||
|
||||
void hmp_info_mice(Monitor *mon)
|
||||
{
|
||||
MouseInfoList *mice_list, *mouse;
|
||||
|
||||
mice_list = qmp_query_mice(NULL);
|
||||
if (!mice_list) {
|
||||
monitor_printf(mon, "No mouse devices connected\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (mouse = mice_list; mouse; mouse = mouse->next) {
|
||||
monitor_printf(mon, "%c Mouse #%" PRId64 ": %s%s\n",
|
||||
mouse->value->current ? '*' : ' ',
|
||||
mouse->value->index, mouse->value->name,
|
||||
mouse->value->absolute ? " (absolute)" : "");
|
||||
}
|
||||
|
||||
qapi_free_MouseInfoList(mice_list);
|
||||
}
|
||||
|
||||
void hmp_info_migrate(Monitor *mon)
|
||||
{
|
||||
MigrationInfo *info;
|
||||
|
||||
info = qmp_query_migrate(NULL);
|
||||
|
||||
if (info->has_status) {
|
||||
monitor_printf(mon, "Migration status: %s\n", info->status);
|
||||
}
|
||||
|
||||
if (info->has_ram) {
|
||||
monitor_printf(mon, "transferred ram: %" PRIu64 " kbytes\n",
|
||||
info->ram->transferred >> 10);
|
||||
monitor_printf(mon, "remaining ram: %" PRIu64 " kbytes\n",
|
||||
info->ram->remaining >> 10);
|
||||
monitor_printf(mon, "total ram: %" PRIu64 " kbytes\n",
|
||||
info->ram->total >> 10);
|
||||
}
|
||||
|
||||
if (info->has_disk) {
|
||||
monitor_printf(mon, "transferred disk: %" PRIu64 " kbytes\n",
|
||||
info->disk->transferred >> 10);
|
||||
monitor_printf(mon, "remaining disk: %" PRIu64 " kbytes\n",
|
||||
info->disk->remaining >> 10);
|
||||
monitor_printf(mon, "total disk: %" PRIu64 " kbytes\n",
|
||||
info->disk->total >> 10);
|
||||
}
|
||||
|
||||
qapi_free_MigrationInfo(info);
|
||||
}
|
||||
|
||||
void hmp_info_cpus(Monitor *mon)
|
||||
{
|
||||
CpuInfoList *cpu_list, *cpu;
|
||||
|
||||
cpu_list = qmp_query_cpus(NULL);
|
||||
|
||||
for (cpu = cpu_list; cpu; cpu = cpu->next) {
|
||||
int active = ' ';
|
||||
|
||||
if (cpu->value->CPU == monitor_get_cpu_index()) {
|
||||
active = '*';
|
||||
}
|
||||
|
||||
monitor_printf(mon, "%c CPU #%" PRId64 ": ", active, cpu->value->CPU);
|
||||
|
||||
if (cpu->value->has_pc) {
|
||||
monitor_printf(mon, "pc=0x%016" PRIx64, cpu->value->pc);
|
||||
}
|
||||
if (cpu->value->has_nip) {
|
||||
monitor_printf(mon, "nip=0x%016" PRIx64, cpu->value->nip);
|
||||
}
|
||||
if (cpu->value->has_npc) {
|
||||
monitor_printf(mon, "pc=0x%016" PRIx64, cpu->value->pc);
|
||||
monitor_printf(mon, "npc=0x%016" PRIx64, cpu->value->npc);
|
||||
}
|
||||
if (cpu->value->has_PC) {
|
||||
monitor_printf(mon, "PC=0x%016" PRIx64, cpu->value->PC);
|
||||
}
|
||||
|
||||
if (cpu->value->halted) {
|
||||
monitor_printf(mon, " (halted)");
|
||||
}
|
||||
|
||||
monitor_printf(mon, " thread_id=%" PRId64 "\n", cpu->value->thread_id);
|
||||
}
|
||||
|
||||
qapi_free_CpuInfoList(cpu_list);
|
||||
}
|
||||
|
||||
void hmp_info_block(Monitor *mon)
|
||||
{
|
||||
BlockInfoList *block_list, *info;
|
||||
|
||||
block_list = qmp_query_block(NULL);
|
||||
|
||||
for (info = block_list; info; info = info->next) {
|
||||
monitor_printf(mon, "%s: removable=%d",
|
||||
info->value->device, info->value->removable);
|
||||
|
||||
if (info->value->removable) {
|
||||
monitor_printf(mon, " locked=%d", info->value->locked);
|
||||
monitor_printf(mon, " tray-open=%d", info->value->tray_open);
|
||||
}
|
||||
|
||||
if (info->value->has_io_status) {
|
||||
monitor_printf(mon, " io-status=%s",
|
||||
BlockDeviceIoStatus_lookup[info->value->io_status]);
|
||||
}
|
||||
|
||||
if (info->value->has_inserted) {
|
||||
monitor_printf(mon, " file=");
|
||||
monitor_print_filename(mon, info->value->inserted->file);
|
||||
|
||||
if (info->value->inserted->has_backing_file) {
|
||||
monitor_printf(mon, " backing_file=");
|
||||
monitor_print_filename(mon, info->value->inserted->backing_file);
|
||||
}
|
||||
monitor_printf(mon, " ro=%d drv=%s encrypted=%d",
|
||||
info->value->inserted->ro,
|
||||
info->value->inserted->drv,
|
||||
info->value->inserted->encrypted);
|
||||
} else {
|
||||
monitor_printf(mon, " [not inserted]");
|
||||
}
|
||||
|
||||
monitor_printf(mon, "\n");
|
||||
}
|
||||
|
||||
qapi_free_BlockInfoList(block_list);
|
||||
}
|
||||
|
||||
void hmp_info_blockstats(Monitor *mon)
|
||||
{
|
||||
BlockStatsList *stats_list, *stats;
|
||||
|
||||
stats_list = qmp_query_blockstats(NULL);
|
||||
|
||||
for (stats = stats_list; stats; stats = stats->next) {
|
||||
if (!stats->value->has_device) {
|
||||
continue;
|
||||
}
|
||||
|
||||
monitor_printf(mon, "%s:", stats->value->device);
|
||||
monitor_printf(mon, " rd_bytes=%" PRId64
|
||||
" wr_bytes=%" PRId64
|
||||
" rd_operations=%" PRId64
|
||||
" wr_operations=%" PRId64
|
||||
" flush_operations=%" PRId64
|
||||
" wr_total_time_ns=%" PRId64
|
||||
" rd_total_time_ns=%" PRId64
|
||||
" flush_total_time_ns=%" PRId64
|
||||
"\n",
|
||||
stats->value->stats->rd_bytes,
|
||||
stats->value->stats->wr_bytes,
|
||||
stats->value->stats->rd_operations,
|
||||
stats->value->stats->wr_operations,
|
||||
stats->value->stats->flush_operations,
|
||||
stats->value->stats->wr_total_time_ns,
|
||||
stats->value->stats->rd_total_time_ns,
|
||||
stats->value->stats->flush_total_time_ns);
|
||||
}
|
||||
|
||||
qapi_free_BlockStatsList(stats_list);
|
||||
}
|
||||
|
||||
void hmp_info_vnc(Monitor *mon)
|
||||
{
|
||||
VncInfo *info;
|
||||
Error *err = NULL;
|
||||
VncClientInfoList *client;
|
||||
|
||||
info = qmp_query_vnc(&err);
|
||||
if (err) {
|
||||
monitor_printf(mon, "%s\n", error_get_pretty(err));
|
||||
error_free(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info->enabled) {
|
||||
monitor_printf(mon, "Server: disabled\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
monitor_printf(mon, "Server:\n");
|
||||
if (info->has_host && info->has_service) {
|
||||
monitor_printf(mon, " address: %s:%s\n", info->host, info->service);
|
||||
}
|
||||
if (info->has_auth) {
|
||||
monitor_printf(mon, " auth: %s\n", info->auth);
|
||||
}
|
||||
|
||||
if (!info->has_clients || info->clients == NULL) {
|
||||
monitor_printf(mon, "Client: none\n");
|
||||
} else {
|
||||
for (client = info->clients; client; client = client->next) {
|
||||
monitor_printf(mon, "Client:\n");
|
||||
monitor_printf(mon, " address: %s:%s\n",
|
||||
client->value->host, client->value->service);
|
||||
monitor_printf(mon, " x509_dname: %s\n",
|
||||
client->value->x509_dname ?
|
||||
client->value->x509_dname : "none");
|
||||
monitor_printf(mon, " username: %s\n",
|
||||
client->value->has_sasl_username ?
|
||||
client->value->sasl_username : "none");
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
qapi_free_VncInfo(info);
|
||||
}
|
||||
|
||||
void hmp_info_spice(Monitor *mon)
|
||||
{
|
||||
SpiceChannelList *chan;
|
||||
SpiceInfo *info;
|
||||
|
||||
info = qmp_query_spice(NULL);
|
||||
|
||||
if (!info->enabled) {
|
||||
monitor_printf(mon, "Server: disabled\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
monitor_printf(mon, "Server:\n");
|
||||
if (info->has_port) {
|
||||
monitor_printf(mon, " address: %s:%" PRId64 "\n",
|
||||
info->host, info->port);
|
||||
}
|
||||
if (info->has_tls_port) {
|
||||
monitor_printf(mon, " address: %s:%" PRId64 " [tls]\n",
|
||||
info->host, info->tls_port);
|
||||
}
|
||||
monitor_printf(mon, " auth: %s\n", info->auth);
|
||||
monitor_printf(mon, " compiled: %s\n", info->compiled_version);
|
||||
|
||||
if (!info->has_channels || info->channels == NULL) {
|
||||
monitor_printf(mon, "Channels: none\n");
|
||||
} else {
|
||||
for (chan = info->channels; chan; chan = chan->next) {
|
||||
monitor_printf(mon, "Channel:\n");
|
||||
monitor_printf(mon, " address: %s:%s%s\n",
|
||||
chan->value->host, chan->value->port,
|
||||
chan->value->tls ? " [tls]" : "");
|
||||
monitor_printf(mon, " session: %" PRId64 "\n",
|
||||
chan->value->connection_id);
|
||||
monitor_printf(mon, " channel: %" PRId64 ":%" PRId64 "\n",
|
||||
chan->value->channel_type, chan->value->channel_id);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
qapi_free_SpiceInfo(info);
|
||||
}
|
||||
|
||||
void hmp_info_balloon(Monitor *mon)
|
||||
{
|
||||
BalloonInfo *info;
|
||||
Error *err = NULL;
|
||||
|
||||
info = qmp_query_balloon(&err);
|
||||
if (err) {
|
||||
monitor_printf(mon, "%s\n", error_get_pretty(err));
|
||||
error_free(err);
|
||||
return;
|
||||
}
|
||||
|
||||
monitor_printf(mon, "balloon: actual=%" PRId64, info->actual >> 20);
|
||||
if (info->has_mem_swapped_in) {
|
||||
monitor_printf(mon, " mem_swapped_in=%" PRId64, info->mem_swapped_in);
|
||||
}
|
||||
if (info->has_mem_swapped_out) {
|
||||
monitor_printf(mon, " mem_swapped_out=%" PRId64, info->mem_swapped_out);
|
||||
}
|
||||
if (info->has_major_page_faults) {
|
||||
monitor_printf(mon, " major_page_faults=%" PRId64,
|
||||
info->major_page_faults);
|
||||
}
|
||||
if (info->has_minor_page_faults) {
|
||||
monitor_printf(mon, " minor_page_faults=%" PRId64,
|
||||
info->minor_page_faults);
|
||||
}
|
||||
if (info->has_free_mem) {
|
||||
monitor_printf(mon, " free_mem=%" PRId64, info->free_mem);
|
||||
}
|
||||
if (info->has_total_mem) {
|
||||
monitor_printf(mon, " total_mem=%" PRId64, info->total_mem);
|
||||
}
|
||||
|
||||
monitor_printf(mon, "\n");
|
||||
|
||||
qapi_free_BalloonInfo(info);
|
||||
}
|
||||
|
||||
static void hmp_info_pci_device(Monitor *mon, const PciDeviceInfo *dev)
|
||||
{
|
||||
PciMemoryRegionList *region;
|
||||
|
||||
monitor_printf(mon, " Bus %2" PRId64 ", ", dev->bus);
|
||||
monitor_printf(mon, "device %3" PRId64 ", function %" PRId64 ":\n",
|
||||
dev->slot, dev->function);
|
||||
monitor_printf(mon, " ");
|
||||
|
||||
if (dev->class_info.has_desc) {
|
||||
monitor_printf(mon, "%s", dev->class_info.desc);
|
||||
} else {
|
||||
monitor_printf(mon, "Class %04" PRId64, dev->class_info.class);
|
||||
}
|
||||
|
||||
monitor_printf(mon, ": PCI device %04" PRIx64 ":%04" PRIx64 "\n",
|
||||
dev->id.vendor, dev->id.device);
|
||||
|
||||
if (dev->has_irq) {
|
||||
monitor_printf(mon, " IRQ %" PRId64 ".\n", dev->irq);
|
||||
}
|
||||
|
||||
if (dev->has_pci_bridge) {
|
||||
monitor_printf(mon, " BUS %" PRId64 ".\n",
|
||||
dev->pci_bridge->bus.number);
|
||||
monitor_printf(mon, " secondary bus %" PRId64 ".\n",
|
||||
dev->pci_bridge->bus.secondary);
|
||||
monitor_printf(mon, " subordinate bus %" PRId64 ".\n",
|
||||
dev->pci_bridge->bus.subordinate);
|
||||
|
||||
monitor_printf(mon, " IO range [0x%04"PRIx64", 0x%04"PRIx64"]\n",
|
||||
dev->pci_bridge->bus.io_range->base,
|
||||
dev->pci_bridge->bus.io_range->limit);
|
||||
|
||||
monitor_printf(mon,
|
||||
" memory range [0x%08"PRIx64", 0x%08"PRIx64"]\n",
|
||||
dev->pci_bridge->bus.memory_range->base,
|
||||
dev->pci_bridge->bus.memory_range->limit);
|
||||
|
||||
monitor_printf(mon, " prefetchable memory range "
|
||||
"[0x%08"PRIx64", 0x%08"PRIx64"]\n",
|
||||
dev->pci_bridge->bus.prefetchable_range->base,
|
||||
dev->pci_bridge->bus.prefetchable_range->limit);
|
||||
}
|
||||
|
||||
for (region = dev->regions; region; region = region->next) {
|
||||
uint64_t addr, size;
|
||||
|
||||
addr = region->value->address;
|
||||
size = region->value->size;
|
||||
|
||||
monitor_printf(mon, " BAR%" PRId64 ": ", region->value->bar);
|
||||
|
||||
if (!strcmp(region->value->type, "io")) {
|
||||
monitor_printf(mon, "I/O at 0x%04" PRIx64
|
||||
" [0x%04" PRIx64 "].\n",
|
||||
addr, addr + size - 1);
|
||||
} else {
|
||||
monitor_printf(mon, "%d bit%s memory at 0x%08" PRIx64
|
||||
" [0x%08" PRIx64 "].\n",
|
||||
region->value->mem_type_64 ? 64 : 32,
|
||||
region->value->prefetch ? " prefetchable" : "",
|
||||
addr, addr + size - 1);
|
||||
}
|
||||
}
|
||||
|
||||
monitor_printf(mon, " id \"%s\"\n", dev->qdev_id);
|
||||
|
||||
if (dev->has_pci_bridge) {
|
||||
if (dev->pci_bridge->has_devices) {
|
||||
PciDeviceInfoList *cdev;
|
||||
for (cdev = dev->pci_bridge->devices; cdev; cdev = cdev->next) {
|
||||
hmp_info_pci_device(mon, cdev->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hmp_info_pci(Monitor *mon)
|
||||
{
|
||||
PciInfoList *info;
|
||||
Error *err = NULL;
|
||||
|
||||
info = qmp_query_pci(&err);
|
||||
if (err) {
|
||||
monitor_printf(mon, "PCI devices not supported\n");
|
||||
error_free(err);
|
||||
return;
|
||||
}
|
||||
|
||||
for (; info; info = info->next) {
|
||||
PciDeviceInfoList *dev;
|
||||
|
||||
for (dev = info->value->devices; dev; dev = dev->next) {
|
||||
hmp_info_pci_device(mon, dev->value);
|
||||
}
|
||||
}
|
||||
|
||||
qapi_free_PciInfoList(info);
|
||||
}
|
||||
|
||||
void hmp_quit(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
monitor_suspend(mon);
|
||||
@@ -114,3 +509,15 @@ void hmp_system_powerdown(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
qmp_system_powerdown(NULL);
|
||||
}
|
||||
|
||||
void hmp_cpu(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
int64_t cpu_index;
|
||||
|
||||
/* XXX: drop the monitor_set_cpu() usage when all HMP commands that
|
||||
use it are converted to the QAPI */
|
||||
cpu_index = qdict_get_int(qdict, "index");
|
||||
if (monitor_set_cpu(cpu_index) < 0) {
|
||||
monitor_printf(mon, "invalid CPU index\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,19 @@ void hmp_info_kvm(Monitor *mon);
|
||||
void hmp_info_status(Monitor *mon);
|
||||
void hmp_info_uuid(Monitor *mon);
|
||||
void hmp_info_chardev(Monitor *mon);
|
||||
void hmp_info_mice(Monitor *mon);
|
||||
void hmp_info_migrate(Monitor *mon);
|
||||
void hmp_info_cpus(Monitor *mon);
|
||||
void hmp_info_block(Monitor *mon);
|
||||
void hmp_info_blockstats(Monitor *mon);
|
||||
void hmp_info_vnc(Monitor *mon);
|
||||
void hmp_info_spice(Monitor *mon);
|
||||
void hmp_info_balloon(Monitor *mon);
|
||||
void hmp_info_pci(Monitor *mon);
|
||||
void hmp_quit(Monitor *mon, const QDict *qdict);
|
||||
void hmp_stop(Monitor *mon, const QDict *qdict);
|
||||
void hmp_system_reset(Monitor *mon, const QDict *qdict);
|
||||
void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
|
||||
void hmp_cpu(Monitor *mon, const QDict *qdict);
|
||||
|
||||
#endif
|
||||
|
||||
+7
-10
@@ -21,22 +21,19 @@
|
||||
#include "sysemu.h"
|
||||
#include "monitor.h"
|
||||
#include "pci.h"
|
||||
#include "qmp-commands.h"
|
||||
|
||||
PciInfoList *qmp_query_pci(Error **errp)
|
||||
{
|
||||
error_set(errp, QERR_UNSUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void pci_error_message(Monitor *mon)
|
||||
{
|
||||
monitor_printf(mon, "PCI devices not supported\n");
|
||||
}
|
||||
|
||||
void do_pci_info(Monitor *mon, QObject **ret_data)
|
||||
{
|
||||
pci_error_message(mon);
|
||||
}
|
||||
|
||||
void do_pci_info_print(Monitor *mon, const QObject *data)
|
||||
{
|
||||
pci_error_message(mon);
|
||||
}
|
||||
|
||||
int do_pcie_aer_inejct_error(Monitor *mon,
|
||||
const QDict *qdict, QObject **ret_data)
|
||||
{
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
#include "net.h"
|
||||
#include "sysemu.h"
|
||||
#include "loader.h"
|
||||
#include "qemu-objects.h"
|
||||
#include "range.h"
|
||||
#include "qmp-commands.h"
|
||||
|
||||
//#define DEBUG_PCI
|
||||
#ifdef DEBUG_PCI
|
||||
@@ -1164,276 +1164,194 @@ void pci_for_each_device(PCIBus *bus, int bus_num,
|
||||
}
|
||||
}
|
||||
|
||||
static void pci_device_print(Monitor *mon, QDict *device)
|
||||
static const pci_class_desc *get_class_desc(int class)
|
||||
{
|
||||
QDict *qdict;
|
||||
QListEntry *entry;
|
||||
uint64_t addr, size;
|
||||
|
||||
monitor_printf(mon, " Bus %2" PRId64 ", ", qdict_get_int(device, "bus"));
|
||||
monitor_printf(mon, "device %3" PRId64 ", function %" PRId64 ":\n",
|
||||
qdict_get_int(device, "slot"),
|
||||
qdict_get_int(device, "function"));
|
||||
monitor_printf(mon, " ");
|
||||
|
||||
qdict = qdict_get_qdict(device, "class_info");
|
||||
if (qdict_haskey(qdict, "desc")) {
|
||||
monitor_printf(mon, "%s", qdict_get_str(qdict, "desc"));
|
||||
} else {
|
||||
monitor_printf(mon, "Class %04" PRId64, qdict_get_int(qdict, "class"));
|
||||
}
|
||||
|
||||
qdict = qdict_get_qdict(device, "id");
|
||||
monitor_printf(mon, ": PCI device %04" PRIx64 ":%04" PRIx64 "\n",
|
||||
qdict_get_int(qdict, "device"),
|
||||
qdict_get_int(qdict, "vendor"));
|
||||
|
||||
if (qdict_haskey(device, "irq")) {
|
||||
monitor_printf(mon, " IRQ %" PRId64 ".\n",
|
||||
qdict_get_int(device, "irq"));
|
||||
}
|
||||
|
||||
if (qdict_haskey(device, "pci_bridge")) {
|
||||
QDict *info;
|
||||
|
||||
qdict = qdict_get_qdict(device, "pci_bridge");
|
||||
|
||||
info = qdict_get_qdict(qdict, "bus");
|
||||
monitor_printf(mon, " BUS %" PRId64 ".\n",
|
||||
qdict_get_int(info, "number"));
|
||||
monitor_printf(mon, " secondary bus %" PRId64 ".\n",
|
||||
qdict_get_int(info, "secondary"));
|
||||
monitor_printf(mon, " subordinate bus %" PRId64 ".\n",
|
||||
qdict_get_int(info, "subordinate"));
|
||||
|
||||
info = qdict_get_qdict(qdict, "io_range");
|
||||
monitor_printf(mon, " IO range [0x%04"PRIx64", 0x%04"PRIx64"]\n",
|
||||
qdict_get_int(info, "base"),
|
||||
qdict_get_int(info, "limit"));
|
||||
|
||||
info = qdict_get_qdict(qdict, "memory_range");
|
||||
monitor_printf(mon,
|
||||
" memory range [0x%08"PRIx64", 0x%08"PRIx64"]\n",
|
||||
qdict_get_int(info, "base"),
|
||||
qdict_get_int(info, "limit"));
|
||||
|
||||
info = qdict_get_qdict(qdict, "prefetchable_range");
|
||||
monitor_printf(mon, " prefetchable memory range "
|
||||
"[0x%08"PRIx64", 0x%08"PRIx64"]\n",
|
||||
qdict_get_int(info, "base"),
|
||||
qdict_get_int(info, "limit"));
|
||||
}
|
||||
|
||||
QLIST_FOREACH_ENTRY(qdict_get_qlist(device, "regions"), entry) {
|
||||
qdict = qobject_to_qdict(qlist_entry_obj(entry));
|
||||
monitor_printf(mon, " BAR%d: ", (int) qdict_get_int(qdict, "bar"));
|
||||
|
||||
addr = qdict_get_int(qdict, "address");
|
||||
size = qdict_get_int(qdict, "size");
|
||||
|
||||
if (!strcmp(qdict_get_str(qdict, "type"), "io")) {
|
||||
monitor_printf(mon, "I/O at 0x%04"FMT_PCIBUS
|
||||
" [0x%04"FMT_PCIBUS"].\n",
|
||||
addr, addr + size - 1);
|
||||
} else {
|
||||
monitor_printf(mon, "%d bit%s memory at 0x%08"FMT_PCIBUS
|
||||
" [0x%08"FMT_PCIBUS"].\n",
|
||||
qdict_get_bool(qdict, "mem_type_64") ? 64 : 32,
|
||||
qdict_get_bool(qdict, "prefetch") ?
|
||||
" prefetchable" : "", addr, addr + size - 1);
|
||||
}
|
||||
}
|
||||
|
||||
monitor_printf(mon, " id \"%s\"\n", qdict_get_str(device, "qdev_id"));
|
||||
|
||||
if (qdict_haskey(device, "pci_bridge")) {
|
||||
qdict = qdict_get_qdict(device, "pci_bridge");
|
||||
if (qdict_haskey(qdict, "devices")) {
|
||||
QListEntry *dev;
|
||||
QLIST_FOREACH_ENTRY(qdict_get_qlist(qdict, "devices"), dev) {
|
||||
pci_device_print(mon, qobject_to_qdict(qlist_entry_obj(dev)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void do_pci_info_print(Monitor *mon, const QObject *data)
|
||||
{
|
||||
QListEntry *bus, *dev;
|
||||
|
||||
QLIST_FOREACH_ENTRY(qobject_to_qlist(data), bus) {
|
||||
QDict *qdict = qobject_to_qdict(qlist_entry_obj(bus));
|
||||
QLIST_FOREACH_ENTRY(qdict_get_qlist(qdict, "devices"), dev) {
|
||||
pci_device_print(mon, qobject_to_qdict(qlist_entry_obj(dev)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static QObject *pci_get_dev_class(const PCIDevice *dev)
|
||||
{
|
||||
int class;
|
||||
const pci_class_desc *desc;
|
||||
|
||||
class = pci_get_word(dev->config + PCI_CLASS_DEVICE);
|
||||
desc = pci_class_descriptions;
|
||||
while (desc->desc && class != desc->class)
|
||||
while (desc->desc && class != desc->class) {
|
||||
desc++;
|
||||
|
||||
if (desc->desc) {
|
||||
return qobject_from_jsonf("{ 'desc': %s, 'class': %d }",
|
||||
desc->desc, class);
|
||||
} else {
|
||||
return qobject_from_jsonf("{ 'class': %d }", class);
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
static QObject *pci_get_dev_id(const PCIDevice *dev)
|
||||
{
|
||||
return qobject_from_jsonf("{ 'device': %d, 'vendor': %d }",
|
||||
pci_get_word(dev->config + PCI_VENDOR_ID),
|
||||
pci_get_word(dev->config + PCI_DEVICE_ID));
|
||||
}
|
||||
static PciDeviceInfoList *qmp_query_pci_devices(PCIBus *bus, int bus_num);
|
||||
|
||||
static QObject *pci_get_regions_list(const PCIDevice *dev)
|
||||
static PciMemoryRegionList *qmp_query_pci_regions(const PCIDevice *dev)
|
||||
{
|
||||
PciMemoryRegionList *head = NULL, *cur_item = NULL;
|
||||
int i;
|
||||
QList *regions_list;
|
||||
|
||||
regions_list = qlist_new();
|
||||
|
||||
for (i = 0; i < PCI_NUM_REGIONS; i++) {
|
||||
QObject *obj;
|
||||
const PCIIORegion *r = &dev->io_regions[i];
|
||||
PciMemoryRegionList *region;
|
||||
|
||||
if (!r->size) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
|
||||
obj = qobject_from_jsonf("{ 'bar': %d, 'type': 'io', "
|
||||
"'address': %" PRId64 ", "
|
||||
"'size': %" PRId64 " }",
|
||||
i, r->addr, r->size);
|
||||
} else {
|
||||
int mem_type_64 = r->type & PCI_BASE_ADDRESS_MEM_TYPE_64;
|
||||
region = g_malloc0(sizeof(*region));
|
||||
region->value = g_malloc0(sizeof(*region->value));
|
||||
|
||||
obj = qobject_from_jsonf("{ 'bar': %d, 'type': 'memory', "
|
||||
"'mem_type_64': %i, 'prefetch': %i, "
|
||||
"'address': %" PRId64 ", "
|
||||
"'size': %" PRId64 " }",
|
||||
i, mem_type_64,
|
||||
r->type & PCI_BASE_ADDRESS_MEM_PREFETCH,
|
||||
r->addr, r->size);
|
||||
if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
|
||||
region->value->type = g_strdup("io");
|
||||
} else {
|
||||
region->value->type = g_strdup("memory");
|
||||
region->value->has_prefetch = true;
|
||||
region->value->prefetch = !!(r->type & PCI_BASE_ADDRESS_MEM_PREFETCH);
|
||||
region->value->has_mem_type_64 = true;
|
||||
region->value->mem_type_64 = !!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64);
|
||||
}
|
||||
|
||||
qlist_append_obj(regions_list, obj);
|
||||
region->value->bar = i;
|
||||
region->value->address = r->addr;
|
||||
region->value->size = r->size;
|
||||
|
||||
/* XXX: waiting for the qapi to support GSList */
|
||||
if (!cur_item) {
|
||||
head = cur_item = region;
|
||||
} else {
|
||||
cur_item->next = region;
|
||||
cur_item = region;
|
||||
}
|
||||
}
|
||||
|
||||
return QOBJECT(regions_list);
|
||||
return head;
|
||||
}
|
||||
|
||||
static QObject *pci_get_devices_list(PCIBus *bus, int bus_num);
|
||||
|
||||
static QObject *pci_get_dev_dict(PCIDevice *dev, PCIBus *bus, int bus_num)
|
||||
static PciBridgeInfo *qmp_query_pci_bridge(PCIDevice *dev, PCIBus *bus,
|
||||
int bus_num)
|
||||
{
|
||||
uint8_t type;
|
||||
QObject *obj;
|
||||
PciBridgeInfo *info;
|
||||
|
||||
obj = qobject_from_jsonf("{ 'bus': %d, 'slot': %d, 'function': %d," "'class_info': %p, 'id': %p, 'regions': %p,"
|
||||
" 'qdev_id': %s }",
|
||||
bus_num,
|
||||
PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
|
||||
pci_get_dev_class(dev), pci_get_dev_id(dev),
|
||||
pci_get_regions_list(dev),
|
||||
dev->qdev.id ? dev->qdev.id : "");
|
||||
info = g_malloc0(sizeof(*info));
|
||||
|
||||
info->bus.number = dev->config[PCI_PRIMARY_BUS];
|
||||
info->bus.secondary = dev->config[PCI_SECONDARY_BUS];
|
||||
info->bus.subordinate = dev->config[PCI_SUBORDINATE_BUS];
|
||||
|
||||
info->bus.io_range = g_malloc0(sizeof(*info->bus.io_range));
|
||||
info->bus.io_range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO);
|
||||
info->bus.io_range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO);
|
||||
|
||||
info->bus.memory_range = g_malloc0(sizeof(*info->bus.memory_range));
|
||||
info->bus.memory_range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
|
||||
info->bus.memory_range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
|
||||
|
||||
info->bus.prefetchable_range = g_malloc0(sizeof(*info->bus.prefetchable_range));
|
||||
info->bus.prefetchable_range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
|
||||
info->bus.prefetchable_range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
|
||||
|
||||
if (dev->config[PCI_SECONDARY_BUS] != 0) {
|
||||
PCIBus *child_bus = pci_find_bus(bus, dev->config[PCI_SECONDARY_BUS]);
|
||||
if (child_bus) {
|
||||
info->has_devices = true;
|
||||
info->devices = qmp_query_pci_devices(child_bus, dev->config[PCI_SECONDARY_BUS]);
|
||||
}
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static PciDeviceInfo *qmp_query_pci_device(PCIDevice *dev, PCIBus *bus,
|
||||
int bus_num)
|
||||
{
|
||||
const pci_class_desc *desc;
|
||||
PciDeviceInfo *info;
|
||||
uint8_t type;
|
||||
int class;
|
||||
|
||||
info = g_malloc0(sizeof(*info));
|
||||
info->bus = bus_num;
|
||||
info->slot = PCI_SLOT(dev->devfn);
|
||||
info->function = PCI_FUNC(dev->devfn);
|
||||
|
||||
class = pci_get_word(dev->config + PCI_CLASS_DEVICE);
|
||||
info->class_info.class = class;
|
||||
desc = get_class_desc(class);
|
||||
if (desc->desc) {
|
||||
info->class_info.has_desc = true;
|
||||
info->class_info.desc = g_strdup(desc->desc);
|
||||
}
|
||||
|
||||
info->id.vendor = pci_get_word(dev->config + PCI_VENDOR_ID);
|
||||
info->id.device = pci_get_word(dev->config + PCI_DEVICE_ID);
|
||||
info->regions = qmp_query_pci_regions(dev);
|
||||
info->qdev_id = g_strdup(dev->qdev.id ? dev->qdev.id : "");
|
||||
|
||||
if (dev->config[PCI_INTERRUPT_PIN] != 0) {
|
||||
QDict *qdict = qobject_to_qdict(obj);
|
||||
qdict_put(qdict, "irq", qint_from_int(dev->config[PCI_INTERRUPT_LINE]));
|
||||
info->has_irq = true;
|
||||
info->irq = dev->config[PCI_INTERRUPT_LINE];
|
||||
}
|
||||
|
||||
type = dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
|
||||
if (type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
QDict *qdict;
|
||||
QObject *pci_bridge;
|
||||
|
||||
pci_bridge = qobject_from_jsonf("{ 'bus': "
|
||||
"{ 'number': %d, 'secondary': %d, 'subordinate': %d }, "
|
||||
"'io_range': { 'base': %" PRId64 ", 'limit': %" PRId64 "}, "
|
||||
"'memory_range': { 'base': %" PRId64 ", 'limit': %" PRId64 "}, "
|
||||
"'prefetchable_range': { 'base': %" PRId64 ", 'limit': %" PRId64 "} }",
|
||||
dev->config[PCI_PRIMARY_BUS], dev->config[PCI_SECONDARY_BUS],
|
||||
dev->config[PCI_SUBORDINATE_BUS],
|
||||
pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO),
|
||||
pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO),
|
||||
pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY),
|
||||
pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY),
|
||||
pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY |
|
||||
PCI_BASE_ADDRESS_MEM_PREFETCH),
|
||||
pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY |
|
||||
PCI_BASE_ADDRESS_MEM_PREFETCH));
|
||||
|
||||
if (dev->config[PCI_SECONDARY_BUS] != 0) {
|
||||
PCIBus *child_bus = pci_find_bus(bus, dev->config[PCI_SECONDARY_BUS]);
|
||||
|
||||
if (child_bus) {
|
||||
qdict = qobject_to_qdict(pci_bridge);
|
||||
qdict_put_obj(qdict, "devices",
|
||||
pci_get_devices_list(child_bus,
|
||||
dev->config[PCI_SECONDARY_BUS]));
|
||||
}
|
||||
}
|
||||
qdict = qobject_to_qdict(obj);
|
||||
qdict_put_obj(qdict, "pci_bridge", pci_bridge);
|
||||
info->has_pci_bridge = true;
|
||||
info->pci_bridge = qmp_query_pci_bridge(dev, bus, bus_num);
|
||||
}
|
||||
|
||||
return obj;
|
||||
return info;
|
||||
}
|
||||
|
||||
static QObject *pci_get_devices_list(PCIBus *bus, int bus_num)
|
||||
static PciDeviceInfoList *qmp_query_pci_devices(PCIBus *bus, int bus_num)
|
||||
{
|
||||
int devfn;
|
||||
PciDeviceInfoList *info, *head = NULL, *cur_item = NULL;
|
||||
PCIDevice *dev;
|
||||
QList *dev_list;
|
||||
|
||||
dev_list = qlist_new();
|
||||
int devfn;
|
||||
|
||||
for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {
|
||||
dev = bus->devices[devfn];
|
||||
if (dev) {
|
||||
qlist_append_obj(dev_list, pci_get_dev_dict(dev, bus, bus_num));
|
||||
info = g_malloc0(sizeof(*info));
|
||||
info->value = qmp_query_pci_device(dev, bus, bus_num);
|
||||
|
||||
/* XXX: waiting for the qapi to support GSList */
|
||||
if (!cur_item) {
|
||||
head = cur_item = info;
|
||||
} else {
|
||||
cur_item->next = info;
|
||||
cur_item = info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QOBJECT(dev_list);
|
||||
return head;
|
||||
}
|
||||
|
||||
static QObject *pci_get_bus_dict(PCIBus *bus, int bus_num)
|
||||
static PciInfo *qmp_query_pci_bus(PCIBus *bus, int bus_num)
|
||||
{
|
||||
PciInfo *info = NULL;
|
||||
|
||||
bus = pci_find_bus(bus, bus_num);
|
||||
if (bus) {
|
||||
return qobject_from_jsonf("{ 'bus': %d, 'devices': %p }",
|
||||
bus_num, pci_get_devices_list(bus, bus_num));
|
||||
info = g_malloc0(sizeof(*info));
|
||||
info->bus = bus_num;
|
||||
info->devices = qmp_query_pci_devices(bus, bus_num);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return info;
|
||||
}
|
||||
|
||||
void do_pci_info(Monitor *mon, QObject **ret_data)
|
||||
PciInfoList *qmp_query_pci(Error **errp)
|
||||
{
|
||||
QList *bus_list;
|
||||
PciInfoList *info, *head = NULL, *cur_item = NULL;
|
||||
struct PCIHostBus *host;
|
||||
|
||||
bus_list = qlist_new();
|
||||
|
||||
QLIST_FOREACH(host, &host_buses, next) {
|
||||
QObject *obj = pci_get_bus_dict(host->bus, 0);
|
||||
if (obj) {
|
||||
qlist_append_obj(bus_list, obj);
|
||||
info = g_malloc0(sizeof(*info));
|
||||
info->value = qmp_query_pci_bus(host->bus, 0);
|
||||
|
||||
/* XXX: waiting for the qapi to support GSList */
|
||||
if (!cur_item) {
|
||||
head = cur_item = info;
|
||||
} else {
|
||||
cur_item->next = info;
|
||||
cur_item = info;
|
||||
}
|
||||
}
|
||||
|
||||
*ret_data = QOBJECT(bus_list);
|
||||
return head;
|
||||
}
|
||||
|
||||
static const char * const pci_nic_models[] = {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#define QEMU_PCI_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qobject.h"
|
||||
|
||||
#include "qdev.h"
|
||||
#include "memory.h"
|
||||
@@ -271,9 +270,6 @@ int pci_parse_devaddr(const char *addr, int *domp, int *busp,
|
||||
int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
|
||||
unsigned *slotp);
|
||||
|
||||
void do_pci_info_print(Monitor *mon, const QObject *data);
|
||||
void do_pci_info(Monitor *mon, QObject **ret_data);
|
||||
|
||||
void pci_device_deassert_intx(PCIDevice *dev);
|
||||
|
||||
static inline void
|
||||
|
||||
+14
-64
@@ -18,22 +18,14 @@
|
||||
#include "virtio.h"
|
||||
#include "pc.h"
|
||||
#include "cpu.h"
|
||||
#include "monitor.h"
|
||||
#include "balloon.h"
|
||||
#include "virtio-balloon.h"
|
||||
#include "kvm.h"
|
||||
#include "qlist.h"
|
||||
#include "qint.h"
|
||||
#include "qstring.h"
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
/* Disable guest-provided stats by now (https://bugzilla.redhat.com/show_bug.cgi?id=623903) */
|
||||
#define ENABLE_GUEST_STATS 0
|
||||
|
||||
|
||||
typedef struct VirtIOBalloon
|
||||
{
|
||||
VirtIODevice vdev;
|
||||
@@ -43,8 +35,6 @@ typedef struct VirtIOBalloon
|
||||
uint64_t stats[VIRTIO_BALLOON_S_NR];
|
||||
VirtQueueElement stats_vq_elem;
|
||||
size_t stats_vq_offset;
|
||||
MonitorCompletion *stats_callback;
|
||||
void *stats_opaque_callback_data;
|
||||
DeviceState *qdev;
|
||||
} VirtIOBalloon;
|
||||
|
||||
@@ -76,31 +66,6 @@ static inline void reset_stats(VirtIOBalloon *dev)
|
||||
for (i = 0; i < VIRTIO_BALLOON_S_NR; dev->stats[i++] = -1);
|
||||
}
|
||||
|
||||
static void stat_put(QDict *dict, const char *label, uint64_t val)
|
||||
{
|
||||
if (val != -1)
|
||||
qdict_put(dict, label, qint_from_int(val));
|
||||
}
|
||||
|
||||
static QObject *get_stats_qobject(VirtIOBalloon *dev)
|
||||
{
|
||||
QDict *dict = qdict_new();
|
||||
uint64_t actual = ram_size - ((uint64_t) dev->actual <<
|
||||
VIRTIO_BALLOON_PFN_SHIFT);
|
||||
|
||||
stat_put(dict, "actual", actual);
|
||||
#if ENABLE_GUEST_STATS
|
||||
stat_put(dict, "mem_swapped_in", dev->stats[VIRTIO_BALLOON_S_SWAP_IN]);
|
||||
stat_put(dict, "mem_swapped_out", dev->stats[VIRTIO_BALLOON_S_SWAP_OUT]);
|
||||
stat_put(dict, "major_page_faults", dev->stats[VIRTIO_BALLOON_S_MAJFLT]);
|
||||
stat_put(dict, "minor_page_faults", dev->stats[VIRTIO_BALLOON_S_MINFLT]);
|
||||
stat_put(dict, "free_mem", dev->stats[VIRTIO_BALLOON_S_MEMFREE]);
|
||||
stat_put(dict, "total_mem", dev->stats[VIRTIO_BALLOON_S_MEMTOT]);
|
||||
#endif
|
||||
|
||||
return QOBJECT(dict);
|
||||
}
|
||||
|
||||
static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
VirtIOBalloon *s = to_virtio_balloon(vdev);
|
||||
@@ -131,20 +96,6 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
}
|
||||
}
|
||||
|
||||
static void complete_stats_request(VirtIOBalloon *vb)
|
||||
{
|
||||
QObject *stats;
|
||||
|
||||
if (!vb->stats_opaque_callback_data)
|
||||
return;
|
||||
|
||||
stats = get_stats_qobject(vb);
|
||||
vb->stats_callback(vb->stats_opaque_callback_data, stats);
|
||||
qobject_decref(stats);
|
||||
vb->stats_opaque_callback_data = NULL;
|
||||
vb->stats_callback = NULL;
|
||||
}
|
||||
|
||||
static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
VirtIOBalloon *s = DO_UPCAST(VirtIOBalloon, vdev, vdev);
|
||||
@@ -172,8 +123,6 @@ static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
|
||||
s->stats[tag] = val;
|
||||
}
|
||||
s->stats_vq_offset = offset;
|
||||
|
||||
complete_stats_request(s);
|
||||
}
|
||||
|
||||
static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
|
||||
@@ -202,32 +151,33 @@ static uint32_t virtio_balloon_get_features(VirtIODevice *vdev, uint32_t f)
|
||||
return f;
|
||||
}
|
||||
|
||||
static void virtio_balloon_stat(void *opaque, MonitorCompletion cb,
|
||||
void *cb_data)
|
||||
static void virtio_balloon_stat(void *opaque, BalloonInfo *info)
|
||||
{
|
||||
VirtIOBalloon *dev = opaque;
|
||||
|
||||
/* For now, only allow one request at a time. This restriction can be
|
||||
* removed later by queueing callback and data pairs.
|
||||
#if 0
|
||||
/* Disable guest-provided stats for now. For more details please check:
|
||||
* https://bugzilla.redhat.com/show_bug.cgi?id=623903
|
||||
*
|
||||
* If you do enable it (which is probably not going to happen as we
|
||||
* need a new command for it), remember that you also need to fill the
|
||||
* appropriate members of the BalloonInfo structure so that the stats
|
||||
* are returned to the client.
|
||||
*/
|
||||
if (dev->stats_callback != NULL) {
|
||||
return;
|
||||
}
|
||||
dev->stats_callback = cb;
|
||||
dev->stats_opaque_callback_data = cb_data;
|
||||
|
||||
if (ENABLE_GUEST_STATS
|
||||
&& (dev->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ))) {
|
||||
if (dev->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ)) {
|
||||
virtqueue_push(dev->svq, &dev->stats_vq_elem, dev->stats_vq_offset);
|
||||
virtio_notify(&dev->vdev, dev->svq);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Stats are not supported. Clear out any stale values that might
|
||||
* have been set by a more featureful guest kernel.
|
||||
*/
|
||||
reset_stats(dev);
|
||||
complete_stats_request(dev);
|
||||
|
||||
info->actual = ram_size - ((uint64_t) dev->actual <<
|
||||
VIRTIO_BALLOON_PFN_SHIFT);
|
||||
}
|
||||
|
||||
static void virtio_balloon_to_target(void *opaque, ram_addr_t target)
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
#include "net.h"
|
||||
#include "monitor.h"
|
||||
#include "console.h"
|
||||
#include "qjson.h"
|
||||
#include "error.h"
|
||||
#include "qmp-commands.h"
|
||||
|
||||
static QEMUPutKBDEvent *qemu_put_kbd_event;
|
||||
static void *qemu_put_kbd_event_opaque;
|
||||
@@ -211,60 +212,27 @@ int kbd_mouse_has_absolute(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void info_mice_iter(QObject *data, void *opaque)
|
||||
{
|
||||
QDict *mouse;
|
||||
Monitor *mon = opaque;
|
||||
|
||||
mouse = qobject_to_qdict(data);
|
||||
monitor_printf(mon, "%c Mouse #%" PRId64 ": %s%s\n",
|
||||
(qdict_get_bool(mouse, "current") ? '*' : ' '),
|
||||
qdict_get_int(mouse, "index"), qdict_get_str(mouse, "name"),
|
||||
qdict_get_bool(mouse, "absolute") ? " (absolute)" : "");
|
||||
}
|
||||
|
||||
void do_info_mice_print(Monitor *mon, const QObject *data)
|
||||
{
|
||||
QList *mice_list;
|
||||
|
||||
mice_list = qobject_to_qlist(data);
|
||||
if (qlist_empty(mice_list)) {
|
||||
monitor_printf(mon, "No mouse devices connected\n");
|
||||
return;
|
||||
}
|
||||
|
||||
qlist_iter(mice_list, info_mice_iter, mon);
|
||||
}
|
||||
|
||||
void do_info_mice(Monitor *mon, QObject **ret_data)
|
||||
MouseInfoList *qmp_query_mice(Error **errp)
|
||||
{
|
||||
MouseInfoList *mice_list = NULL;
|
||||
QEMUPutMouseEntry *cursor;
|
||||
QList *mice_list;
|
||||
int current;
|
||||
|
||||
mice_list = qlist_new();
|
||||
|
||||
if (QTAILQ_EMPTY(&mouse_handlers)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
current = QTAILQ_FIRST(&mouse_handlers)->index;
|
||||
bool current = true;
|
||||
|
||||
QTAILQ_FOREACH(cursor, &mouse_handlers, node) {
|
||||
QObject *obj;
|
||||
obj = qobject_from_jsonf("{ 'name': %s,"
|
||||
" 'index': %d,"
|
||||
" 'current': %i,"
|
||||
" 'absolute': %i }",
|
||||
cursor->qemu_put_mouse_event_name,
|
||||
cursor->index,
|
||||
cursor->index == current,
|
||||
!!cursor->qemu_put_mouse_event_absolute);
|
||||
qlist_append_obj(mice_list, obj);
|
||||
MouseInfoList *info = g_malloc0(sizeof(*info));
|
||||
info->value = g_malloc0(sizeof(*info->value));
|
||||
info->value->name = g_strdup(cursor->qemu_put_mouse_event_name);
|
||||
info->value->index = cursor->index;
|
||||
info->value->absolute = !!cursor->qemu_put_mouse_event_absolute;
|
||||
info->value->current = current;
|
||||
|
||||
current = false;
|
||||
|
||||
info->next = mice_list;
|
||||
mice_list = info;
|
||||
}
|
||||
|
||||
out:
|
||||
*ret_data = QOBJECT(mice_list);
|
||||
return mice_list;
|
||||
}
|
||||
|
||||
void do_mouse_set(Monitor *mon, const QDict *qdict)
|
||||
|
||||
+23
-59
@@ -19,7 +19,7 @@
|
||||
#include "block.h"
|
||||
#include "qemu_socket.h"
|
||||
#include "block-migration.h"
|
||||
#include "qemu-objects.h"
|
||||
#include "qmp-commands.h"
|
||||
|
||||
//#define DEBUG_MIGRATION
|
||||
|
||||
@@ -107,53 +107,9 @@ uint64_t migrate_max_downtime(void)
|
||||
return max_downtime;
|
||||
}
|
||||
|
||||
static void migrate_print_status(Monitor *mon, const char *name,
|
||||
const QDict *status_dict)
|
||||
MigrationInfo *qmp_query_migrate(Error **errp)
|
||||
{
|
||||
QDict *qdict;
|
||||
|
||||
qdict = qobject_to_qdict(qdict_get(status_dict, name));
|
||||
|
||||
monitor_printf(mon, "transferred %s: %" PRIu64 " kbytes\n", name,
|
||||
qdict_get_int(qdict, "transferred") >> 10);
|
||||
monitor_printf(mon, "remaining %s: %" PRIu64 " kbytes\n", name,
|
||||
qdict_get_int(qdict, "remaining") >> 10);
|
||||
monitor_printf(mon, "total %s: %" PRIu64 " kbytes\n", name,
|
||||
qdict_get_int(qdict, "total") >> 10);
|
||||
}
|
||||
|
||||
void do_info_migrate_print(Monitor *mon, const QObject *data)
|
||||
{
|
||||
QDict *qdict;
|
||||
|
||||
qdict = qobject_to_qdict(data);
|
||||
|
||||
monitor_printf(mon, "Migration status: %s\n",
|
||||
qdict_get_str(qdict, "status"));
|
||||
|
||||
if (qdict_haskey(qdict, "ram")) {
|
||||
migrate_print_status(mon, "ram", qdict);
|
||||
}
|
||||
|
||||
if (qdict_haskey(qdict, "disk")) {
|
||||
migrate_print_status(mon, "disk", qdict);
|
||||
}
|
||||
}
|
||||
|
||||
static void migrate_put_status(QDict *qdict, const char *name,
|
||||
uint64_t trans, uint64_t rem, uint64_t total)
|
||||
{
|
||||
QObject *obj;
|
||||
|
||||
obj = qobject_from_jsonf("{ 'transferred': %" PRId64 ", "
|
||||
"'remaining': %" PRId64 ", "
|
||||
"'total': %" PRId64 " }", trans, rem, total);
|
||||
qdict_put_obj(qdict, name, obj);
|
||||
}
|
||||
|
||||
void do_info_migrate(Monitor *mon, QObject **ret_data)
|
||||
{
|
||||
QDict *qdict;
|
||||
MigrationInfo *info = g_malloc0(sizeof(*info));
|
||||
MigrationState *s = migrate_get_current();
|
||||
|
||||
switch (s->state) {
|
||||
@@ -161,30 +117,38 @@ void do_info_migrate(Monitor *mon, QObject **ret_data)
|
||||
/* no migration has happened ever */
|
||||
break;
|
||||
case MIG_STATE_ACTIVE:
|
||||
qdict = qdict_new();
|
||||
qdict_put(qdict, "status", qstring_from_str("active"));
|
||||
info->has_status = true;
|
||||
info->status = g_strdup("active");
|
||||
|
||||
migrate_put_status(qdict, "ram", ram_bytes_transferred(),
|
||||
ram_bytes_remaining(), ram_bytes_total());
|
||||
info->has_ram = true;
|
||||
info->ram = g_malloc0(sizeof(*info->ram));
|
||||
info->ram->transferred = ram_bytes_transferred();
|
||||
info->ram->remaining = ram_bytes_remaining();
|
||||
info->ram->total = ram_bytes_total();
|
||||
|
||||
if (blk_mig_active()) {
|
||||
migrate_put_status(qdict, "disk", blk_mig_bytes_transferred(),
|
||||
blk_mig_bytes_remaining(),
|
||||
blk_mig_bytes_total());
|
||||
info->has_disk = true;
|
||||
info->disk = g_malloc0(sizeof(*info->disk));
|
||||
info->disk->transferred = blk_mig_bytes_transferred();
|
||||
info->disk->remaining = blk_mig_bytes_remaining();
|
||||
info->disk->total = blk_mig_bytes_total();
|
||||
}
|
||||
|
||||
*ret_data = QOBJECT(qdict);
|
||||
break;
|
||||
case MIG_STATE_COMPLETED:
|
||||
*ret_data = qobject_from_jsonf("{ 'status': 'completed' }");
|
||||
info->has_status = true;
|
||||
info->status = g_strdup("completed");
|
||||
break;
|
||||
case MIG_STATE_ERROR:
|
||||
*ret_data = qobject_from_jsonf("{ 'status': 'failed' }");
|
||||
info->has_status = true;
|
||||
info->status = g_strdup("failed");
|
||||
break;
|
||||
case MIG_STATE_CANCELLED:
|
||||
*ret_data = qobject_from_jsonf("{ 'status': 'cancelled' }");
|
||||
info->has_status = true;
|
||||
info->status = g_strdup("cancelled");
|
||||
break;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/* shared migration helpers */
|
||||
|
||||
@@ -123,8 +123,6 @@ typedef struct mon_cmd_t {
|
||||
void (*user_print)(Monitor *mon, const QObject *data);
|
||||
union {
|
||||
void (*info)(Monitor *mon);
|
||||
void (*info_new)(Monitor *mon, QObject **ret_data);
|
||||
int (*info_async)(Monitor *mon, MonitorCompletion *cb, void *opaque);
|
||||
void (*cmd)(Monitor *mon, const QDict *qdict);
|
||||
int (*cmd_new)(Monitor *mon, const QDict *params, QObject **ret_data);
|
||||
int (*cmd_async)(Monitor *mon, const QDict *params,
|
||||
@@ -205,7 +203,6 @@ static const mon_cmd_t mon_cmds[];
|
||||
static const mon_cmd_t info_cmds[];
|
||||
|
||||
static const mon_cmd_t qmp_cmds[];
|
||||
static const mon_cmd_t qmp_query_cmds[];
|
||||
|
||||
Monitor *cur_mon;
|
||||
Monitor *default_mon;
|
||||
@@ -514,7 +511,6 @@ static int do_qmp_capabilities(Monitor *mon, const QDict *params,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mon_set_cpu(int cpu_index);
|
||||
static void handle_user_command(Monitor *mon, const char *cmdline);
|
||||
|
||||
static int do_hmp_passthrough(Monitor *mon, const QDict *params,
|
||||
@@ -532,7 +528,7 @@ static int do_hmp_passthrough(Monitor *mon, const QDict *params,
|
||||
cur_mon = &hmp;
|
||||
|
||||
if (qdict_haskey(params, "cpu-index")) {
|
||||
ret = mon_set_cpu(qdict_get_int(params, "cpu-index"));
|
||||
ret = monitor_set_cpu(qdict_get_int(params, "cpu-index"));
|
||||
if (ret < 0) {
|
||||
cur_mon = old_mon;
|
||||
qerror_report(QERR_INVALID_PARAMETER_VALUE, "cpu-index", "a CPU number");
|
||||
@@ -664,11 +660,6 @@ static int qmp_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd,
|
||||
return cmd->mhandler.cmd_async(mon, params, qmp_monitor_complete, mon);
|
||||
}
|
||||
|
||||
static void qmp_async_info_handler(Monitor *mon, const mon_cmd_t *cmd)
|
||||
{
|
||||
cmd->mhandler.info_async(mon, qmp_monitor_complete, mon);
|
||||
}
|
||||
|
||||
static void user_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd,
|
||||
const QDict *params)
|
||||
{
|
||||
@@ -686,21 +677,6 @@ static void user_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd,
|
||||
}
|
||||
}
|
||||
|
||||
static void user_async_info_handler(Monitor *mon, const mon_cmd_t *cmd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
MonitorCompletionData *cb_data = g_malloc(sizeof(*cb_data));
|
||||
cb_data->mon = mon;
|
||||
cb_data->user_print = cmd->user_print;
|
||||
monitor_suspend(mon);
|
||||
ret = cmd->mhandler.info_async(mon, user_monitor_complete, cb_data);
|
||||
if (ret < 0) {
|
||||
monitor_resume(mon);
|
||||
g_free(cb_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void do_info(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const mon_cmd_t *cmd;
|
||||
@@ -719,52 +695,23 @@ static void do_info(Monitor *mon, const QDict *qdict)
|
||||
goto help;
|
||||
}
|
||||
|
||||
if (handler_is_async(cmd)) {
|
||||
user_async_info_handler(mon, cmd);
|
||||
} else if (handler_is_qobject(cmd)) {
|
||||
QObject *info_data = NULL;
|
||||
|
||||
cmd->mhandler.info_new(mon, &info_data);
|
||||
if (info_data) {
|
||||
cmd->user_print(mon, info_data);
|
||||
qobject_decref(info_data);
|
||||
}
|
||||
} else {
|
||||
cmd->mhandler.info(mon);
|
||||
}
|
||||
|
||||
cmd->mhandler.info(mon);
|
||||
return;
|
||||
|
||||
help:
|
||||
help_cmd(mon, "info");
|
||||
}
|
||||
|
||||
static CommandInfoList *alloc_cmd_entry(const char *cmd_name)
|
||||
{
|
||||
CommandInfoList *info;
|
||||
|
||||
info = g_malloc0(sizeof(*info));
|
||||
info->value = g_malloc0(sizeof(*info->value));
|
||||
info->value->name = g_strdup(cmd_name);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
CommandInfoList *qmp_query_commands(Error **errp)
|
||||
{
|
||||
CommandInfoList *info, *cmd_list = NULL;
|
||||
const mon_cmd_t *cmd;
|
||||
|
||||
for (cmd = qmp_cmds; cmd->name != NULL; cmd++) {
|
||||
info = alloc_cmd_entry(cmd->name);
|
||||
info->next = cmd_list;
|
||||
cmd_list = info;
|
||||
}
|
||||
info = g_malloc0(sizeof(*info));
|
||||
info->value = g_malloc0(sizeof(*info->value));
|
||||
info->value->name = g_strdup(cmd->name);
|
||||
|
||||
for (cmd = qmp_query_cmds; cmd->name != NULL; cmd++) {
|
||||
char buf[128];
|
||||
snprintf(buf, sizeof(buf), "query-%s", cmd->name);
|
||||
info = alloc_cmd_entry(buf);
|
||||
info->next = cmd_list;
|
||||
cmd_list = info;
|
||||
}
|
||||
@@ -772,8 +719,8 @@ CommandInfoList *qmp_query_commands(Error **errp)
|
||||
return cmd_list;
|
||||
}
|
||||
|
||||
/* get the current CPU defined by the user */
|
||||
static int mon_set_cpu(int cpu_index)
|
||||
/* set the current CPU defined by the user */
|
||||
int monitor_set_cpu(int cpu_index)
|
||||
{
|
||||
CPUState *env;
|
||||
|
||||
@@ -789,12 +736,17 @@ static int mon_set_cpu(int cpu_index)
|
||||
static CPUState *mon_get_cpu(void)
|
||||
{
|
||||
if (!cur_mon->mon_cpu) {
|
||||
mon_set_cpu(0);
|
||||
monitor_set_cpu(0);
|
||||
}
|
||||
cpu_synchronize_state(cur_mon->mon_cpu);
|
||||
return cur_mon->mon_cpu;
|
||||
}
|
||||
|
||||
int monitor_get_cpu_index(void)
|
||||
{
|
||||
return mon_get_cpu()->cpu_index;
|
||||
}
|
||||
|
||||
static void do_info_registers(Monitor *mon)
|
||||
{
|
||||
CPUState *env;
|
||||
@@ -808,107 +760,6 @@ static void do_info_registers(Monitor *mon)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void print_cpu_iter(QObject *obj, void *opaque)
|
||||
{
|
||||
QDict *cpu;
|
||||
int active = ' ';
|
||||
Monitor *mon = opaque;
|
||||
|
||||
assert(qobject_type(obj) == QTYPE_QDICT);
|
||||
cpu = qobject_to_qdict(obj);
|
||||
|
||||
if (qdict_get_bool(cpu, "current")) {
|
||||
active = '*';
|
||||
}
|
||||
|
||||
monitor_printf(mon, "%c CPU #%d: ", active, (int)qdict_get_int(cpu, "CPU"));
|
||||
|
||||
#if defined(TARGET_I386)
|
||||
monitor_printf(mon, "pc=0x" TARGET_FMT_lx,
|
||||
(target_ulong) qdict_get_int(cpu, "pc"));
|
||||
#elif defined(TARGET_PPC)
|
||||
monitor_printf(mon, "nip=0x" TARGET_FMT_lx,
|
||||
(target_long) qdict_get_int(cpu, "nip"));
|
||||
#elif defined(TARGET_SPARC)
|
||||
monitor_printf(mon, "pc=0x" TARGET_FMT_lx,
|
||||
(target_long) qdict_get_int(cpu, "pc"));
|
||||
monitor_printf(mon, "npc=0x" TARGET_FMT_lx,
|
||||
(target_long) qdict_get_int(cpu, "npc"));
|
||||
#elif defined(TARGET_MIPS)
|
||||
monitor_printf(mon, "PC=0x" TARGET_FMT_lx,
|
||||
(target_long) qdict_get_int(cpu, "PC"));
|
||||
#endif
|
||||
|
||||
if (qdict_get_bool(cpu, "halted")) {
|
||||
monitor_printf(mon, " (halted)");
|
||||
}
|
||||
|
||||
monitor_printf(mon, " thread_id=%" PRId64 " ",
|
||||
qdict_get_int(cpu, "thread_id"));
|
||||
|
||||
monitor_printf(mon, "\n");
|
||||
}
|
||||
|
||||
static void monitor_print_cpus(Monitor *mon, const QObject *data)
|
||||
{
|
||||
QList *cpu_list;
|
||||
|
||||
assert(qobject_type(data) == QTYPE_QLIST);
|
||||
cpu_list = qobject_to_qlist(data);
|
||||
qlist_iter(cpu_list, print_cpu_iter, mon);
|
||||
}
|
||||
|
||||
static void do_info_cpus(Monitor *mon, QObject **ret_data)
|
||||
{
|
||||
CPUState *env;
|
||||
QList *cpu_list;
|
||||
|
||||
cpu_list = qlist_new();
|
||||
|
||||
/* just to set the default cpu if not already done */
|
||||
mon_get_cpu();
|
||||
|
||||
for(env = first_cpu; env != NULL; env = env->next_cpu) {
|
||||
QDict *cpu;
|
||||
QObject *obj;
|
||||
|
||||
cpu_synchronize_state(env);
|
||||
|
||||
obj = qobject_from_jsonf("{ 'CPU': %d, 'current': %i, 'halted': %i }",
|
||||
env->cpu_index, env == mon->mon_cpu,
|
||||
env->halted);
|
||||
|
||||
cpu = qobject_to_qdict(obj);
|
||||
|
||||
#if defined(TARGET_I386)
|
||||
qdict_put(cpu, "pc", qint_from_int(env->eip + env->segs[R_CS].base));
|
||||
#elif defined(TARGET_PPC)
|
||||
qdict_put(cpu, "nip", qint_from_int(env->nip));
|
||||
#elif defined(TARGET_SPARC)
|
||||
qdict_put(cpu, "pc", qint_from_int(env->pc));
|
||||
qdict_put(cpu, "npc", qint_from_int(env->npc));
|
||||
#elif defined(TARGET_MIPS)
|
||||
qdict_put(cpu, "PC", qint_from_int(env->active_tc.PC));
|
||||
#endif
|
||||
qdict_put(cpu, "thread_id", qint_from_int(env->thread_id));
|
||||
|
||||
qlist_append(cpu_list, cpu);
|
||||
}
|
||||
|
||||
*ret_data = QOBJECT(cpu_list);
|
||||
}
|
||||
|
||||
static int do_cpu_set(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
{
|
||||
int index = qdict_get_int(qdict, "index");
|
||||
if (mon_set_cpu(index) < 0) {
|
||||
qerror_report(QERR_INVALID_PARAMETER_VALUE, "index",
|
||||
"a CPU number");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void do_info_jit(Monitor *mon)
|
||||
{
|
||||
dump_exec_info((FILE *)mon, monitor_fprintf);
|
||||
@@ -2773,16 +2624,14 @@ static const mon_cmd_t info_cmds[] = {
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show the block devices",
|
||||
.user_print = bdrv_info_print,
|
||||
.mhandler.info_new = bdrv_info,
|
||||
.mhandler.info = hmp_info_block,
|
||||
},
|
||||
{
|
||||
.name = "blockstats",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show block device statistics",
|
||||
.user_print = bdrv_stats_print,
|
||||
.mhandler.info_new = bdrv_info_stats,
|
||||
.mhandler.info = hmp_info_blockstats,
|
||||
},
|
||||
{
|
||||
.name = "registers",
|
||||
@@ -2796,8 +2645,7 @@ static const mon_cmd_t info_cmds[] = {
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show infos for each CPU",
|
||||
.user_print = monitor_print_cpus,
|
||||
.mhandler.info_new = do_info_cpus,
|
||||
.mhandler.info = hmp_info_cpus,
|
||||
},
|
||||
{
|
||||
.name = "history",
|
||||
@@ -2840,8 +2688,7 @@ static const mon_cmd_t info_cmds[] = {
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show PCI info",
|
||||
.user_print = do_pci_info_print,
|
||||
.mhandler.info_new = do_pci_info,
|
||||
.mhandler.info = hmp_info_pci,
|
||||
},
|
||||
#if defined(TARGET_I386) || defined(TARGET_SH4) || defined(TARGET_SPARC) || \
|
||||
defined(TARGET_PPC)
|
||||
@@ -2944,16 +2791,14 @@ static const mon_cmd_t info_cmds[] = {
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show which guest mouse is receiving events",
|
||||
.user_print = do_info_mice_print,
|
||||
.mhandler.info_new = do_info_mice,
|
||||
.mhandler.info = hmp_info_mice,
|
||||
},
|
||||
{
|
||||
.name = "vnc",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show the vnc server status",
|
||||
.user_print = do_info_vnc_print,
|
||||
.mhandler.info_new = do_info_vnc,
|
||||
.mhandler.info = hmp_info_vnc,
|
||||
},
|
||||
#if defined(CONFIG_SPICE)
|
||||
{
|
||||
@@ -2961,8 +2806,7 @@ static const mon_cmd_t info_cmds[] = {
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show the spice server status",
|
||||
.user_print = do_info_spice_print,
|
||||
.mhandler.info_new = do_info_spice,
|
||||
.mhandler.info = hmp_info_spice,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
@@ -3002,17 +2846,14 @@ static const mon_cmd_t info_cmds[] = {
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show migration status",
|
||||
.user_print = do_info_migrate_print,
|
||||
.mhandler.info_new = do_info_migrate,
|
||||
.mhandler.info = hmp_info_migrate,
|
||||
},
|
||||
{
|
||||
.name = "balloon",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show balloon information",
|
||||
.user_print = monitor_print_balloon,
|
||||
.mhandler.info_async = do_info_balloon,
|
||||
.flags = MONITOR_CMD_ASYNC,
|
||||
.mhandler.info = hmp_info_balloon,
|
||||
},
|
||||
{
|
||||
.name = "qtree",
|
||||
@@ -3061,85 +2902,6 @@ static const mon_cmd_t qmp_cmds[] = {
|
||||
{ /* NULL */ },
|
||||
};
|
||||
|
||||
static const mon_cmd_t qmp_query_cmds[] = {
|
||||
{
|
||||
.name = "block",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show the block devices",
|
||||
.user_print = bdrv_info_print,
|
||||
.mhandler.info_new = bdrv_info,
|
||||
},
|
||||
{
|
||||
.name = "blockstats",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show block device statistics",
|
||||
.user_print = bdrv_stats_print,
|
||||
.mhandler.info_new = bdrv_info_stats,
|
||||
},
|
||||
{
|
||||
.name = "cpus",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show infos for each CPU",
|
||||
.user_print = monitor_print_cpus,
|
||||
.mhandler.info_new = do_info_cpus,
|
||||
},
|
||||
{
|
||||
.name = "pci",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show PCI info",
|
||||
.user_print = do_pci_info_print,
|
||||
.mhandler.info_new = do_pci_info,
|
||||
},
|
||||
{
|
||||
.name = "mice",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show which guest mouse is receiving events",
|
||||
.user_print = do_info_mice_print,
|
||||
.mhandler.info_new = do_info_mice,
|
||||
},
|
||||
{
|
||||
.name = "vnc",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show the vnc server status",
|
||||
.user_print = do_info_vnc_print,
|
||||
.mhandler.info_new = do_info_vnc,
|
||||
},
|
||||
#if defined(CONFIG_SPICE)
|
||||
{
|
||||
.name = "spice",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show the spice server status",
|
||||
.user_print = do_info_spice_print,
|
||||
.mhandler.info_new = do_info_spice,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.name = "migrate",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show migration status",
|
||||
.user_print = do_info_migrate_print,
|
||||
.mhandler.info_new = do_info_migrate,
|
||||
},
|
||||
{
|
||||
.name = "balloon",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show balloon information",
|
||||
.user_print = monitor_print_balloon,
|
||||
.mhandler.info_async = do_info_balloon,
|
||||
.flags = MONITOR_CMD_ASYNC,
|
||||
},
|
||||
{ /* NULL */ },
|
||||
};
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
static const char *pch;
|
||||
@@ -3934,11 +3696,6 @@ static const mon_cmd_t *monitor_find_command(const char *cmdname)
|
||||
return search_dispatch_table(mon_cmds, cmdname);
|
||||
}
|
||||
|
||||
static const mon_cmd_t *qmp_find_query_cmd(const char *info_item)
|
||||
{
|
||||
return search_dispatch_table(qmp_query_cmds, info_item);
|
||||
}
|
||||
|
||||
static const mon_cmd_t *qmp_find_cmd(const char *cmdname)
|
||||
{
|
||||
return search_dispatch_table(qmp_cmds, cmdname);
|
||||
@@ -4862,22 +4619,6 @@ static QDict *qmp_check_input_obj(QObject *input_obj)
|
||||
return input_dict;
|
||||
}
|
||||
|
||||
static void qmp_call_query_cmd(Monitor *mon, const mon_cmd_t *cmd)
|
||||
{
|
||||
QObject *ret_data = NULL;
|
||||
|
||||
if (handler_is_async(cmd)) {
|
||||
qmp_async_info_handler(mon, cmd);
|
||||
if (monitor_has_error(mon)) {
|
||||
monitor_protocol_emitter(mon, NULL);
|
||||
}
|
||||
} else {
|
||||
cmd->mhandler.info_new(mon, &ret_data);
|
||||
monitor_protocol_emitter(mon, ret_data);
|
||||
qobject_decref(ret_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void qmp_call_cmd(Monitor *mon, const mon_cmd_t *cmd,
|
||||
const QDict *params)
|
||||
{
|
||||
@@ -4898,10 +4639,9 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
|
||||
QObject *obj;
|
||||
QDict *input, *args;
|
||||
const mon_cmd_t *cmd;
|
||||
const char *cmd_name;
|
||||
Monitor *mon = cur_mon;
|
||||
const char *cmd_name, *query_cmd;
|
||||
|
||||
query_cmd = NULL;
|
||||
args = input = NULL;
|
||||
|
||||
obj = json_parser_parse(tokens, NULL);
|
||||
@@ -4928,9 +4668,6 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
|
||||
}
|
||||
|
||||
cmd = qmp_find_cmd(cmd_name);
|
||||
if (!cmd && strstart(cmd_name, "query-", &query_cmd)) {
|
||||
cmd = qmp_find_query_cmd(query_cmd);
|
||||
}
|
||||
if (!cmd) {
|
||||
qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name);
|
||||
goto err_out;
|
||||
@@ -4949,9 +4686,7 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (query_cmd) {
|
||||
qmp_call_query_cmd(mon, cmd);
|
||||
} else if (handler_is_async(cmd)) {
|
||||
if (handler_is_async(cmd)) {
|
||||
err = qmp_async_cmd_handler(mon, cmd, args);
|
||||
if (err) {
|
||||
/* emit the error response */
|
||||
|
||||
@@ -57,6 +57,8 @@ void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
|
||||
void monitor_printf(Monitor *mon, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
|
||||
void monitor_print_filename(Monitor *mon, const char *filename);
|
||||
void monitor_flush(Monitor *mon);
|
||||
int monitor_set_cpu(int cpu_index);
|
||||
int monitor_get_cpu_index(void);
|
||||
|
||||
typedef void (MonitorCompletion)(void *opaque, QObject *ret_data);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user