$ qemu -capabilities all
{
"machines": [
{
"name": "pc-0.13",
"description": "Standard PC",
"default": 0
},
{
"name": "pc",
....
}
....
}
"version": {
"qemu": {
"micro": 50,
"minor": 12,
"major": 0
},
"package": ""
},
"target": {
"arch": "i386",
"wordsize": 32,
...
}
Signed-off-by: Daniel P. Berrange<address@hidden>
---
monitor.c | 4 +-
monitor.h | 2 +
qemu-options.hx | 9 +++++
vl.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 113 insertions(+), 2 deletions(-)
diff --git a/monitor.c b/monitor.c
index 6203f75..401a27a 100644
--- a/monitor.c
+++ b/monitor.c
@@ -711,7 +711,7 @@ static void do_info_version_print(Monitor *mon, const
QObject *data)
*
* { qemu: { "major": 0, "minor": 11, "micro": 5 }, "package": "" }
*/
-static void do_info_version(Monitor *mon, QObject **ret_data)
+void do_info_version(Monitor *mon, QObject **ret_data)
{
const char *version = QEMU_VERSION;
int major = 0, minor = 0, micro = 0;
@@ -760,7 +760,7 @@ static QObject *get_cmd_dict(const char *name)
return qobject_from_jsonf("{ 'name': %s }", p);
}
-static void do_info_commands(Monitor *mon, QObject **ret_data)
+void do_info_commands(Monitor *mon, QObject **ret_data)
{
QList *cmd_list;
const mon_cmd_t *cmd;
diff --git a/monitor.h b/monitor.h
index 733485f..dc376af 100644
--- a/monitor.h
+++ b/monitor.h
@@ -57,5 +57,7 @@ typedef void (MonitorCompletion)(void *opaque, QObject
*ret_data);
void monitor_set_error(Monitor *mon, QError *qerror);
void do_info_argv(Monitor *mon, QObject **data);
+void do_info_version(Monitor *mon, QObject **ret_data);
+void do_info_commands(Monitor *mon, QObject **ret_data);
#endif /* !MONITOR_H */
diff --git a/qemu-options.hx b/qemu-options.hx
index a6928b7..5f82347 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -27,6 +27,15 @@ STEXI
Display version information and exit
ETEXI
+DEF("capabilities", HAS_ARG, QEMU_OPTION_capabilities,
+ "-capabilities
all|version|machines|devices|cputypes|target|commands|argv|netdev\n"
+ " display capabilities of the QEMU binary and exit\n",
QEMU_ARCH_ALL)
+STEXI
address@hidden -capabilities
all|version|machines|devices|cputypes|target|commands|argv|netdev
address@hidden -capabilities
+Display capabilities of the QEMU binary and exit
+ETEXI
+
DEF("M", HAS_ARG, QEMU_OPTION_M,
"-M machine select emulated machine (-M ? for list)\n",
QEMU_ARCH_ALL)
STEXI
diff --git a/vl.c b/vl.c
index de010cc..1f165a1 100644
--- a/vl.c
+++ b/vl.c
@@ -1988,6 +1988,97 @@ static void version(void)
}
+enum {
+ QEMU_CAPS_VERSION,
+ QEMU_CAPS_MACHINES,
+ QEMU_CAPS_DEVICES,
+ QEMU_CAPS_CPUTYPES,
+ QEMU_CAPS_TARGET,
+ QEMU_CAPS_COMMANDS,
+ QEMU_CAPS_ARGV,
+ QEMU_CAPS_NETDEV,
+ QEMU_CAPS_CONFIG,
+
+ QEMU_CAPS_LAST
+};
+
+QEMU_ENUM_DECL(qemu_caps_flag);
+QEMU_ENUM_IMPL(qemu_caps_flag, QEMU_CAPS_LAST,
+ "version",
+ "machines",
+ "devices",
+ "cputypes",
+ "target",
+ "commands",
+ "argv",
+ "netdev",
+ "config");
+
+static int qemu_caps_flags_from_string(const char *flagsstr)
+{
+ if (strcmp(flagsstr, "all") == 0)
+ return ~0;
+ else {
+ int i = qemu_caps_flag_from_string(flagsstr);
+ if (i< 0)
+ return 0;
+ return (1<< i);
+ }
+
+ return 0;
+}
+typedef void (*qemu_caps_handler)(Monitor *mon, QObject **);
+
+/* Binding capabilities to a subset of monitor commands.
+ * The commands must only use static binary state, no
+ * VM runtime state and must accept mon=NULL
+ */
+static const qemu_caps_handler qemu_caps_handlers[] = {
+ do_info_version,
+ do_info_machines,
+ do_info_devices,
+ do_info_cpu_types,
+ do_info_target,
+ do_info_commands,
+ do_info_argv,
+ do_info_netdev,
+ do_info_config,
+};
+verify(ARRAY_SIZE(qemu_caps_handlers) == QEMU_CAPS_LAST);
+
+static void qemu_show_caps(const char *flagsstr)
+{
+ QDict *data = qdict_new();
+ QString *json;
+ int i;
+ int flags;
+
+ flags = qemu_caps_flags_from_string(flagsstr);
+ if (flags == 0) {
+ fprintf(stderr, "Unknown capabilities '%s'\n", flagsstr);
+ exit(1);
+ }
+
+ for (i = 0 ; i< QEMU_CAPS_LAST ; i++) {
+ if (flags& (1<< i)) {
+ QObject *val;
+ qemu_caps_handler handler = qemu_caps_handlers[i];
+ const char *name = qemu_caps_flag_to_string(i);
+ (*handler)(NULL,&val);
+ qdict_put_obj(data, name, val);
+ }
+ }
+ json = qobject_to_json_pretty(QOBJECT(data));
+ assert(json != NULL);
+
+ qstring_append_chr(json, '\n');
+ fprintf(stdout, qstring_get_str(json));
+
+ QDECREF(json);
+
+}
+
+
/**
* do_info_argv():
*
@@ -2647,6 +2738,7 @@ int main(int argc, char **argv, char **envp)
#endif
int show_vnc_port = 0;
int defconfig = 1;
+ const char *showcaps = NULL;
error_set_progname(argv[0]);
@@ -3020,6 +3112,9 @@ int main(int argc, char **argv, char **envp)
version();
exit(0);
break;
+ case QEMU_OPTION_capabilities:
+ showcaps = optarg;
+ break;
case QEMU_OPTION_m: {
uint64_t value;
char *ptr;
@@ -3785,6 +3880,11 @@ int main(int argc, char **argv, char **envp)
if (qemu_opts_foreach(&qemu_device_opts, device_help_func, NULL, 0) != 0)
exit(0);
+ if (showcaps) {
+ qemu_show_caps(showcaps);
+ exit(0);
+ }
+
if (watchdog) {
i = select_watchdog(watchdog);
if (i> 0)