/*
* Human Monitor Interface
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
* Contributions after 2012-01-13 are licensed under the terms of the
* GNU GPL, version 2 or (at your option) any later version.
*/
#include "qemu/osdep.h"
#include "hmp.h"
#include "net/net.h"
#include "net/eth.h"
#include "sysemu/char.h"
#include "sysemu/block-backend.h"
#include "qemu/option.h"
#include "qemu/timer.h"
#include "qmp-commands.h"
#include "qemu/sockets.h"
#include "monitor/monitor.h"
#include "monitor/qdev.h"
#include "qapi/opts-visitor.h"
#include "qapi/qmp/qerror.h"
#include "qapi/string-output-visitor.h"
#include "qapi/util.h"
#include "qapi-visit.h"
#include "qom/object_interfaces.h"
#include "ui/console.h"
#include "block/qapi.h"
#include "qemu-io.h"
#include "qemu/cutils.h"
#ifdef CONFIG_SPICE
#include <spice/enums.h>
#endif
static void hmp_handle_error(Monitor *mon, Error **errp)
{
assert(errp);
if (*errp) {
error_report_err(*errp);
}
}
void hmp_info_name(Monitor *mon, const QDict *qdict)
{
NameInfo *info;
info = qmp_query_name(NULL);
if (info->has_name) {
monitor_printf(mon, "%s\n", info->name);
}
qapi_free_NameInfo(info);
}
void hmp_info_version(Monitor *mon, const QDict *qdict)
{
VersionInfo *info;
info = qmp_query_version(NULL);
monitor_printf(mon, "%" PRId64 ".%" PRId64 ".%" PRId64 "%s\n",
info->qemu->major, info->qemu->minor, info->qemu->micro,
info->package);
qapi_free_VersionInfo(info);
}
void hmp_info_kvm(Monitor *mon, const QDict *qdict)
{
KvmInfo *info;
info = qmp_query_kvm(NULL);
monitor_printf(mon, "kvm support: ");
if (info->present) {
monitor_printf(mon, "%s\n", info->enabled ? "enabled" : "disabled");
} else {
monitor_printf(mon, "not compiled\n");
}
qapi_free_KvmInfo(info);
}
void hmp_info_status(Monitor *mon, const QDict *qdict)
{
StatusInfo *info;
info = qmp_query_status(NULL);
monitor_printf(mon, "VM status: %s%s",
info->running ? "running" : "paused",
info->singlestep ? " (single step mode)" : "");
if (!info->running && info->status != RUN_STATE_PAUSED) {
monitor_printf(mon, " (%s)", RunState_lookup[info->status]);
}
monitor_printf(mon, "\n");
qapi_free_StatusInfo(info);
}
void hmp_info_uuid(Monitor *mon, const QDict *qdict)
{
UuidInfo *info;
info = qmp_query_uuid(NULL);
monitor_printf(mon, "%s\n", info->UUID);
qapi_free_UuidInfo(info);
}
void hmp_info_chardev(Monitor *mon, const QDict *qdict)
{
ChardevInfoList *char_info, *info;
char_info = qmp_query_chardev(NULL);
for (info = char_info; info; info = info->next) {
monitor_printf(mon, "%s: filename=%s\n", info->value->label,
info->value->filename);
}
qapi_free_ChardevInfoList(char_info);
}
void hmp_info_mice(Monitor *mon, const QDict *qdict)
{
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, const QDict *qdict)
{
MigrationInfo *info;
MigrationCapabilityStatusList *caps, *cap;
info = qmp_query_migrate(NULL);
caps = qmp_query_migrate_capabilities(NULL);
/* do not display parameters during setup */
if (info->has_status && caps) {
monitor_printf(mon, "capabilities: ");
for (cap = caps; cap; cap = cap->next) {
monitor_printf(mon, "%s: %s ",
MigrationCapability_lookup[cap->value->capability],
cap->value->state ? "on" : "off");
}
monitor_printf(mon, "\n");
}
if (info->has_status) {
monitor_printf(mon, "Migration status: %s\n",
MigrationStatus_lookup[info->status]);
monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n",
info->total_time);
if (info->has_expected_downtime) {
monitor_printf(mon, "expected downtime: %" PRIu64 " milliseconds\n",
info->expected_downtime);
}
if (info->has_downtime) {
monitor_printf(mon, "downtime: %" PRIu64 " milliseconds\n",
info->downtime);
}
if (info->has_setup_time) {
monitor_printf(mon, "setup: %" PRIu64 " milliseconds\n",
info->setup_time);
}
}
if (info->has_ram) {
monitor_printf(mon, "transferred ram: %" PRIu64 " kbytes\n",
info->ram->transferred >> 10);
monitor_printf(mon, "throughput: %0.2f mbps\n",
info->ram->mbps);
monitor_printf(mon, "remaining ram: %" PRIu64 " kbytes\n",
info->ram->remaining >> 10);
monitor_printf(mon, "total ram: %" PRIu64 " kbytes\n",
info->ram->total >> 10);
monitor_printf(mon, "duplicate: %" PRIu64 " pages\n",
info->ram->duplicate);
monitor_printf(mon, "skipped: %" PRIu64 " pages\n",
info->ram->skipped);
monitor_printf(mon, "normal: %" PRIu64 " pages\n",
info->ram->normal);
monitor_printf(mon, "normal bytes: %" PRIu64 " kbytes\n",
info->ram->normal_bytes >> 10);
monitor_printf(mon, "dirty sync count: %" PRIu64 "\n",
info->ram->dirty_sync_count);
if (info->ram->dirty_pages_rate) {
monitor_printf(mon, "dirty pages rate: %" PRIu64 " pages\n",
info->ram->dirty_pages_rate);
}
}
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);
}
if (info->has_xbzrle_cache) {
monitor_printf(mon, "cache size: %" PRIu64 " bytes\n",
info->xbzrle_cache->cache_size);
monitor_printf(mon, "xbzrle transferred: %" PRIu64 " kbytes\n",
info->xbzrle_cache->bytes >> 10);
monitor_printf(mon, "xbzrle pages: %" PRIu64 " pages\n",
info->xbzrle_cache->pages);
monitor_printf(mon, "xbzrle cache miss: %" PRIu64 "\n",
info->xbzrle_cache->cache_miss);
monitor_printf(mon, "xbzrle cache miss rate: %0.2f\n",
info->xbzrle_cache->cache_miss_rate);
monitor_printf(mon, "xbzrle overflow : %" PRIu64 "\n",
info->xbzrle_cache->overflow);
}
if (info->has_x_cpu_throttle_percentage) {
monitor_printf(mon, "cpu throttle percentage: %" PRIu64 "\n",
info->x_cpu_throttle_percentage);
}
qapi_free_MigrationInfo(info);
qapi_free_MigrationCapabilityStatusList(caps);
}
void hmp_info_migrate_capabilities(Monitor *mon, const QDict *qdict)
{
MigrationCapabilityStatusList *caps, *cap;
caps = qmp_query_migrate_capabilities(NULL);
if (caps) {
monitor_printf(mon, "capabilities: ");
for (cap = caps; cap; cap = cap->next) {
monitor_printf(mon, "%s: %s ",
MigrationCapability_lookup[cap->value->capability],
cap->value->state ? "on" : "off");
}
monitor_printf(mon, "\n");
}
qapi_free_MigrationCapabilityStatusList(caps);
}
void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
{
MigrationParameters *params;
params = qmp_query_migrate_parameters(NULL);
if (params) {
monitor_printf(mon, "parameters:");
monitor_printf(mon, " %s: %" PRId64,
MigrationParameter_lookup[MIGRATION_PARAMETER_COMPRESS_LEVEL],
params->compress_level);
monitor_printf(mon, " %s: %" PRId64,
MigrationParameter_lookup[MIGRATION_PARAMETER_COMPRESS_THREADS],
params->compress_threads);
monitor_printf(mon, " %s: %" PRId64,
MigrationParameter_lookup[MIGRATION_PARAMETER_DECOMPRESS_THREADS],
params->decompress_threads);
monitor_printf(mon, " %s: %" PRId64,
MigrationParameter_lookup[MIGRATION_PARAMETER_X_CPU_THROTTLE_INITIAL],
params->x_cpu_throttle_initial);
monitor_printf(mon, " %s: %" PRId64,
MigrationParameter_lookup[MIGRATION_PARAMETER_X_CPU_THROTTLE_INCREMENT],
params->x_cpu_throttle_increment);
monitor_printf(mon, "\n");
}
qapi_free_MigrationParameters(params);
}
void hmp_info_migrate_cache_size(Monitor *mon, const QDict *qdict)
{
monitor_printf(mon, "xbzrel cache size: %" PRId64 " kbytes\n",
qmp_query_migrate_cache_size(NULL) >> 10);
}
void hmp_info_cpus(Monitor *mon, const QDict *qdict)
{
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);
switch (cpu->value->arch) {
case CPU_INFO_ARCH_X86:
monitor_printf(mon, " pc=0x%016" PRIx64, cpu->value->u.x86.pc);
break;
case CPU_INFO_ARCH_PPC:
monitor_printf(mon, " nip=0x%016" PRIx64, cpu->value->u.ppc.nip);
break;
case CPU_INFO_ARCH_SPARC:
monitor_printf(mon, " pc=0x%016" PRIx64,
cpu->value->u.q_sparc.pc);
monitor_printf(mon, " npc=0x%016" PRIx64,
cpu->value->u.q_sparc.npc);
break;
case CPU_INFO_ARCH_MIPS:
monitor_printf(mon, " PC=0x%016" PRIx64, cpu->value->u.q_mips.PC);
break;
case CPU_INFO_ARCH_TRICORE:
monitor_printf(mon, " PC=0x%016" PRIx64, cpu->value->u.tricore.PC);
break;
default:
break;
}
if (cpu->value->halted) {
monitor_printf(mon, " (halted)");
}
monitor_printf(mon, " thread_id=%" PRId64 "\n", cpu->value->thread_id);
}
qapi_free_CpuInfoList(cpu_list);
}
static void print_block_info(Monitor *mon, BlockInfo *info,
BlockDeviceInfo *inserted, bool verbose)
{
ImageInfo *image_info;
assert(!info || !info->has_inserted || info->inserted == inserted);
if (info) {
monitor_printf(mon, "%s", info->device);
if (inserted && inserted->has_node_name) {
monitor_printf(mon, " (%s)", inserted->node_name);
}
} else {
assert(inserted);
monitor_printf(mon, "%s",
inserted->has_node_name
? inserted->node_name
: "<anonymous>");
}
if (inserted) {
monitor_printf(mon, ": %s (%s%s%s)\n",
inserted->file,
inserted->drv,
inserted->ro ? ", read-only" : "",
inserted->encrypted ? ", encrypted" : "");
} else {
monitor_printf(mon, ": [not inserted]\n");
}
if (info) {
if (info->has_io_status && info->io_status != BLOCK_DEVICE_IO_STATUS_OK) {
monitor_printf(mon, " I/O status: %s\n",
BlockDeviceIoStatus_lookup[info->io_status]);
}
if (info->removable) {
monitor_printf(mon, " Removable device: %slocked, tray %s\n",
info->locked ? "" : "not ",
info->tray_open ? "open" : "closed");
}
}
if (!inserted) {
return;
}
monitor_printf(mon, " Cache mode: %s%s%s\n",
inserted->cache->writeback ? "writeback" : "writethrough",
inserted->cache->direct ? ", direct" : "",
inserted->cache->no_flush ? ", ignore flushes" : "");
if (inserted->has_backing_file) {
monitor_printf(mon,
" Backing file: %s "
"(chain depth: %" PRId64 ")\n",
inserted->backing_file,
|