qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes
@ 2012-03-19 15:09 Anthony Liguori
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 1/9] qemu-config: fix -writeconfig when using qemu_opt_set_bool Anthony Liguori
                   ` (9 more replies)
  0 siblings, 10 replies; 26+ messages in thread
From: Anthony Liguori @ 2012-03-19 15:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Eric Blake, Eduardo Habkost, Gerd Hoffman

Hi,

I didn't start out intending to write this series, but I end up here trying to
resolve an issue in the gtk UI.

This series does some dramatic refactoring to -readconfig essentially throwing
away the existing (trivial) implementation and replacing it with glib's
GKeyFile support.

It also plumbs the existing command line options through QemuOpts via a special
'system' section.  This means that any command line option can be specified via
readconfig and that the combination of -nodefconfig and -writeconfig should give
you exactly the same guest in a repeatable fashion.

Finally, this series exposes a new -query-capabilities option which dumps the
QemuOpts schema's via JSON to standard output (along with some other goodies
like the version info and supported QMP commands).

The purpose of this series is to change the way management tools (esp libvirt)
interact with QEMU to determine capabilities.  Instead of help parsing, libvirt
should use -query-capabilities to figure out which options are supported and
when new suboptions are available.

I would like to push this series into 1.1 and deprecate the help output.  My
plan would be to radically change the help output for 1.2 giving libvirt about a
release cycle to update the parsing of capabilities.

To ease the transition, the help text is available via -query-capabilities but
will be subject to change in the future.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 1/9] qemu-config: fix -writeconfig when using qemu_opt_set_bool
  2012-03-19 15:09 [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Anthony Liguori
@ 2012-03-19 15:09 ` Anthony Liguori
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 2/9] qemu-config: friends don't let friends use sscanf Anthony Liguori
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 26+ messages in thread
From: Anthony Liguori @ 2012-03-19 15:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Eric Blake, Eduardo Habkost, Gerd Hoffman

opts->str is what writeconfig uses so lets make sure it's set.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 qemu-option.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/qemu-option.c b/qemu-option.c
index 35cd609..b9a6642 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -678,6 +678,7 @@ int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
         opt->desc = desc+i;
     }
     opt->value.boolean = !!val;
+    opt->str = val ? "on" : "off";
     return 0;
 }
 
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 2/9] qemu-config: friends don't let friends use sscanf
  2012-03-19 15:09 [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Anthony Liguori
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 1/9] qemu-config: fix -writeconfig when using qemu_opt_set_bool Anthony Liguori
@ 2012-03-19 15:09 ` Anthony Liguori
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 3/9] vl: refactor command line parsing to allow options to be set via config Anthony Liguori
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 26+ messages in thread
From: Anthony Liguori @ 2012-03-19 15:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Eric Blake, Eduardo Habkost, Gerd Hoffman

The current qemu-config code uses a simple sscanf parser.  The use of scanf is
actually incorrect as scanf is incredibly hard to use correctly.  Moreover, it
introduces unnecessary strictness in terms of how whitespace is handled.

Fortunately, glib has a key value pair parser that will work very well for our
purposes.  Switch the code to use this.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 block/blkdebug.c |    9 +---
 qemu-config.c    |  141 ++++++++++++++++++++++++++++++------------------------
 qemu-config.h    |    2 +-
 3 files changed, 81 insertions(+), 71 deletions(-)

diff --git a/block/blkdebug.c b/block/blkdebug.c
index a251802..71f1cab 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -244,16 +244,10 @@ static int add_rule(QemuOpts *opts, void *opaque)
 
 static int read_config(BDRVBlkdebugState *s, const char *filename)
 {
-    FILE *f;
     int ret;
     struct add_rule_data d;
 
-    f = fopen(filename, "r");
-    if (f == NULL) {
-        return -errno;
-    }
-
-    ret = qemu_config_parse(f, config_groups, filename);
+    ret = qemu_config_parse(config_groups, filename);
     if (ret < 0) {
         goto fail;
     }
@@ -269,7 +263,6 @@ static int read_config(BDRVBlkdebugState *s, const char *filename)
 fail:
     qemu_opts_reset(&inject_error_opts);
     qemu_opts_reset(&set_state_opts);
-    fclose(f);
     return ret;
 }
 
diff --git a/qemu-config.c b/qemu-config.c
index be84a03..daf6557 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -757,80 +757,97 @@ void qemu_config_write(FILE *fp)
     }
 }
 
-int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
+int qemu_config_parse(QemuOptsList **lists, const char *filename)
 {
-    char line[1024], group[64], id[64], arg[64], value[1024];
-    Location loc;
-    QemuOptsList *list = NULL;
-    QemuOpts *opts = NULL;
-    int res = -1, lno = 0;
-
-    loc_push_none(&loc);
-    while (fgets(line, sizeof(line), fp) != NULL) {
-        loc_set_file(fname, ++lno);
-        if (line[0] == '\n') {
-            /* skip empty lines */
-            continue;
+    GKeyFile *f;
+    GError *err = NULL;
+    gchar **groups;
+    gsize i, nb_groups = 0;
+
+    f = g_key_file_new();
+    if (!g_key_file_load_from_file(f, filename, 0, &err)) {
+        if (err->code == G_FILE_ERROR_NOENT) {
+            return 0;
         }
-        if (line[0] == '#') {
-            /* comment */
-            continue;
+        fprintf(stderr, "could not parse config: %s\n", err->message);
+        g_error_free(err);
+        return -EINVAL;
+    }
+
+    groups = g_key_file_get_groups(f, &nb_groups);
+    for (i = 0; i < nb_groups; i++) {
+        gchar **keys;
+        gchar *subkey = NULL;
+        gchar *group;
+        gsize j, nb_keys = 0;
+        char *ptr;
+        QemuOpts *opts;
+        QemuOptsList *list;
+
+        group = g_strdup(groups[i]);
+
+        ptr = strchr(group, '"');
+        if (ptr) {
+            *ptr = 0;
+            subkey = g_strdup(ptr + 1);
+            ptr = strchr(subkey, '"');
+            *ptr = 0;
+            g_strchomp(group);
         }
-        if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
-            /* group with id */
-            list = find_list(lists, group);
-            if (list == NULL)
-                goto out;
-            opts = qemu_opts_create(list, id, 1);
-            continue;
+            
+        list = find_list(lists, group);
+        if (list == NULL) {
+            break;
         }
-        if (sscanf(line, "[%63[^]]]", group) == 1) {
-            /* group without id */
-            list = find_list(lists, group);
-            if (list == NULL)
-                goto out;
+
+        if (subkey) {
+            opts = qemu_opts_create(list, subkey, 1);
+        } else {
             opts = qemu_opts_create(list, NULL, 0);
-            continue;
         }
-        if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) {
-            /* arg = value */
-            if (opts == NULL) {
-                error_report("no group defined");
-                goto out;
+
+        keys = g_key_file_get_keys(f, groups[i], &nb_keys, NULL);
+        for (j = 0; j < nb_keys; j++) {
+            gchar *value;
+            gsize len;
+
+            value = g_key_file_get_string(f, groups[i], keys[j], &err);
+            if (err) {
+                fprintf(stderr,
+                        "warning: failed to read key `%s' in section `%s': %s\n",
+                        keys[j], groups[i], err->message);
+                g_free(value);
+                g_error_free(err);
+                break;
             }
-            if (qemu_opt_set(opts, arg, value) != 0) {
-                goto out;
+            
+            if (value[0] == '"') {
+                value[0] = ' ';
             }
-            continue;
+
+            len = strlen(value);
+            if (value[len - 1] == '"') {
+                value[len - 1] = 0;
+            }
+            g_strchug(value);
+
+            qemu_opt_set(opts, keys[j], value);
+            g_free(value);
         }
-        error_report("parse error");
-        goto out;
-    }
-    if (ferror(fp)) {
-        error_report("error reading file");
-        goto out;
+
+        g_free(subkey);
+        g_free(group);
+        g_strfreev(keys);
     }
-    res = 0;
-out:
-    loc_pop(&loc);
-    return res;
-}
 
-int qemu_read_config_file(const char *filename)
-{
-    FILE *f = fopen(filename, "r");
-    int ret;
+    g_strfreev(groups);
 
-    if (f == NULL) {
-        return -errno;
-    }
+    g_key_file_free(f);
 
-    ret = qemu_config_parse(f, vm_config_groups, filename);
-    fclose(f);
+    return 0;
+}
 
-    if (ret == 0) {
-        return 0;
-    } else {
-        return -EINVAL;
-    }
+int qemu_read_config_file(const char *filename)
+{
+    return qemu_config_parse(vm_config_groups, filename);
 }
diff --git a/qemu-config.h b/qemu-config.h
index 20d707f..d767d51 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -12,7 +12,7 @@ int qemu_global_option(const char *str);
 void qemu_add_globals(void);
 
 void qemu_config_write(FILE *fp);
-int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname);
+int qemu_config_parse(QemuOptsList **lists, const char *fname);
 
 int qemu_read_config_file(const char *filename);
 
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 3/9] vl: refactor command line parsing to allow options to be set via config
  2012-03-19 15:09 [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Anthony Liguori
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 1/9] qemu-config: fix -writeconfig when using qemu_opt_set_bool Anthony Liguori
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 2/9] qemu-config: friends don't let friends use sscanf Anthony Liguori
@ 2012-03-19 15:09 ` Anthony Liguori
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 4/9] vl: mark system configuration options in qemu-options.hx Anthony Liguori
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 26+ messages in thread
From: Anthony Liguori @ 2012-03-19 15:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Eric Blake, Eduardo Habkost, Gerd Hoffman

This is a lot of code movement but otherwise a straight forward refactoring.
This patch:

 1) Moves the option state that lives in main() into a structure (QemuOptions)

 2) Moves the option parsing code to qemu_parse_options()

 3) Moves the parsing of a single option to qemu_parse_option()

qemu_parse_option() can now be used to set options from a configuration file.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 vl.c | 1869 +++++++++++++++++++++++++++++++++---------------------------------
 1 files changed, 945 insertions(+), 924 deletions(-)

diff --git a/vl.c b/vl.c
index bd95539..18cea4b 100644
--- a/vl.c
+++ b/vl.c
@@ -2251,940 +2251,961 @@ int qemu_init_main_loop(void)
     return main_loop_init();
 }
 
-int main(int argc, char **argv, char **envp)
+typedef struct QemuOptions
 {
-    int i;
-    int snapshot, linux_boot;
-    const char *icount_option = NULL;
-    const char *initrd_filename;
-    const char *kernel_filename, *kernel_cmdline;
-    char boot_devices[33] = "cad"; /* default to HD->floppy->CD-ROM */
-    DisplayState *ds;
-    DisplayChangeListener *dcl;
-    int cyls, heads, secs, translation;
-    QemuOpts *hda_opts = NULL, *opts, *machine_opts;
-    QemuOptsList *olist;
-    int optind;
-    const char *optarg;
-    const char *loadvm = NULL;
     QEMUMachine *machine;
     const char *cpu_model;
-    const char *vga_model = NULL;
-    const char *pid_file = NULL;
-    const char *incoming = NULL;
-#ifdef CONFIG_VNC
-    int show_vnc_port = 0;
-#endif
-    int defconfig = 1;
-    const char *log_mask = NULL;
-    const char *log_file = NULL;
-    GMemVTable mem_trace = {
-        .malloc = malloc_and_trace,
-        .realloc = realloc_and_trace,
-        .free = free_and_trace,
-    };
-    const char *trace_events = NULL;
-    const char *trace_file = NULL;
-
-    atexit(qemu_run_exit_notifiers);
-    error_set_progname(argv[0]);
-
-    g_mem_set_vtable(&mem_trace);
-    if (!g_thread_supported()) {
-#if !GLIB_CHECK_VERSION(2, 31, 0)
-        g_thread_init(NULL);
-#else
-        fprintf(stderr, "glib threading failed to initialize.\n");
-        exit(1);
-#endif
-    }
-
-    module_call_init(MODULE_INIT_QOM);
-
-    runstate_init();
-
-    init_clocks();
-    rtc_clock = host_clock;
-
-    qemu_cache_utils_init(envp);
-
-    QLIST_INIT (&vm_change_state_head);
-    os_setup_early_signal_handling();
-
-    module_call_init(MODULE_INIT_MACHINE);
-    machine = find_default_machine();
-    cpu_model = NULL;
-    ram_size = 0;
-    snapshot = 0;
-    cyls = heads = secs = 0;
-    translation = BIOS_ATA_TRANSLATION_AUTO;
-
-    for (i = 0; i < MAX_NODES; i++) {
-        node_mem[i] = 0;
-        node_cpumask[i] = 0;
-    }
-
-    nb_numa_nodes = 0;
-    nb_nics = 0;
-
-    autostart= 1;
+    int snapshot;
+    char boot_devices[33];
+    const char *log_mask;
+    const char *log_file;
+    const char *vga_model;
+    const char *loadvm;
+    const char *pid_file;
+    const char *icount_option;
+    const char *incoming;
+    const char *trace_events;
+    const char *trace_file;
+
+    QemuOpts *hda_opts;
+    int cyls, heads, secs, translation;
+    int defconfig;
+} QemuOptions;
 
-    /* first pass of option parsing */
-    optind = 1;
-    while (optind < argc) {
-        if (argv[optind][0] != '-') {
-            /* disk image */
-            optind++;
-            continue;
-        } else {
-            const QEMUOption *popt;
+static void qemu_parse_option(int index, const char *optarg, QemuOptions *options)
+{
+    QemuOpts *opts;
+    QemuOptsList *olist;
 
-            popt = lookup_opt(argc, argv, &optarg, &optind);
-            switch (popt->index) {
-            case QEMU_OPTION_nodefconfig:
-                defconfig=0;
-                break;
-            }
+    switch(index) {
+    case QEMU_OPTION_M:
+        options->machine = machine_parse(optarg);
+        break;
+    case QEMU_OPTION_cpu:
+        /* hw initialization will check this */
+        options->cpu_model = optarg;
+        break;
+    case QEMU_OPTION_hda:
+        {
+            char buf[256];
+            if (options->cyls == 0)
+                snprintf(buf, sizeof(buf), "%s", HD_OPTS);
+            else
+                snprintf(buf, sizeof(buf),
+                         "%s,cyls=%d,heads=%d,secs=%d%s",
+                         HD_OPTS , options->cyls, options->heads, options->secs,
+                         options->translation == BIOS_ATA_TRANSLATION_LBA ?
+                         ",trans=lba" :
+                         options->translation == BIOS_ATA_TRANSLATION_NONE ?
+                         ",trans=none" : "");
+            drive_add(IF_DEFAULT, 0, optarg, buf);
+            break;
         }
-    }
-
-    if (defconfig) {
-        int ret;
-
-        ret = qemu_read_config_file(CONFIG_QEMU_CONFDIR "/qemu.conf");
-        if (ret < 0 && ret != -ENOENT) {
+    case QEMU_OPTION_hdb:
+    case QEMU_OPTION_hdc:
+    case QEMU_OPTION_hdd:
+        drive_add(IF_DEFAULT, index - QEMU_OPTION_hda, optarg,
+                  HD_OPTS);
+        break;
+    case QEMU_OPTION_drive:
+        if (drive_def(optarg) == NULL) {
             exit(1);
         }
-
-        ret = qemu_read_config_file(arch_config_name);
-        if (ret < 0 && ret != -ENOENT) {
+        break;
+    case QEMU_OPTION_set:
+        if (qemu_set_option(optarg) != 0)
             exit(1);
-        }
-    }
-
-    /* second pass of option parsing */
-    optind = 1;
-    for(;;) {
-        if (optind >= argc)
-            break;
-        if (argv[optind][0] != '-') {
-	    hda_opts = drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS);
-        } else {
-            const QEMUOption *popt;
-
-            popt = lookup_opt(argc, argv, &optarg, &optind);
-            if (!(popt->arch_mask & arch_type)) {
-                printf("Option %s not supported for this target\n", popt->name);
+        break;
+    case QEMU_OPTION_global:
+        if (qemu_global_option(optarg) != 0)
+            exit(1);
+        break;
+    case QEMU_OPTION_mtdblock:
+        drive_add(IF_MTD, -1, optarg, MTD_OPTS);
+        break;
+    case QEMU_OPTION_sd:
+        drive_add(IF_SD, 0, optarg, SD_OPTS);
+        break;
+    case QEMU_OPTION_pflash:
+        drive_add(IF_PFLASH, -1, optarg, PFLASH_OPTS);
+        break;
+    case QEMU_OPTION_snapshot:
+        options->snapshot = 1;
+        break;
+    case QEMU_OPTION_hdachs:
+        {
+            const char *p;
+            p = optarg;
+            options->cyls = strtol(p, (char **)&p, 0);
+            if (options->cyls < 1 || options->cyls > 16383)
+                goto chs_fail;
+            if (*p != ',')
+                goto chs_fail;
+            p++;
+            options->heads = strtol(p, (char **)&p, 0);
+            if (options->heads < 1 || options->heads > 16)
+                goto chs_fail;
+            if (*p != ',')
+                goto chs_fail;
+            p++;
+            options->secs = strtol(p, (char **)&p, 0);
+            if (options->secs < 1 || options->secs > 63)
+                goto chs_fail;
+            if (*p == ',') {
+                p++;
+                if (!strcmp(p, "none"))
+                    options->translation = BIOS_ATA_TRANSLATION_NONE;
+                else if (!strcmp(p, "lba"))
+                    options->translation = BIOS_ATA_TRANSLATION_LBA;
+                else if (!strcmp(p, "auto"))
+                    options->translation = BIOS_ATA_TRANSLATION_AUTO;
+                else
+                    goto chs_fail;
+            } else if (*p != '\0') {
+            chs_fail:
+                fprintf(stderr, "qemu: invalid physical CHS format\n");
                 exit(1);
             }
-            switch(popt->index) {
-            case QEMU_OPTION_M:
-                machine = machine_parse(optarg);
-                break;
-            case QEMU_OPTION_cpu:
-                /* hw initialization will check this */
-                cpu_model = optarg;
-                break;
-            case QEMU_OPTION_hda:
-                {
-                    char buf[256];
-                    if (cyls == 0)
-                        snprintf(buf, sizeof(buf), "%s", HD_OPTS);
-                    else
-                        snprintf(buf, sizeof(buf),
-                                 "%s,cyls=%d,heads=%d,secs=%d%s",
-                                 HD_OPTS , cyls, heads, secs,
-                                 translation == BIOS_ATA_TRANSLATION_LBA ?
-                                 ",trans=lba" :
-                                 translation == BIOS_ATA_TRANSLATION_NONE ?
-                                 ",trans=none" : "");
-                    drive_add(IF_DEFAULT, 0, optarg, buf);
-                    break;
-                }
-            case QEMU_OPTION_hdb:
-            case QEMU_OPTION_hdc:
-            case QEMU_OPTION_hdd:
-                drive_add(IF_DEFAULT, popt->index - QEMU_OPTION_hda, optarg,
-                          HD_OPTS);
-                break;
-            case QEMU_OPTION_drive:
-                if (drive_def(optarg) == NULL) {
-                    exit(1);
-                }
-	        break;
-            case QEMU_OPTION_set:
-                if (qemu_set_option(optarg) != 0)
-                    exit(1);
-	        break;
-            case QEMU_OPTION_global:
-                if (qemu_global_option(optarg) != 0)
-                    exit(1);
-	        break;
-            case QEMU_OPTION_mtdblock:
-                drive_add(IF_MTD, -1, optarg, MTD_OPTS);
-                break;
-            case QEMU_OPTION_sd:
-                drive_add(IF_SD, 0, optarg, SD_OPTS);
-                break;
-            case QEMU_OPTION_pflash:
-                drive_add(IF_PFLASH, -1, optarg, PFLASH_OPTS);
-                break;
-            case QEMU_OPTION_snapshot:
-                snapshot = 1;
-                break;
-            case QEMU_OPTION_hdachs:
-                {
-                    const char *p;
-                    p = optarg;
-                    cyls = strtol(p, (char **)&p, 0);
-                    if (cyls < 1 || cyls > 16383)
-                        goto chs_fail;
-                    if (*p != ',')
-                        goto chs_fail;
-                    p++;
-                    heads = strtol(p, (char **)&p, 0);
-                    if (heads < 1 || heads > 16)
-                        goto chs_fail;
-                    if (*p != ',')
-                        goto chs_fail;
-                    p++;
-                    secs = strtol(p, (char **)&p, 0);
-                    if (secs < 1 || secs > 63)
-                        goto chs_fail;
-                    if (*p == ',') {
-                        p++;
-                        if (!strcmp(p, "none"))
-                            translation = BIOS_ATA_TRANSLATION_NONE;
-                        else if (!strcmp(p, "lba"))
-                            translation = BIOS_ATA_TRANSLATION_LBA;
-                        else if (!strcmp(p, "auto"))
-                            translation = BIOS_ATA_TRANSLATION_AUTO;
-                        else
-                            goto chs_fail;
-                    } else if (*p != '\0') {
-                    chs_fail:
-                        fprintf(stderr, "qemu: invalid physical CHS format\n");
-                        exit(1);
-                    }
-		    if (hda_opts != NULL) {
-                        char num[16];
-                        snprintf(num, sizeof(num), "%d", cyls);
-                        qemu_opt_set(hda_opts, "cyls", num);
-                        snprintf(num, sizeof(num), "%d", heads);
-                        qemu_opt_set(hda_opts, "heads", num);
-                        snprintf(num, sizeof(num), "%d", secs);
-                        qemu_opt_set(hda_opts, "secs", num);
-                        if (translation == BIOS_ATA_TRANSLATION_LBA)
-                            qemu_opt_set(hda_opts, "trans", "lba");
-                        if (translation == BIOS_ATA_TRANSLATION_NONE)
-                            qemu_opt_set(hda_opts, "trans", "none");
-                    }
-                }
-                break;
-            case QEMU_OPTION_numa:
-                if (nb_numa_nodes >= MAX_NODES) {
-                    fprintf(stderr, "qemu: too many NUMA nodes\n");
-                    exit(1);
-                }
-                numa_add(optarg);
-                break;
-            case QEMU_OPTION_display:
-                display_type = select_display(optarg);
-                break;
-            case QEMU_OPTION_nographic:
-                display_type = DT_NOGRAPHIC;
-                break;
-            case QEMU_OPTION_curses:
+            if (options->hda_opts != NULL) {
+                char num[16];
+                snprintf(num, sizeof(num), "%d", options->cyls);
+                qemu_opt_set(options->hda_opts, "cyls", num);
+                snprintf(num, sizeof(num), "%d", options->heads);
+                qemu_opt_set(options->hda_opts, "heads", num);
+                snprintf(num, sizeof(num), "%d", options->secs);
+                qemu_opt_set(options->hda_opts, "secs", num);
+                if (options->translation == BIOS_ATA_TRANSLATION_LBA)
+                    qemu_opt_set(options->hda_opts, "trans", "lba");
+                if (options->translation == BIOS_ATA_TRANSLATION_NONE)
+                    qemu_opt_set(options->hda_opts, "trans", "none");
+            }
+        }
+        break;
+    case QEMU_OPTION_numa:
+        if (nb_numa_nodes >= MAX_NODES) {
+            fprintf(stderr, "qemu: too many NUMA nodes\n");
+            exit(1);
+        }
+        numa_add(optarg);
+        break;
+    case QEMU_OPTION_display:
+        display_type = select_display(optarg);
+        break;
+    case QEMU_OPTION_nographic:
+        display_type = DT_NOGRAPHIC;
+        break;
+    case QEMU_OPTION_curses:
 #ifdef CONFIG_CURSES
-                display_type = DT_CURSES;
+        display_type = DT_CURSES;
 #else
-                fprintf(stderr, "Curses support is disabled\n");
-                exit(1);
+        fprintf(stderr, "Curses support is disabled\n");
+        exit(1);
 #endif
-                break;
-            case QEMU_OPTION_portrait:
-                graphic_rotate = 90;
-                break;
-            case QEMU_OPTION_rotate:
-                graphic_rotate = strtol(optarg, (char **) &optarg, 10);
-                if (graphic_rotate != 0 && graphic_rotate != 90 &&
-                    graphic_rotate != 180 && graphic_rotate != 270) {
-                    fprintf(stderr,
-                        "qemu: only 90, 180, 270 deg rotation is available\n");
-                    exit(1);
+        break;
+    case QEMU_OPTION_portrait:
+        graphic_rotate = 90;
+        break;
+    case QEMU_OPTION_rotate:
+        graphic_rotate = strtol(optarg, (char **) &optarg, 10);
+        if (graphic_rotate != 0 && graphic_rotate != 90 &&
+            graphic_rotate != 180 && graphic_rotate != 270) {
+            fprintf(stderr,
+                "qemu: only 90, 180, 270 deg rotation is available\n");
+            exit(1);
+        }
+        break;
+    case QEMU_OPTION_kernel:
+        qemu_opts_set(qemu_find_opts("machine"), 0, "kernel", optarg);
+        break;
+    case QEMU_OPTION_initrd:
+        qemu_opts_set(qemu_find_opts("machine"), 0, "initrd", optarg);
+        break;
+    case QEMU_OPTION_append:
+        qemu_opts_set(qemu_find_opts("machine"), 0, "append", optarg);
+        break;
+    case QEMU_OPTION_dtb:
+        qemu_opts_set(qemu_find_opts("machine"), 0, "dtb", optarg);
+        break;
+    case QEMU_OPTION_cdrom:
+        drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS);
+        break;
+    case QEMU_OPTION_boot:
+        {
+            static const char * const params[] = {
+                "order", "once", "menu",
+                "splash", "splash-time", NULL
+            };
+            char buf[sizeof(options->boot_devices)];
+            char *standard_boot_devices;
+            int legacy = 0;
+
+            if (!strchr(optarg, '=')) {
+                legacy = 1;
+                pstrcpy(buf, sizeof(buf), optarg);
+            } else if (check_params(buf, sizeof(buf), params, optarg) < 0) {
+                fprintf(stderr,
+                        "qemu: unknown boot parameter '%s' in '%s'\n",
+                        buf, optarg);
+                exit(1);
+            }
+
+            if (legacy ||
+                get_param_value(buf, sizeof(buf), "order", optarg)) {
+                validate_bootdevices(buf);
+                pstrcpy(options->boot_devices, sizeof(options->boot_devices), buf);
+            }
+            if (!legacy) {
+                if (get_param_value(buf, sizeof(buf),
+                                    "once", optarg)) {
+                    validate_bootdevices(buf);
+                    standard_boot_devices = g_strdup(options->boot_devices);
+                    pstrcpy(options->boot_devices, sizeof(options->boot_devices), buf);
+                    qemu_register_reset(restore_boot_devices,
+                                        standard_boot_devices);
                 }
-                break;
-            case QEMU_OPTION_kernel:
-                qemu_opts_set(qemu_find_opts("machine"), 0, "kernel", optarg);
-                break;
-            case QEMU_OPTION_initrd:
-                qemu_opts_set(qemu_find_opts("machine"), 0, "initrd", optarg);
-                break;
-            case QEMU_OPTION_append:
-                qemu_opts_set(qemu_find_opts("machine"), 0, "append", optarg);
-                break;
-            case QEMU_OPTION_dtb:
-                qemu_opts_set(qemu_find_opts("machine"), 0, "dtb", optarg);
-                break;
-            case QEMU_OPTION_cdrom:
-                drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS);
-                break;
-            case QEMU_OPTION_boot:
-                {
-                    static const char * const params[] = {
-                        "order", "once", "menu",
-                        "splash", "splash-time", NULL
-                    };
-                    char buf[sizeof(boot_devices)];
-                    char *standard_boot_devices;
-                    int legacy = 0;
-
-                    if (!strchr(optarg, '=')) {
-                        legacy = 1;
-                        pstrcpy(buf, sizeof(buf), optarg);
-                    } else if (check_params(buf, sizeof(buf), params, optarg) < 0) {
+                if (get_param_value(buf, sizeof(buf),
+                                    "menu", optarg)) {
+                    if (!strcmp(buf, "on")) {
+                        boot_menu = 1;
+                    } else if (!strcmp(buf, "off")) {
+                        boot_menu = 0;
+                    } else {
                         fprintf(stderr,
-                                "qemu: unknown boot parameter '%s' in '%s'\n",
-                                buf, optarg);
+                                "qemu: invalid option value '%s'\n",
+                                buf);
                         exit(1);
                     }
-
-                    if (legacy ||
-                        get_param_value(buf, sizeof(buf), "order", optarg)) {
-                        validate_bootdevices(buf);
-                        pstrcpy(boot_devices, sizeof(boot_devices), buf);
-                    }
-                    if (!legacy) {
-                        if (get_param_value(buf, sizeof(buf),
-                                            "once", optarg)) {
-                            validate_bootdevices(buf);
-                            standard_boot_devices = g_strdup(boot_devices);
-                            pstrcpy(boot_devices, sizeof(boot_devices), buf);
-                            qemu_register_reset(restore_boot_devices,
-                                                standard_boot_devices);
-                        }
-                        if (get_param_value(buf, sizeof(buf),
-                                            "menu", optarg)) {
-                            if (!strcmp(buf, "on")) {
-                                boot_menu = 1;
-                            } else if (!strcmp(buf, "off")) {
-                                boot_menu = 0;
-                            } else {
-                                fprintf(stderr,
-                                        "qemu: invalid option value '%s'\n",
-                                        buf);
-                                exit(1);
-                            }
-                        }
-                        qemu_opts_parse(qemu_find_opts("boot-opts"),
-                                        optarg, 0);
-                    }
                 }
-                break;
-            case QEMU_OPTION_fda:
-            case QEMU_OPTION_fdb:
-                drive_add(IF_FLOPPY, popt->index - QEMU_OPTION_fda,
-                          optarg, FD_OPTS);
-                break;
-            case QEMU_OPTION_no_fd_bootchk:
-                fd_bootchk = 0;
-                break;
-            case QEMU_OPTION_netdev:
-                if (net_client_parse(qemu_find_opts("netdev"), optarg) == -1) {
-                    exit(1);
-                }
-                break;
-            case QEMU_OPTION_net:
-                if (net_client_parse(qemu_find_opts("net"), optarg) == -1) {
-                    exit(1);
-                }
-                break;
+                qemu_opts_parse(qemu_find_opts("boot-opts"),
+                                optarg, 0);
+            }
+        }
+        break;
+    case QEMU_OPTION_fda:
+    case QEMU_OPTION_fdb:
+        drive_add(IF_FLOPPY, index - QEMU_OPTION_fda,
+                  optarg, FD_OPTS);
+        break;
+    case QEMU_OPTION_no_fd_bootchk:
+        fd_bootchk = 0;
+        break;
+    case QEMU_OPTION_netdev:
+        if (net_client_parse(qemu_find_opts("netdev"), optarg) == -1) {
+            exit(1);
+        }
+        break;
+    case QEMU_OPTION_net:
+        if (net_client_parse(qemu_find_opts("net"), optarg) == -1) {
+            exit(1);
+        }
+        break;
 #ifdef CONFIG_LIBISCSI
-            case QEMU_OPTION_iscsi:
-                opts = qemu_opts_parse(qemu_find_opts("iscsi"), optarg, 0);
-                if (!opts) {
-                    exit(1);
-                }
-                break;
+    case QEMU_OPTION_iscsi:
+        opts = qemu_opts_parse(qemu_find_opts("iscsi"), optarg, 0);
+        if (!opts) {
+            exit(1);
+        }
+        break;
 #endif
 #ifdef CONFIG_SLIRP
-            case QEMU_OPTION_tftp:
-                legacy_tftp_prefix = optarg;
-                break;
-            case QEMU_OPTION_bootp:
-                legacy_bootp_filename = optarg;
-                break;
-            case QEMU_OPTION_redir:
-                if (net_slirp_redir(optarg) < 0)
-                    exit(1);
-                break;
+    case QEMU_OPTION_tftp:
+        legacy_tftp_prefix = optarg;
+        break;
+    case QEMU_OPTION_bootp:
+        legacy_bootp_filename = optarg;
+        break;
+    case QEMU_OPTION_redir:
+        if (net_slirp_redir(optarg) < 0)
+            exit(1);
+        break;
 #endif
-            case QEMU_OPTION_bt:
-                add_device_config(DEV_BT, optarg);
-                break;
-            case QEMU_OPTION_audio_help:
-                if (!(audio_available())) {
-                    printf("Option %s not supported for this target\n", popt->name);
-                    exit(1);
-                }
-                AUD_help ();
-                exit (0);
-                break;
-            case QEMU_OPTION_soundhw:
-                if (!(audio_available())) {
-                    printf("Option %s not supported for this target\n", popt->name);
-                    exit(1);
-                }
-                select_soundhw (optarg);
-                break;
-            case QEMU_OPTION_h:
-                help(0);
-                break;
-            case QEMU_OPTION_version:
-                version();
-                exit(0);
-                break;
-            case QEMU_OPTION_m: {
-                int64_t value;
-                char *end;
+    case QEMU_OPTION_bt:
+        add_device_config(DEV_BT, optarg);
+        break;
+    case QEMU_OPTION_audio_help:
+        if (!(audio_available())) {
+            printf("Option audio_help not supported for this target\n");
+            exit(1);
+        }
+        AUD_help ();
+        exit (0);
+        break;
+    case QEMU_OPTION_soundhw:
+        if (!(audio_available())) {
+            printf("Option soudhw not supported for this target\n");
+            exit(1);
+        }
+        select_soundhw (optarg);
+        break;
+    case QEMU_OPTION_h:
+        help(0);
+        break;
+    case QEMU_OPTION_version:
+        version();
+        exit(0);
+        break;
+    case QEMU_OPTION_m: {
+        int64_t value;
+        char *end;
 
-                value = strtosz(optarg, &end);
-                if (value < 0 || *end) {
-                    fprintf(stderr, "qemu: invalid ram size: %s\n", optarg);
-                    exit(1);
-                }
+        value = strtosz(optarg, &end);
+        if (value < 0 || *end) {
+            fprintf(stderr, "qemu: invalid ram size: %s\n", optarg);
+            exit(1);
+        }
 
-                if (value != (uint64_t)(ram_addr_t)value) {
-                    fprintf(stderr, "qemu: ram size too large\n");
-                    exit(1);
-                }
-                ram_size = value;
-                break;
-            }
-            case QEMU_OPTION_mempath:
-                mem_path = optarg;
-                break;
+        if (value != (uint64_t)(ram_addr_t)value) {
+            fprintf(stderr, "qemu: ram size too large\n");
+            exit(1);
+        }
+        ram_size = value;
+        break;
+    }
+    case QEMU_OPTION_mempath:
+        mem_path = optarg;
+        break;
 #ifdef MAP_POPULATE
-            case QEMU_OPTION_mem_prealloc:
-                mem_prealloc = 1;
-                break;
+    case QEMU_OPTION_mem_prealloc:
+        mem_prealloc = 1;
+        break;
 #endif
-            case QEMU_OPTION_d:
-                log_mask = optarg;
-                break;
-            case QEMU_OPTION_D:
-                log_file = optarg;
-                break;
-            case QEMU_OPTION_s:
-                add_device_config(DEV_GDB, "tcp::" DEFAULT_GDBSTUB_PORT);
-                break;
-            case QEMU_OPTION_gdb:
-                add_device_config(DEV_GDB, optarg);
-                break;
-            case QEMU_OPTION_L:
-                data_dir = optarg;
-                break;
-            case QEMU_OPTION_bios:
-                bios_name = optarg;
-                break;
-            case QEMU_OPTION_singlestep:
-                singlestep = 1;
-                break;
-            case QEMU_OPTION_S:
-                autostart = 0;
-                break;
-	    case QEMU_OPTION_k:
-		keyboard_layout = optarg;
-		break;
-            case QEMU_OPTION_localtime:
-                rtc_utc = 0;
-                break;
-            case QEMU_OPTION_vga:
-                vga_model = optarg;
-                break;
-            case QEMU_OPTION_g:
-                {
-                    const char *p;
-                    int w, h, depth;
-                    p = optarg;
-                    w = strtol(p, (char **)&p, 10);
-                    if (w <= 0) {
-                    graphic_error:
-                        fprintf(stderr, "qemu: invalid resolution or depth\n");
-                        exit(1);
-                    }
-                    if (*p != 'x')
-                        goto graphic_error;
-                    p++;
-                    h = strtol(p, (char **)&p, 10);
-                    if (h <= 0)
-                        goto graphic_error;
-                    if (*p == 'x') {
-                        p++;
-                        depth = strtol(p, (char **)&p, 10);
-                        if (depth != 8 && depth != 15 && depth != 16 &&
-                            depth != 24 && depth != 32)
-                            goto graphic_error;
-                    } else if (*p == '\0') {
-                        depth = graphic_depth;
-                    } else {
-                        goto graphic_error;
-                    }
+    case QEMU_OPTION_d:
+        options->log_mask = optarg;
+        break;
+    case QEMU_OPTION_D:
+        options->log_file = optarg;
+        break;
+    case QEMU_OPTION_s:
+        add_device_config(DEV_GDB, "tcp::" DEFAULT_GDBSTUB_PORT);
+        break;
+    case QEMU_OPTION_gdb:
+        add_device_config(DEV_GDB, optarg);
+        break;
+    case QEMU_OPTION_L:
+        data_dir = optarg;
+        break;
+    case QEMU_OPTION_bios:
+        bios_name = optarg;
+        break;
+    case QEMU_OPTION_singlestep:
+        singlestep = 1;
+        break;
+    case QEMU_OPTION_S:
+        autostart = 0;
+        break;
+    case QEMU_OPTION_k:
+        keyboard_layout = optarg;
+        break;
+    case QEMU_OPTION_localtime:
+        rtc_utc = 0;
+        break;
+    case QEMU_OPTION_vga:
+        options->vga_model = optarg;
+        break;
+    case QEMU_OPTION_g:
+        {
+            const char *p;
+            int w, h, depth;
+            p = optarg;
+            w = strtol(p, (char **)&p, 10);
+            if (w <= 0) {
+            graphic_error:
+                fprintf(stderr, "qemu: invalid resolution or depth\n");
+                exit(1);
+            }
+            if (*p != 'x')
+                goto graphic_error;
+            p++;
+            h = strtol(p, (char **)&p, 10);
+            if (h <= 0)
+                goto graphic_error;
+            if (*p == 'x') {
+                p++;
+                depth = strtol(p, (char **)&p, 10);
+                if (depth != 8 && depth != 15 && depth != 16 &&
+                    depth != 24 && depth != 32)
+                    goto graphic_error;
+            } else if (*p == '\0') {
+                depth = graphic_depth;
+            } else {
+                goto graphic_error;
+            }
 
-                    graphic_width = w;
-                    graphic_height = h;
-                    graphic_depth = depth;
-                }
-                break;
-            case QEMU_OPTION_echr:
-                {
-                    char *r;
-                    term_escape_char = strtol(optarg, &r, 0);
-                    if (r == optarg)
-                        printf("Bad argument to echr\n");
-                    break;
-                }
-            case QEMU_OPTION_monitor:
-                monitor_parse(optarg, "readline");
-                default_monitor = 0;
-                break;
-            case QEMU_OPTION_qmp:
-                monitor_parse(optarg, "control");
-                default_monitor = 0;
-                break;
-            case QEMU_OPTION_mon:
-                opts = qemu_opts_parse(qemu_find_opts("mon"), optarg, 1);
-                if (!opts) {
-                    exit(1);
-                }
-                default_monitor = 0;
-                break;
-            case QEMU_OPTION_chardev:
-                opts = qemu_opts_parse(qemu_find_opts("chardev"), optarg, 1);
-                if (!opts) {
-                    exit(1);
-                }
-                break;
-            case QEMU_OPTION_fsdev:
-                olist = qemu_find_opts("fsdev");
-                if (!olist) {
-                    fprintf(stderr, "fsdev is not supported by this qemu build.\n");
-                    exit(1);
-                }
-                opts = qemu_opts_parse(olist, optarg, 1);
-                if (!opts) {
-                    fprintf(stderr, "parse error: %s\n", optarg);
-                    exit(1);
-                }
-                break;
-            case QEMU_OPTION_virtfs: {
-                QemuOpts *fsdev;
-                QemuOpts *device;
-                const char *writeout, *sock_fd, *socket;
-
-                olist = qemu_find_opts("virtfs");
-                if (!olist) {
-                    fprintf(stderr, "virtfs is not supported by this qemu build.\n");
-                    exit(1);
-                }
-                opts = qemu_opts_parse(olist, optarg, 1);
-                if (!opts) {
-                    fprintf(stderr, "parse error: %s\n", optarg);
-                    exit(1);
-                }
+            graphic_width = w;
+            graphic_height = h;
+            graphic_depth = depth;
+        }
+        break;
+    case QEMU_OPTION_echr:
+        {
+            char *r;
+            term_escape_char = strtol(optarg, &r, 0);
+            if (r == optarg)
+                printf("Bad argument to echr\n");
+            break;
+        }
+    case QEMU_OPTION_monitor:
+        monitor_parse(optarg, "readline");
+        default_monitor = 0;
+        break;
+    case QEMU_OPTION_qmp:
+        monitor_parse(optarg, "control");
+        default_monitor = 0;
+        break;
+    case QEMU_OPTION_mon:
+        opts = qemu_opts_parse(qemu_find_opts("mon"), optarg, 1);
+        if (!opts) {
+            exit(1);
+        }
+        default_monitor = 0;
+        break;
+    case QEMU_OPTION_chardev:
+        opts = qemu_opts_parse(qemu_find_opts("chardev"), optarg, 1);
+        if (!opts) {
+            exit(1);
+        }
+        break;
+    case QEMU_OPTION_fsdev:
+        olist = qemu_find_opts("fsdev");
+        if (!olist) {
+            fprintf(stderr, "fsdev is not supported by this qemu build.\n");
+            exit(1);
+        }
+        opts = qemu_opts_parse(olist, optarg, 1);
+        if (!opts) {
+            fprintf(stderr, "parse error: %s\n", optarg);
+            exit(1);
+        }
+        break;
+    case QEMU_OPTION_virtfs: {
+        QemuOpts *fsdev;
+        QemuOpts *device;
+        const char *writeout, *sock_fd, *socket;
+
+        olist = qemu_find_opts("virtfs");
+        if (!olist) {
+            fprintf(stderr, "virtfs is not supported by this qemu build.\n");
+            exit(1);
+        }
+        opts = qemu_opts_parse(olist, optarg, 1);
+        if (!opts) {
+            fprintf(stderr, "parse error: %s\n", optarg);
+            exit(1);
+        }
 
-                if (qemu_opt_get(opts, "fsdriver") == NULL ||
-                    qemu_opt_get(opts, "mount_tag") == NULL) {
-                    fprintf(stderr, "Usage: -virtfs fsdriver,mount_tag=tag.\n");
-                    exit(1);
-                }
-                fsdev = qemu_opts_create(qemu_find_opts("fsdev"),
-                                         qemu_opt_get(opts, "mount_tag"), 1);
-                if (!fsdev) {
-                    fprintf(stderr, "duplicate fsdev id: %s\n",
-                            qemu_opt_get(opts, "mount_tag"));
-                    exit(1);
-                }
+        if (qemu_opt_get(opts, "fsdriver") == NULL ||
+            qemu_opt_get(opts, "mount_tag") == NULL) {
+            fprintf(stderr, "Usage: -virtfs fsdriver,mount_tag=tag.\n");
+            exit(1);
+        }
+        fsdev = qemu_opts_create(qemu_find_opts("fsdev"),
+                                 qemu_opt_get(opts, "mount_tag"), 1);
+        if (!fsdev) {
+            fprintf(stderr, "duplicate fsdev id: %s\n",
+                    qemu_opt_get(opts, "mount_tag"));
+            exit(1);
+        }
 
-                writeout = qemu_opt_get(opts, "writeout");
-                if (writeout) {
+        writeout = qemu_opt_get(opts, "writeout");
+        if (writeout) {
 #ifdef CONFIG_SYNC_FILE_RANGE
-                    qemu_opt_set(fsdev, "writeout", writeout);
+            qemu_opt_set(fsdev, "writeout", writeout);
 #else
-                    fprintf(stderr, "writeout=immediate not supported on "
-                            "this platform\n");
-                    exit(1);
+            fprintf(stderr, "writeout=immediate not supported on "
+                    "this platform\n");
+            exit(1);
 #endif
-                }
-                qemu_opt_set(fsdev, "fsdriver", qemu_opt_get(opts, "fsdriver"));
-                qemu_opt_set(fsdev, "path", qemu_opt_get(opts, "path"));
-                qemu_opt_set(fsdev, "security_model",
-                             qemu_opt_get(opts, "security_model"));
-                socket = qemu_opt_get(opts, "socket");
-                if (socket) {
-                    qemu_opt_set(fsdev, "socket", socket);
-                }
-                sock_fd = qemu_opt_get(opts, "sock_fd");
-                if (sock_fd) {
-                    qemu_opt_set(fsdev, "sock_fd", sock_fd);
-                }
+        }
+        qemu_opt_set(fsdev, "fsdriver", qemu_opt_get(opts, "fsdriver"));
+        qemu_opt_set(fsdev, "path", qemu_opt_get(opts, "path"));
+        qemu_opt_set(fsdev, "security_model",
+                     qemu_opt_get(opts, "security_model"));
+        socket = qemu_opt_get(opts, "socket");
+        if (socket) {
+            qemu_opt_set(fsdev, "socket", socket);
+        }
+        sock_fd = qemu_opt_get(opts, "sock_fd");
+        if (sock_fd) {
+            qemu_opt_set(fsdev, "sock_fd", sock_fd);
+        }
 
-                qemu_opt_set_bool(fsdev, "readonly",
-                                qemu_opt_get_bool(opts, "readonly", 0));
-                device = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
-                qemu_opt_set(device, "driver", "virtio-9p-pci");
-                qemu_opt_set(device, "fsdev",
-                             qemu_opt_get(opts, "mount_tag"));
-                qemu_opt_set(device, "mount_tag",
-                             qemu_opt_get(opts, "mount_tag"));
-                break;
-            }
-            case QEMU_OPTION_virtfs_synth: {
-                QemuOpts *fsdev;
-                QemuOpts *device;
+        qemu_opt_set_bool(fsdev, "readonly",
+                        qemu_opt_get_bool(opts, "readonly", 0));
+        device = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+        qemu_opt_set(device, "driver", "virtio-9p-pci");
+        qemu_opt_set(device, "fsdev",
+                     qemu_opt_get(opts, "mount_tag"));
+        qemu_opt_set(device, "mount_tag",
+                     qemu_opt_get(opts, "mount_tag"));
+        break;
+    }
+    case QEMU_OPTION_virtfs_synth: {
+        QemuOpts *fsdev;
+        QemuOpts *device;
 
-                fsdev = qemu_opts_create(qemu_find_opts("fsdev"), "v_synth", 1);
-                if (!fsdev) {
-                    fprintf(stderr, "duplicate option: %s\n", "virtfs_synth");
-                    exit(1);
-                }
-                qemu_opt_set(fsdev, "fsdriver", "synth");
+        fsdev = qemu_opts_create(qemu_find_opts("fsdev"), "v_synth", 1);
+        if (!fsdev) {
+            fprintf(stderr, "duplicate option: %s\n", "virtfs_synth");
+            exit(1);
+        }
+        qemu_opt_set(fsdev, "fsdriver", "synth");
 
-                device = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
-                qemu_opt_set(device, "driver", "virtio-9p-pci");
-                qemu_opt_set(device, "fsdev", "v_synth");
-                qemu_opt_set(device, "mount_tag", "v_synth");
-                break;
-            }
-            case QEMU_OPTION_serial:
-                add_device_config(DEV_SERIAL, optarg);
-                default_serial = 0;
-                if (strncmp(optarg, "mon:", 4) == 0) {
-                    default_monitor = 0;
-                }
-                break;
-            case QEMU_OPTION_watchdog:
-                if (watchdog) {
-                    fprintf(stderr,
-                            "qemu: only one watchdog option may be given\n");
-                    return 1;
-                }
-                watchdog = optarg;
-                break;
-            case QEMU_OPTION_watchdog_action:
-                if (select_watchdog_action(optarg) == -1) {
-                    fprintf(stderr, "Unknown -watchdog-action parameter\n");
-                    exit(1);
-                }
-                break;
-            case QEMU_OPTION_virtiocon:
-                add_device_config(DEV_VIRTCON, optarg);
-                default_virtcon = 0;
-                if (strncmp(optarg, "mon:", 4) == 0) {
-                    default_monitor = 0;
-                }
-                break;
-            case QEMU_OPTION_parallel:
-                add_device_config(DEV_PARALLEL, optarg);
-                default_parallel = 0;
-                if (strncmp(optarg, "mon:", 4) == 0) {
-                    default_monitor = 0;
-                }
-                break;
-            case QEMU_OPTION_debugcon:
-                add_device_config(DEV_DEBUGCON, optarg);
-                break;
-	    case QEMU_OPTION_loadvm:
-		loadvm = optarg;
-		break;
-            case QEMU_OPTION_full_screen:
-                full_screen = 1;
-                break;
+        device = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+        qemu_opt_set(device, "driver", "virtio-9p-pci");
+        qemu_opt_set(device, "fsdev", "v_synth");
+        qemu_opt_set(device, "mount_tag", "v_synth");
+        break;
+    }
+    case QEMU_OPTION_serial:
+        add_device_config(DEV_SERIAL, optarg);
+        default_serial = 0;
+        if (strncmp(optarg, "mon:", 4) == 0) {
+            default_monitor = 0;
+        }
+        break;
+    case QEMU_OPTION_watchdog:
+        if (watchdog) {
+            fprintf(stderr,
+                    "qemu: only one watchdog option may be given\n");
+            exit(1);
+        }
+        watchdog = optarg;
+        break;
+    case QEMU_OPTION_watchdog_action:
+        if (select_watchdog_action(optarg) == -1) {
+            fprintf(stderr, "Unknown -watchdog-action parameter\n");
+            exit(1);
+        }
+        break;
+    case QEMU_OPTION_virtiocon:
+        add_device_config(DEV_VIRTCON, optarg);
+        default_virtcon = 0;
+        if (strncmp(optarg, "mon:", 4) == 0) {
+            default_monitor = 0;
+        }
+        break;
+    case QEMU_OPTION_parallel:
+        add_device_config(DEV_PARALLEL, optarg);
+        default_parallel = 0;
+        if (strncmp(optarg, "mon:", 4) == 0) {
+            default_monitor = 0;
+        }
+        break;
+    case QEMU_OPTION_debugcon:
+        add_device_config(DEV_DEBUGCON, optarg);
+        break;
+    case QEMU_OPTION_loadvm:
+        options->loadvm = optarg;
+        break;
+    case QEMU_OPTION_full_screen:
+        full_screen = 1;
+        break;
 #ifdef CONFIG_SDL
-            case QEMU_OPTION_no_frame:
-                no_frame = 1;
-                break;
-            case QEMU_OPTION_alt_grab:
-                alt_grab = 1;
-                break;
-            case QEMU_OPTION_ctrl_grab:
-                ctrl_grab = 1;
-                break;
-            case QEMU_OPTION_no_quit:
-                no_quit = 1;
-                break;
-            case QEMU_OPTION_sdl:
-                display_type = DT_SDL;
-                break;
+    case QEMU_OPTION_no_frame:
+        no_frame = 1;
+        break;
+    case QEMU_OPTION_alt_grab:
+        alt_grab = 1;
+        break;
+    case QEMU_OPTION_ctrl_grab:
+        ctrl_grab = 1;
+        break;
+    case QEMU_OPTION_no_quit:
+        no_quit = 1;
+        break;
+    case QEMU_OPTION_sdl:
+        display_type = DT_SDL;
+        break;
 #else
-            case QEMU_OPTION_no_frame:
-            case QEMU_OPTION_alt_grab:
-            case QEMU_OPTION_ctrl_grab:
-            case QEMU_OPTION_no_quit:
-            case QEMU_OPTION_sdl:
-                fprintf(stderr, "SDL support is disabled\n");
-                exit(1);
+    case QEMU_OPTION_no_frame:
+    case QEMU_OPTION_alt_grab:
+    case QEMU_OPTION_ctrl_grab:
+    case QEMU_OPTION_no_quit:
+    case QEMU_OPTION_sdl:
+        fprintf(stderr, "SDL support is disabled\n");
+        exit(1);
 #endif
-            case QEMU_OPTION_pidfile:
-                pid_file = optarg;
-                break;
-            case QEMU_OPTION_win2k_hack:
-                win2k_install_hack = 1;
-                break;
-            case QEMU_OPTION_rtc_td_hack: {
-                static GlobalProperty slew_lost_ticks[] = {
-                    {
-                        .driver   = "mc146818rtc",
-                        .property = "lost_tick_policy",
-                        .value    = "slew",
-                    },
-                    { /* end of list */ }
-                };
-
-                qdev_prop_register_global_list(slew_lost_ticks);
-                break;
-            }
-            case QEMU_OPTION_acpitable:
-                do_acpitable_option(optarg);
-                break;
-            case QEMU_OPTION_smbios:
-                do_smbios_option(optarg);
-                break;
-            case QEMU_OPTION_enable_kvm:
-                olist = qemu_find_opts("machine");
-                qemu_opts_parse(olist, "accel=kvm", 0);
-                break;
-            case QEMU_OPTION_machine:
-                olist = qemu_find_opts("machine");
-                opts = qemu_opts_parse(olist, optarg, 1);
-                if (!opts) {
-                    fprintf(stderr, "parse error: %s\n", optarg);
-                    exit(1);
-                }
-                optarg = qemu_opt_get(opts, "type");
-                if (optarg) {
-                    machine = machine_parse(optarg);
-                }
-                break;
-            case QEMU_OPTION_usb:
-                usb_enabled = 1;
-                break;
-            case QEMU_OPTION_usbdevice:
-                usb_enabled = 1;
-                add_device_config(DEV_USB, optarg);
-                break;
-            case QEMU_OPTION_device:
-                if (!qemu_opts_parse(qemu_find_opts("device"), optarg, 1)) {
-                    exit(1);
-                }
-                break;
-            case QEMU_OPTION_smp:
-                smp_parse(optarg);
-                if (smp_cpus < 1) {
-                    fprintf(stderr, "Invalid number of CPUs\n");
-                    exit(1);
-                }
-                if (max_cpus < smp_cpus) {
-                    fprintf(stderr, "maxcpus must be equal to or greater than "
-                            "smp\n");
-                    exit(1);
-                }
-                if (max_cpus > 255) {
-                    fprintf(stderr, "Unsupported number of maxcpus\n");
-                    exit(1);
-                }
-                break;
-	    case QEMU_OPTION_vnc:
+    case QEMU_OPTION_pidfile:
+        options->pid_file = optarg;
+        break;
+    case QEMU_OPTION_win2k_hack:
+        win2k_install_hack = 1;
+        break;
+    case QEMU_OPTION_rtc_td_hack: {
+        static GlobalProperty slew_lost_ticks[] = {
+            {
+                .driver   = "mc146818rtc",
+                .property = "lost_tick_policy",
+                .value    = "slew",
+            },
+            { /* end of list */ }
+        };
+
+        qdev_prop_register_global_list(slew_lost_ticks);
+        break;
+    }
+    case QEMU_OPTION_acpitable:
+        do_acpitable_option(optarg);
+        break;
+    case QEMU_OPTION_smbios:
+        do_smbios_option(optarg);
+        break;
+    case QEMU_OPTION_enable_kvm:
+        olist = qemu_find_opts("machine");
+        qemu_opts_parse(olist, "accel=kvm", 0);
+        break;
+    case QEMU_OPTION_machine:
+        olist = qemu_find_opts("machine");
+        opts = qemu_opts_parse(olist, optarg, 1);
+        if (!opts) {
+            fprintf(stderr, "parse error: %s\n", optarg);
+            exit(1);
+        }
+        optarg = qemu_opt_get(opts, "type");
+        if (optarg) {
+            options->machine = machine_parse(optarg);
+        }
+        break;
+    case QEMU_OPTION_usb:
+        usb_enabled = 1;
+        break;
+    case QEMU_OPTION_usbdevice:
+        usb_enabled = 1;
+        add_device_config(DEV_USB, optarg);
+        break;
+    case QEMU_OPTION_device:
+        if (!qemu_opts_parse(qemu_find_opts("device"), optarg, 1)) {
+            exit(1);
+        }
+        break;
+    case QEMU_OPTION_smp:
+        smp_parse(optarg);
+        if (smp_cpus < 1) {
+            fprintf(stderr, "Invalid number of CPUs\n");
+            exit(1);
+        }
+        if (max_cpus < smp_cpus) {
+            fprintf(stderr, "maxcpus must be equal to or greater than "
+                    "smp\n");
+            exit(1);
+        }
+        if (max_cpus > 255) {
+            fprintf(stderr, "Unsupported number of maxcpus\n");
+            exit(1);
+        }
+        break;
+    case QEMU_OPTION_vnc:
 #ifdef CONFIG_VNC
-                display_remote++;
-                vnc_display = optarg;
+        display_remote++;
+        vnc_display = optarg;
 #else
-                fprintf(stderr, "VNC support is disabled\n");
-                exit(1);
+        fprintf(stderr, "VNC support is disabled\n");
+        exit(1);
 #endif
-                break;
-            case QEMU_OPTION_no_acpi:
-                acpi_enabled = 0;
-                break;
-            case QEMU_OPTION_no_hpet:
-                no_hpet = 1;
-                break;
-            case QEMU_OPTION_balloon:
-                if (balloon_parse(optarg) < 0) {
-                    fprintf(stderr, "Unknown -balloon argument %s\n", optarg);
-                    exit(1);
-                }
-                break;
-            case QEMU_OPTION_no_reboot:
-                no_reboot = 1;
-                break;
-            case QEMU_OPTION_no_shutdown:
-                no_shutdown = 1;
-                break;
-            case QEMU_OPTION_show_cursor:
-                cursor_hide = 0;
-                break;
-            case QEMU_OPTION_uuid:
-                if(qemu_uuid_parse(optarg, qemu_uuid) < 0) {
-                    fprintf(stderr, "Fail to parse UUID string."
-                            " Wrong format.\n");
-                    exit(1);
-                }
-                break;
-	    case QEMU_OPTION_option_rom:
-		if (nb_option_roms >= MAX_OPTION_ROMS) {
-		    fprintf(stderr, "Too many option ROMs\n");
-		    exit(1);
-		}
-                opts = qemu_opts_parse(qemu_find_opts("option-rom"), optarg, 1);
-                option_rom[nb_option_roms].name = qemu_opt_get(opts, "romfile");
-                option_rom[nb_option_roms].bootindex =
-                    qemu_opt_get_number(opts, "bootindex", -1);
-                if (!option_rom[nb_option_roms].name) {
-                    fprintf(stderr, "Option ROM file is not specified\n");
-                    exit(1);
-                }
-		nb_option_roms++;
-		break;
-            case QEMU_OPTION_semihosting:
-                semihosting_enabled = 1;
-                break;
-            case QEMU_OPTION_name:
-                qemu_name = g_strdup(optarg);
-		 {
-		     char *p = strchr(qemu_name, ',');
-		     if (p != NULL) {
-		        *p++ = 0;
-			if (strncmp(p, "process=", 8)) {
-			    fprintf(stderr, "Unknown subargument %s to -name\n", p);
-			    exit(1);
-			}
-			p += 8;
-			os_set_proc_name(p);
-		     }	
-		 }	
-                break;
-            case QEMU_OPTION_prom_env:
-                if (nb_prom_envs >= MAX_PROM_ENVS) {
-                    fprintf(stderr, "Too many prom variables\n");
-                    exit(1);
-                }
-                prom_envs[nb_prom_envs] = optarg;
-                nb_prom_envs++;
-                break;
-            case QEMU_OPTION_old_param:
-                old_param = 1;
-                break;
-            case QEMU_OPTION_clock:
-                configure_alarms(optarg);
-                break;
-            case QEMU_OPTION_startdate:
-                configure_rtc_date_offset(optarg, 1);
-                break;
-            case QEMU_OPTION_rtc:
-                opts = qemu_opts_parse(qemu_find_opts("rtc"), optarg, 0);
-                if (!opts) {
-                    exit(1);
-                }
-                configure_rtc(opts);
-                break;
-            case QEMU_OPTION_tb_size:
-                tcg_tb_size = strtol(optarg, NULL, 0);
-                if (tcg_tb_size < 0) {
-                    tcg_tb_size = 0;
-                }
-                break;
-            case QEMU_OPTION_icount:
-                icount_option = optarg;
-                break;
-            case QEMU_OPTION_incoming:
-                incoming = optarg;
-                break;
-            case QEMU_OPTION_nodefaults:
-                default_serial = 0;
-                default_parallel = 0;
-                default_virtcon = 0;
-                default_monitor = 0;
-                default_net = 0;
-                default_floppy = 0;
-                default_cdrom = 0;
-                default_sdcard = 0;
-                vga_model = "none";
-                break;
-            case QEMU_OPTION_xen_domid:
-                if (!(xen_available())) {
-                    printf("Option %s not supported for this target\n", popt->name);
-                    exit(1);
-                }
-                xen_domid = atoi(optarg);
-                break;
-            case QEMU_OPTION_xen_create:
-                if (!(xen_available())) {
-                    printf("Option %s not supported for this target\n", popt->name);
-                    exit(1);
-                }
-                xen_mode = XEN_CREATE;
-                break;
-            case QEMU_OPTION_xen_attach:
-                if (!(xen_available())) {
-                    printf("Option %s not supported for this target\n", popt->name);
-                    exit(1);
-                }
-                xen_mode = XEN_ATTACH;
-                break;
-            case QEMU_OPTION_trace:
-            {
-                opts = qemu_opts_parse(qemu_find_opts("trace"), optarg, 0);
-                if (!opts) {
-                    exit(1);
-                }
-                trace_events = qemu_opt_get(opts, "events");
-                trace_file = qemu_opt_get(opts, "file");
-                break;
+        break;
+    case QEMU_OPTION_no_acpi:
+        acpi_enabled = 0;
+        break;
+    case QEMU_OPTION_no_hpet:
+        no_hpet = 1;
+        break;
+    case QEMU_OPTION_balloon:
+        if (balloon_parse(optarg) < 0) {
+            fprintf(stderr, "Unknown -balloon argument %s\n", optarg);
+            exit(1);
+        }
+        break;
+    case QEMU_OPTION_no_reboot:
+        no_reboot = 1;
+        break;
+    case QEMU_OPTION_no_shutdown:
+        no_shutdown = 1;
+        break;
+    case QEMU_OPTION_show_cursor:
+        cursor_hide = 0;
+        break;
+    case QEMU_OPTION_uuid:
+        if(qemu_uuid_parse(optarg, qemu_uuid) < 0) {
+            fprintf(stderr, "Fail to parse UUID string."
+                    " Wrong format.\n");
+            exit(1);
+        }
+        break;
+    case QEMU_OPTION_option_rom:
+        if (nb_option_roms >= MAX_OPTION_ROMS) {
+            fprintf(stderr, "Too many option ROMs\n");
+            exit(1);
+        }
+        opts = qemu_opts_parse(qemu_find_opts("option-rom"), optarg, 1);
+        option_rom[nb_option_roms].name = qemu_opt_get(opts, "romfile");
+        option_rom[nb_option_roms].bootindex =
+            qemu_opt_get_number(opts, "bootindex", -1);
+        if (!option_rom[nb_option_roms].name) {
+            fprintf(stderr, "Option ROM file is not specified\n");
+            exit(1);
+        }
+        nb_option_roms++;
+        break;
+    case QEMU_OPTION_semihosting:
+        semihosting_enabled = 1;
+        break;
+    case QEMU_OPTION_name:
+        qemu_name = g_strdup(optarg);
+         {
+             char *p = strchr(qemu_name, ',');
+             if (p != NULL) {
+                *p++ = 0;
+        	if (strncmp(p, "process=", 8)) {
+        	    fprintf(stderr, "Unknown subargument %s to -name\n", p);
+        	    exit(1);
+        	}
+        	p += 8;
+        	os_set_proc_name(p);
+             }	
+         }	
+        break;
+    case QEMU_OPTION_prom_env:
+        if (nb_prom_envs >= MAX_PROM_ENVS) {
+            fprintf(stderr, "Too many prom variables\n");
+            exit(1);
+        }
+        prom_envs[nb_prom_envs] = optarg;
+        nb_prom_envs++;
+        break;
+    case QEMU_OPTION_old_param:
+        old_param = 1;
+        break;
+    case QEMU_OPTION_clock:
+        configure_alarms(optarg);
+        break;
+    case QEMU_OPTION_startdate:
+        configure_rtc_date_offset(optarg, 1);
+        break;
+    case QEMU_OPTION_rtc:
+        opts = qemu_opts_parse(qemu_find_opts("rtc"), optarg, 0);
+        if (!opts) {
+            exit(1);
+        }
+        configure_rtc(opts);
+        break;
+    case QEMU_OPTION_tb_size:
+        tcg_tb_size = strtol(optarg, NULL, 0);
+        if (tcg_tb_size < 0) {
+            tcg_tb_size = 0;
+        }
+        break;
+    case QEMU_OPTION_icount:
+        options->icount_option = optarg;
+        break;
+    case QEMU_OPTION_incoming:
+        options->incoming = optarg;
+        break;
+    case QEMU_OPTION_nodefaults:
+        default_serial = 0;
+        default_parallel = 0;
+        default_virtcon = 0;
+        default_monitor = 0;
+        default_net = 0;
+        default_floppy = 0;
+        default_cdrom = 0;
+        default_sdcard = 0;
+        options->vga_model = "none";
+        break;
+    case QEMU_OPTION_xen_domid:
+        if (!(xen_available())) {
+            printf("Option xen_domid not supported for this target\n");
+            exit(1);
+        }
+        xen_domid = atoi(optarg);
+        break;
+    case QEMU_OPTION_xen_create:
+        if (!(xen_available())) {
+            printf("Option xen_create not supported for this target\n");
+            exit(1);
+        }
+        xen_mode = XEN_CREATE;
+        break;
+    case QEMU_OPTION_xen_attach:
+        if (!(xen_available())) {
+            printf("Option xen_attach not supported for this target\n");
+            exit(1);
+        }
+        xen_mode = XEN_ATTACH;
+        break;
+    case QEMU_OPTION_trace:
+    {
+        opts = qemu_opts_parse(qemu_find_opts("trace"), optarg, 0);
+        if (!opts) {
+            exit(1);
+        }
+        options->trace_events = qemu_opt_get(opts, "events");
+        options->trace_file = qemu_opt_get(opts, "file");
+        break;
+    }
+    case QEMU_OPTION_readconfig:
+        {
+            int ret = qemu_read_config_file(optarg);
+            if (ret < 0) {
+                fprintf(stderr, "read config %s: %s\n", optarg,
+                    strerror(-ret));
+                exit(1);
             }
-            case QEMU_OPTION_readconfig:
-                {
-                    int ret = qemu_read_config_file(optarg);
-                    if (ret < 0) {
-                        fprintf(stderr, "read config %s: %s\n", optarg,
-                            strerror(-ret));
-                        exit(1);
-                    }
-                    break;
-                }
-            case QEMU_OPTION_spice:
-                olist = qemu_find_opts("spice");
-                if (!olist) {
-                    fprintf(stderr, "spice is not supported by this qemu build.\n");
-                    exit(1);
-                }
-                opts = qemu_opts_parse(olist, optarg, 0);
-                if (!opts) {
-                    fprintf(stderr, "parse error: %s\n", optarg);
+            break;
+        }
+    case QEMU_OPTION_spice:
+        olist = qemu_find_opts("spice");
+        if (!olist) {
+            fprintf(stderr, "spice is not supported by this qemu build.\n");
+            exit(1);
+        }
+        opts = qemu_opts_parse(olist, optarg, 0);
+        if (!opts) {
+            fprintf(stderr, "parse error: %s\n", optarg);
+            exit(1);
+        }
+        break;
+    case QEMU_OPTION_writeconfig:
+        {
+            FILE *fp;
+            if (strcmp(optarg, "-") == 0) {
+                fp = stdout;
+            } else {
+                fp = fopen(optarg, "w");
+                if (fp == NULL) {
+                    fprintf(stderr, "open %s: %s\n", optarg, strerror(errno));
                     exit(1);
                 }
+            }
+            qemu_config_write(fp);
+            fclose(fp);
+            break;
+        }
+    default:
+        os_parse_cmd_args(index, optarg);
+    }
+}
+
+static void qemu_parse_options(int argc, char **argv, QemuOptions *options)
+{
+    int optind;
+    const char *optarg;
+
+    /* first pass of option parsing */
+    optind = 1;
+    while (optind < argc) {
+        if (argv[optind][0] != '-') {
+            /* disk image */
+            optind++;
+            continue;
+        } else {
+            const QEMUOption *popt;
+
+            popt = lookup_opt(argc, argv, &optarg, &optind);
+            switch (popt->index) {
+            case QEMU_OPTION_nodefconfig:
+                options->defconfig=0;
                 break;
-            case QEMU_OPTION_writeconfig:
-                {
-                    FILE *fp;
-                    if (strcmp(optarg, "-") == 0) {
-                        fp = stdout;
-                    } else {
-                        fp = fopen(optarg, "w");
-                        if (fp == NULL) {
-                            fprintf(stderr, "open %s: %s\n", optarg, strerror(errno));
-                            exit(1);
-                        }
-                    }
-                    qemu_config_write(fp);
-                    fclose(fp);
-                    break;
-                }
-            default:
-                os_parse_cmd_args(popt->index, optarg);
             }
         }
     }
+
+    if (options->defconfig) {
+        int ret;
+
+        ret = qemu_read_config_file(CONFIG_QEMU_CONFDIR "/qemu.conf");
+        if (ret < 0 && ret != -ENOENT) {
+            exit(1);
+        }
+
+        ret = qemu_read_config_file(arch_config_name);
+        if (ret < 0 && ret != -ENOENT) {
+            exit(1);
+        }
+    }
+
+    /* second pass of option parsing */
+    optind = 1;
+    for(;;) {
+        if (optind >= argc)
+            break;
+        if (argv[optind][0] != '-') {
+	    options->hda_opts = drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS);
+        } else {
+            const QEMUOption *popt;
+
+            popt = lookup_opt(argc, argv, &optarg, &optind);
+            if (!(popt->arch_mask & arch_type)) {
+                printf("Option %s not supported for this target\n", popt->name);
+                exit(1);
+            }
+
+            qemu_parse_option(popt->index, optarg, options);
+        }
+    }
+}
+
+int main(int argc, char **argv, char **envp)
+{
+    int i;
+    int linux_boot;
+    const char *initrd_filename;
+    const char *kernel_filename, *kernel_cmdline;
+    DisplayState *ds;
+    DisplayChangeListener *dcl;
+    QemuOptions options = {};
+    QemuOpts *machine_opts;
+#ifdef CONFIG_VNC
+    int show_vnc_port = 0;
+#endif
+    GMemVTable mem_trace = {
+        .malloc = malloc_and_trace,
+        .realloc = realloc_and_trace,
+        .free = free_and_trace,
+    };
+
+    atexit(qemu_run_exit_notifiers);
+    error_set_progname(argv[0]);
+
+    g_mem_set_vtable(&mem_trace);
+    if (!g_thread_supported()) {
+#if !GLIB_CHECK_VERSION(2, 31, 0)
+        g_thread_init(NULL);
+#else
+        fprintf(stderr, "glib threading failed to initialize.\n");
+        exit(1);
+#endif
+    }
+
+    module_call_init(MODULE_INIT_QOM);
+
+    runstate_init();
+
+    init_clocks();
+    rtc_clock = host_clock;
+
+    qemu_cache_utils_init(envp);
+
+    QLIST_INIT (&vm_change_state_head);
+    os_setup_early_signal_handling();
+
+    module_call_init(MODULE_INIT_MACHINE);
+    options.machine = find_default_machine();
+    options.cpu_model = NULL;
+    snprintf(options.boot_devices, sizeof(options.boot_devices), "cad");
+    options.defconfig = 1;
+    options.translation = BIOS_ATA_TRANSLATION_AUTO;
+    ram_size = 0;
+
+    for (i = 0; i < MAX_NODES; i++) {
+        node_mem[i] = 0;
+        node_cpumask[i] = 0;
+    }
+
+    nb_numa_nodes = 0;
+    nb_nics = 0;
+
+    autostart= 1;
+    qemu_parse_options(argc, argv, &options);
     loc_set_none();
 
     /* Init CPU def lists, based on config
@@ -3194,7 +3215,7 @@ int main(int argc, char **argv, char **envp)
      */
     cpudef_init();
 
-    if (cpu_model && *cpu_model == '?') {
+    if (options.cpu_model && *options.cpu_model == '?') {
         list_cpus(stdout, &fprintf, optarg);
         exit(0);
     }
@@ -3204,14 +3225,14 @@ int main(int argc, char **argv, char **envp)
      * other one may be encountered later on the command line, changing the
      * location or level of logging.
      */
-    if (log_mask) {
-        if (log_file) {
-            set_cpu_log_filename(log_file);
+    if (options.log_mask) {
+        if (options.log_file) {
+            set_cpu_log_filename(options.log_file);
         }
-        set_cpu_log(log_mask);
+        set_cpu_log(options.log_mask);
     }
 
-    if (!trace_backend_init(trace_events, trace_file)) {
+    if (!trace_backend_init(options.trace_events, options.trace_file)) {
         exit(1);
     }
 
@@ -3225,7 +3246,7 @@ int main(int argc, char **argv, char **envp)
         data_dir = CONFIG_QEMU_DATADIR;
     }
 
-    if (machine == NULL) {
+    if (options.machine == NULL) {
         fprintf(stderr, "No machine found.\n");
         exit(1);
     }
@@ -3237,11 +3258,11 @@ int main(int argc, char **argv, char **envp)
     if (!max_cpus)
         max_cpus = smp_cpus;
 
-    machine->max_cpus = machine->max_cpus ?: 1; /* Default to UP */
-    if (smp_cpus > machine->max_cpus) {
+    options.machine->max_cpus = options.machine->max_cpus ?: 1; /* Default to UP */
+    if (smp_cpus > options.machine->max_cpus) {
         fprintf(stderr, "Number of SMP cpus requested (%d), exceeds max cpus "
-                "supported by machine `%s' (%d)\n", smp_cpus,  machine->name,
-                machine->max_cpus);
+                "supported by machine `%s' (%d)\n", smp_cpus,  options.machine->name,
+                options.machine->max_cpus);
         exit(1);
     }
 
@@ -3249,30 +3270,30 @@ int main(int argc, char **argv, char **envp)
      * Get the default machine options from the machine if it is not already
      * specified either by the configuration file or by the command line.
      */
-    if (machine->default_machine_opts) {
+    if (options.machine->default_machine_opts) {
         qemu_opts_set_defaults(qemu_find_opts("machine"),
-                               machine->default_machine_opts, 0);
+                               options.machine->default_machine_opts, 0);
     }
 
     qemu_opts_foreach(qemu_find_opts("device"), default_driver_check, NULL, 0);
     qemu_opts_foreach(qemu_find_opts("global"), default_driver_check, NULL, 0);
 
-    if (machine->no_serial) {
+    if (options.machine->no_serial) {
         default_serial = 0;
     }
-    if (machine->no_parallel) {
+    if (options.machine->no_parallel) {
         default_parallel = 0;
     }
-    if (!machine->use_virtcon) {
+    if (!options.machine->use_virtcon) {
         default_virtcon = 0;
     }
-    if (machine->no_floppy) {
+    if (options.machine->no_floppy) {
         default_floppy = 0;
     }
-    if (machine->no_cdrom) {
+    if (options.machine->no_cdrom) {
         default_cdrom = 0;
     }
-    if (machine->no_sdcard) {
+    if (options.machine->no_sdcard) {
         default_sdcard = 0;
     }
 
@@ -3314,7 +3335,7 @@ int main(int argc, char **argv, char **envp)
 
     os_daemonize();
 
-    if (pid_file && qemu_create_pidfile(pid_file) != 0) {
+    if (options.pid_file && qemu_create_pidfile(options.pid_file) != 0) {
         os_pidfile_error();
         exit(1);
     }
@@ -3369,11 +3390,11 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
-    if (icount_option && (kvm_enabled() || xen_enabled())) {
+    if (options.icount_option && (kvm_enabled() || xen_enabled())) {
         fprintf(stderr, "-icount is not allowed with kvm or xen\n");
         exit(1);
     }
-    configure_icount(icount_option);
+    configure_icount(options.icount_option);
 
     if (net_init_clients() < 0) {
         exit(1);
@@ -3398,16 +3419,16 @@ int main(int argc, char **argv, char **envp)
     blk_mig_init();
 
     /* open the virtual block devices */
-    if (snapshot)
+    if (options.snapshot)
         qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot, NULL, 0);
-    if (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func, &machine->use_scsi, 1) != 0)
+    if (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func, &options.machine->use_scsi, 1) != 0)
         exit(1);
 
-    default_drive(default_cdrom, snapshot, machine->use_scsi,
+    default_drive(default_cdrom, options.snapshot, options.machine->use_scsi,
                   IF_DEFAULT, 2, CDROM_OPTS);
-    default_drive(default_floppy, snapshot, machine->use_scsi,
+    default_drive(default_floppy, options.snapshot, options.machine->use_scsi,
                   IF_FLOPPY, 0, FD_OPTS);
-    default_drive(default_sdcard, snapshot, machine->use_scsi,
+    default_drive(default_sdcard, options.snapshot, options.machine->use_scsi,
                   IF_SD, 0, SD_OPTS);
 
     register_savevm_live(NULL, "ram", 0, 4, NULL, ram_save_live, NULL,
@@ -3469,8 +3490,8 @@ int main(int argc, char **argv, char **envp)
         exit(1);
 
     /* must be after qdev registration but before machine init */
-    if (vga_model) {
-        select_vgahw(vga_model);
+    if (options.vga_model) {
+        select_vgahw(options.vga_model);
     } else if (cirrus_vga_available()) {
         select_vgahw("cirrus");
     } else {
@@ -3486,21 +3507,21 @@ int main(int argc, char **argv, char **envp)
             exit (i == 1 ? 1 : 0);
     }
 
-    if (machine->compat_props) {
-        qdev_prop_register_global_list(machine->compat_props);
+    if (options.machine->compat_props) {
+        qdev_prop_register_global_list(options.machine->compat_props);
     }
     qemu_add_globals();
 
     qdev_machine_init();
 
-    machine->init(ram_size, boot_devices,
-                  kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
+    options.machine->init(ram_size, options.boot_devices,
+                  kernel_filename, kernel_cmdline, initrd_filename, options.cpu_model);
 
     cpu_synchronize_all_post_init();
 
     set_numa_modes();
 
-    current_machine = machine;
+    current_machine = options.machine;
 
     /* init USB devices */
     if (usb_enabled) {
@@ -3604,18 +3625,18 @@ int main(int argc, char **argv, char **envp)
     qemu_run_machine_init_done_notifiers();
 
     qemu_system_reset(VMRESET_SILENT);
-    if (loadvm) {
-        if (load_vmstate(loadvm) < 0) {
+    if (options.loadvm) {
+        if (load_vmstate(options.loadvm) < 0) {
             autostart = 0;
         }
     }
 
-    if (incoming) {
+    if (options.incoming) {
         runstate_set(RUN_STATE_INMIGRATE);
-        int ret = qemu_start_incoming_migration(incoming);
+        int ret = qemu_start_incoming_migration(options.incoming);
         if (ret < 0) {
             fprintf(stderr, "Migration failed. Exit code %s(%d), exiting.\n",
-                    incoming, ret);
+                    options.incoming, ret);
             exit(ret);
         }
     } else if (autostart) {
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 4/9] vl: mark system configuration options in qemu-options.hx
  2012-03-19 15:09 [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Anthony Liguori
                   ` (2 preceding siblings ...)
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 3/9] vl: refactor command line parsing to allow options to be set via config Anthony Liguori
@ 2012-03-19 15:09 ` Anthony Liguori
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 5/9] vl: enable system configuration to be used Anthony Liguori
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 26+ messages in thread
From: Anthony Liguori @ 2012-03-19 15:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Eric Blake, Eduardo Habkost, Gerd Hoffman

Mark all options that cannot be parsed via QemuOptions in qemu-options.hx.  This
lets us construct a [system] section to house all of these options.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 qemu-config.c          |   15 ++++
 qemu-options-wrapper.h |   21 +++++-
 qemu-options.hx        |  205 ++++++++++++++++++++++++------------------------
 vl.c                   |    1 +
 4 files changed, 139 insertions(+), 103 deletions(-)

diff --git a/qemu-config.c b/qemu-config.c
index daf6557..5856e5a 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -3,6 +3,20 @@
 #include "qemu-option.h"
 #include "qemu-config.h"
 #include "hw/qdev.h"
+#include "gdbstub.h"
+#include "net.h"
+
+static QemuOptsList qemu_system_opts = {
+    .name = "system",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_system_opts.head),
+    .merge_lists = true,
+    .desc = {
+#define HAS_ARG 1
+#define QEMU_OPTIONS_GENERATE_QEMUOPTS
+#include "qemu-options-wrapper.h"
+        { /* end of list */}
+    },
+};
 
 static QemuOptsList qemu_drive_opts = {
     .name = "drive",
@@ -628,6 +642,7 @@ static QemuOptsList *vm_config_groups[32] = {
     &qemu_machine_opts,
     &qemu_boot_opts,
     &qemu_iscsi_opts,
+    &qemu_system_opts,
     NULL,
 };
 
diff --git a/qemu-options-wrapper.h b/qemu-options-wrapper.h
index 13bfea0..08e0463 100644
--- a/qemu-options-wrapper.h
+++ b/qemu-options-wrapper.h
@@ -1,8 +1,10 @@
 
 #if defined(QEMU_OPTIONS_GENERATE_ENUM)
 
-#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)     \
+#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)    \
     opt_enum,
+#define GDEF(option, opt_arg, opt_enum, opt_help, arch_mask)    \
+    DEF(option, opt_ag, opt_enum, opt_help, arch_mask)
 #define DEFHEADING(text)
 #define ARCHHEADING(text, arch_mask)
 
@@ -11,6 +13,8 @@
 #define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)    \
     if ((arch_mask) & arch_type)                               \
         fputs(opt_help, stdout);
+#define GDEF(option, opt_arg, opt_enum, opt_help, arch_mask)    \
+    DEF(option, opt_ag, opt_enum, opt_help, arch_mask)
 
 #define ARCHHEADING(text, arch_mask) \
     if ((arch_mask) & arch_type)    \
@@ -21,7 +25,18 @@
 #elif defined(QEMU_OPTIONS_GENERATE_OPTIONS)
 
 #define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)     \
-    { option, opt_arg, opt_enum, arch_mask },
+    { option, opt_arg, opt_enum, arch_mask, false },
+#define GDEF(option, opt_arg, opt_enum, opt_help, arch_mask)    \
+    { option, opt_arg, opt_enum, arch_mask, true },
+#define DEFHEADING(text)
+#define ARCHHEADING(text, arch_mask)
+
+#elif defined(QEMU_OPTIONS_GENERATE_QEMUOPTS)
+
+#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
+    { .name = option, .type = opt_arg ? QEMU_OPT_STRING : QEMU_OPT_BOOL, .help = opt_help },
+#define GDEF(option, opt_arg, opt_enum, opt_help, arch_mask)    \
+    DEF(option, opt_arg, opt_enum, opt_help, arch_mask)
 #define DEFHEADING(text)
 #define ARCHHEADING(text, arch_mask)
 
@@ -32,6 +47,7 @@
 #include "qemu-options.def"
 
 #undef DEF
+#undef GDEF
 #undef DEFHEADING
 #undef ARCHHEADING
 #undef GEN_DOCS
@@ -39,3 +55,4 @@
 #undef QEMU_OPTIONS_GENERATE_ENUM
 #undef QEMU_OPTIONS_GENERATE_HELP
 #undef QEMU_OPTIONS_GENERATE_OPTIONS
+#undef QEMU_OPTIONS_GENERATE_QEMUOPTS
diff --git a/qemu-options.hx b/qemu-options.hx
index daefce3..584dc76 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -4,6 +4,9 @@ HXCOMM discarded from C version
 HXCOMM DEF(option, HAS_ARG/0, opt_enum, opt_help, arch_mask) is used to
 HXCOMM construct option structures, enums and help message for specified
 HXCOMM architectures.
+HXCOMM Use GDEF to indicate that an option is not mapped to QemuOptions.
+HXCOMM This will cause the option to be accessible from the catch-all
+HXCOMM system option type.
 HXCOMM HXCOMM can be used for comments, discarded from both texi and C
 
 DEFHEADING(Standard options:)
@@ -54,9 +57,9 @@ Defines the size of the KVM shadow MMU.
 ETEXI
 
 HXCOMM Deprecated by -machine
-DEF("M", HAS_ARG, QEMU_OPTION_M, "", QEMU_ARCH_ALL)
+GDEF("M", HAS_ARG, QEMU_OPTION_M, "", QEMU_ARCH_ALL)
 
-DEF("cpu", HAS_ARG, QEMU_OPTION_cpu,
+GDEF("cpu", HAS_ARG, QEMU_OPTION_cpu,
     "-cpu cpu        select CPU (-cpu ? for list)\n", QEMU_ARCH_ALL)
 STEXI
 @item -cpu @var{model}
@@ -64,7 +67,7 @@ STEXI
 Select CPU model (-cpu ? for list and additional feature selection)
 ETEXI
 
-DEF("smp", HAS_ARG, QEMU_OPTION_smp,
+GDEF("smp", HAS_ARG, QEMU_OPTION_smp,
     "-smp n[,maxcpus=cpus][,cores=cores][,threads=threads][,sockets=sockets]\n"
     "                set the number of CPUs to 'n' [default=1]\n"
     "                maxcpus= maximum number of total cpus, including\n"
@@ -86,7 +89,7 @@ given, the total number of CPUs @var{n} can be omitted. @var{maxcpus}
 specifies the maximum number of hotpluggable CPUs.
 ETEXI
 
-DEF("numa", HAS_ARG, QEMU_OPTION_numa,
+GDEF("numa", HAS_ARG, QEMU_OPTION_numa,
     "-numa node[,mem=size][,cpus=cpu[-cpu]][,nodeid=node]\n", QEMU_ARCH_ALL)
 STEXI
 @item -numa @var{opts}
@@ -95,9 +98,9 @@ Simulate a multi node NUMA system. If mem and cpus are omitted, resources
 are split equally.
 ETEXI
 
-DEF("fda", HAS_ARG, QEMU_OPTION_fda,
+GDEF("fda", HAS_ARG, QEMU_OPTION_fda,
     "-fda/-fdb file  use 'file' as floppy disk 0/1 image\n", QEMU_ARCH_ALL)
-DEF("fdb", HAS_ARG, QEMU_OPTION_fdb, "", QEMU_ARCH_ALL)
+GDEF("fdb", HAS_ARG, QEMU_OPTION_fdb, "", QEMU_ARCH_ALL)
 STEXI
 @item -fda @var{file}
 @item -fdb @var{file}
@@ -107,12 +110,12 @@ Use @var{file} as floppy disk 0/1 image (@pxref{disk_images}). You can
 use the host floppy by using @file{/dev/fd0} as filename (@pxref{host_drives}).
 ETEXI
 
-DEF("hda", HAS_ARG, QEMU_OPTION_hda,
+GDEF("hda", HAS_ARG, QEMU_OPTION_hda,
     "-hda/-hdb file  use 'file' as IDE hard disk 0/1 image\n", QEMU_ARCH_ALL)
-DEF("hdb", HAS_ARG, QEMU_OPTION_hdb, "", QEMU_ARCH_ALL)
-DEF("hdc", HAS_ARG, QEMU_OPTION_hdc,
+GDEF("hdb", HAS_ARG, QEMU_OPTION_hdb, "", QEMU_ARCH_ALL)
+GDEF("hdc", HAS_ARG, QEMU_OPTION_hdc,
     "-hdc/-hdd file  use 'file' as IDE hard disk 2/3 image\n", QEMU_ARCH_ALL)
-DEF("hdd", HAS_ARG, QEMU_OPTION_hdd, "", QEMU_ARCH_ALL)
+GDEF("hdd", HAS_ARG, QEMU_OPTION_hdd, "", QEMU_ARCH_ALL)
 STEXI
 @item -hda @var{file}
 @item -hdb @var{file}
@@ -125,7 +128,7 @@ STEXI
 Use @var{file} as hard disk 0, 1, 2 or 3 image (@pxref{disk_images}).
 ETEXI
 
-DEF("cdrom", HAS_ARG, QEMU_OPTION_cdrom,
+GDEF("cdrom", HAS_ARG, QEMU_OPTION_cdrom,
     "-cdrom file     use 'file' as IDE cdrom image (cdrom is ide1 master)\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -297,7 +300,7 @@ STEXI
 TODO
 ETEXI
 
-DEF("mtdblock", HAS_ARG, QEMU_OPTION_mtdblock,
+GDEF("mtdblock", HAS_ARG, QEMU_OPTION_mtdblock,
     "-mtdblock file  use 'file' as on-board Flash memory image\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -306,7 +309,7 @@ STEXI
 Use @var{file} as on-board Flash memory image.
 ETEXI
 
-DEF("sd", HAS_ARG, QEMU_OPTION_sd,
+GDEF("sd", HAS_ARG, QEMU_OPTION_sd,
     "-sd file        use 'file' as SecureDigital card image\n", QEMU_ARCH_ALL)
 STEXI
 @item -sd @var{file}
@@ -314,7 +317,7 @@ STEXI
 Use @var{file} as SecureDigital card image.
 ETEXI
 
-DEF("pflash", HAS_ARG, QEMU_OPTION_pflash,
+GDEF("pflash", HAS_ARG, QEMU_OPTION_pflash,
     "-pflash file    use 'file' as a parallel flash image\n", QEMU_ARCH_ALL)
 STEXI
 @item -pflash @var{file}
@@ -322,7 +325,7 @@ STEXI
 Use @var{file} as a parallel flash image.
 ETEXI
 
-DEF("boot", HAS_ARG, QEMU_OPTION_boot,
+GDEF("boot", HAS_ARG, QEMU_OPTION_boot,
     "-boot [order=drives][,once=drives][,menu=on|off]\n"
     "      [,splash=sp_name][,splash-time=sp_time]\n"
     "                'drives': floppy (a), hard disk (c), CD-ROM (d), network (n)\n"
@@ -362,7 +365,7 @@ Note: The legacy format '-boot @var{drives}' is still supported but its
 use is discouraged as it may be removed from future versions.
 ETEXI
 
-DEF("snapshot", 0, QEMU_OPTION_snapshot,
+GDEF("snapshot", 0, QEMU_OPTION_snapshot,
     "-snapshot       write to temporary files instead of disk image files\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -373,7 +376,7 @@ the raw disk image you use is not written back. You can however force
 the write back by pressing @key{C-a s} (@pxref{disk_images}).
 ETEXI
 
-DEF("m", HAS_ARG, QEMU_OPTION_m,
+GDEF("m", HAS_ARG, QEMU_OPTION_m,
     "-m megs         set virtual RAM size to megs MB [default="
     stringify(DEFAULT_RAM_SIZE) "]\n", QEMU_ARCH_ALL)
 STEXI
@@ -384,7 +387,7 @@ a suffix of ``M'' or ``G'' can be used to signify a value in megabytes or
 gigabytes respectively.
 ETEXI
 
-DEF("mem-path", HAS_ARG, QEMU_OPTION_mempath,
+GDEF("mem-path", HAS_ARG, QEMU_OPTION_mempath,
     "-mem-path FILE  provide backing storage for guest RAM\n", QEMU_ARCH_ALL)
 STEXI
 @item -mem-path @var{path}
@@ -392,7 +395,7 @@ Allocate guest RAM from a temporarily created file in @var{path}.
 ETEXI
 
 #ifdef MAP_POPULATE
-DEF("mem-prealloc", 0, QEMU_OPTION_mem_prealloc,
+GDEF("mem-prealloc", 0, QEMU_OPTION_mem_prealloc,
     "-mem-prealloc   preallocate guest memory (use with -mem-path)\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -401,7 +404,7 @@ Preallocate memory when using -mem-path.
 ETEXI
 #endif
 
-DEF("k", HAS_ARG, QEMU_OPTION_k,
+GDEF("k", HAS_ARG, QEMU_OPTION_k,
     "-k language     use keyboard layout (for example 'fr' for French)\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -434,7 +437,7 @@ Will show the audio subsystem help: list of drivers, tunable
 parameters.
 ETEXI
 
-DEF("soundhw", HAS_ARG, QEMU_OPTION_soundhw,
+GDEF("soundhw", HAS_ARG, QEMU_OPTION_soundhw,
     "-soundhw c1,... enable audio support\n"
     "                and only specified sound cards (comma separated list)\n"
     "                use -soundhw ? to get the list of supported cards\n"
@@ -462,7 +465,7 @@ modprobe i810_audio clocking=48000
 @end example
 ETEXI
 
-DEF("balloon", HAS_ARG, QEMU_OPTION_balloon,
+GDEF("balloon", HAS_ARG, QEMU_OPTION_balloon,
     "-balloon none   disable balloon device\n"
     "-balloon virtio[,addr=str]\n"
     "                enable virtio balloon device (default)\n", QEMU_ARCH_ALL)
@@ -479,7 +482,7 @@ STEXI
 @end table
 ETEXI
 
-DEF("usb", 0, QEMU_OPTION_usb,
+GDEF("usb", 0, QEMU_OPTION_usb,
     "-usb            enable the USB driver (will be the default soon)\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -491,7 +494,7 @@ USB options:
 Enable the USB driver (will be the default soon)
 ETEXI
 
-DEF("usbdevice", HAS_ARG, QEMU_OPTION_usbdevice,
+GDEF("usbdevice", HAS_ARG, QEMU_OPTION_usbdevice,
     "-usbdevice name add the host or guest USB device 'name'\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -674,7 +677,7 @@ descriptor for interfacing with virtfs-proxy-helper
 @end table
 ETEXI
 
-DEF("virtfs_synth", 0, QEMU_OPTION_virtfs_synth,
+GDEF("virtfs_synth", 0, QEMU_OPTION_virtfs_synth,
     "-virtfs_synth Create synthetic file system image\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -685,7 +688,7 @@ ETEXI
 
 DEFHEADING()
 
-DEF("name", HAS_ARG, QEMU_OPTION_name,
+GDEF("name", HAS_ARG, QEMU_OPTION_name,
     "-name string1[,process=string2]\n"
     "                set the name of the guest\n"
     "                string1 sets the window title and string2 the process name (on Linux)\n",
@@ -699,7 +702,7 @@ The @var{name} will also be used for the VNC server.
 Also optionally set the top visible process name in Linux.
 ETEXI
 
-DEF("uuid", HAS_ARG, QEMU_OPTION_uuid,
+GDEF("uuid", HAS_ARG, QEMU_OPTION_uuid,
     "-uuid %08x-%04x-%04x-%04x-%012x\n"
     "                specify machine UUID\n", QEMU_ARCH_ALL)
 STEXI
@@ -720,7 +723,7 @@ STEXI
 @table @option
 ETEXI
 
-DEF("display", HAS_ARG, QEMU_OPTION_display,
+GDEF("display", HAS_ARG, QEMU_OPTION_display,
     "-display sdl[,frame=on|off][,alt_grab=on|off][,ctrl_grab=on|off]\n"
     "            [,window_close=on|off]|curses|none|\n"
     "            vnc=<display>[,<optargs>]\n"
@@ -751,7 +754,7 @@ Start a VNC server on display <arg>
 @end table
 ETEXI
 
-DEF("nographic", 0, QEMU_OPTION_nographic,
+GDEF("nographic", 0, QEMU_OPTION_nographic,
     "-nographic      disable graphical output and redirect serial I/Os to console\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -764,7 +767,7 @@ the console. Therefore, you can still use QEMU to debug a Linux kernel
 with a serial console.
 ETEXI
 
-DEF("curses", 0, QEMU_OPTION_curses,
+GDEF("curses", 0, QEMU_OPTION_curses,
     "-curses         use a curses/ncurses interface instead of SDL\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -775,7 +778,7 @@ QEMU can display the VGA output when in text mode using a
 curses/ncurses interface.  Nothing is displayed in graphical mode.
 ETEXI
 
-DEF("no-frame", 0, QEMU_OPTION_no_frame,
+GDEF("no-frame", 0, QEMU_OPTION_no_frame,
     "-no-frame       open SDL window without a frame and window decorations\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -786,7 +789,7 @@ available screen space. This makes the using QEMU in a dedicated desktop
 workspace more convenient.
 ETEXI
 
-DEF("alt-grab", 0, QEMU_OPTION_alt_grab,
+GDEF("alt-grab", 0, QEMU_OPTION_alt_grab,
     "-alt-grab       use Ctrl-Alt-Shift to grab mouse (instead of Ctrl-Alt)\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -796,7 +799,7 @@ Use Ctrl-Alt-Shift to grab mouse (instead of Ctrl-Alt). Note that this also
 affects the special keys (for fullscreen, monitor-mode switching, etc).
 ETEXI
 
-DEF("ctrl-grab", 0, QEMU_OPTION_ctrl_grab,
+GDEF("ctrl-grab", 0, QEMU_OPTION_ctrl_grab,
     "-ctrl-grab      use Right-Ctrl to grab mouse (instead of Ctrl-Alt)\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -806,7 +809,7 @@ Use Right-Ctrl to grab mouse (instead of Ctrl-Alt). Note that this also
 affects the special keys (for fullscreen, monitor-mode switching, etc).
 ETEXI
 
-DEF("no-quit", 0, QEMU_OPTION_no_quit,
+GDEF("no-quit", 0, QEMU_OPTION_no_quit,
     "-no-quit        disable SDL window close capability\n", QEMU_ARCH_ALL)
 STEXI
 @item -no-quit
@@ -814,7 +817,7 @@ STEXI
 Disable SDL window close capability.
 ETEXI
 
-DEF("sdl", 0, QEMU_OPTION_sdl,
+GDEF("sdl", 0, QEMU_OPTION_sdl,
     "-sdl            enable SDL\n", QEMU_ARCH_ALL)
 STEXI
 @item -sdl
@@ -908,7 +911,7 @@ Enable/disable audio stream compression (using celt 0.5.1).  Default is on.
 @end table
 ETEXI
 
-DEF("portrait", 0, QEMU_OPTION_portrait,
+GDEF("portrait", 0, QEMU_OPTION_portrait,
     "-portrait       rotate graphical output 90 deg left (only PXA LCD)\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -917,7 +920,7 @@ STEXI
 Rotate graphical output 90 deg left (only PXA LCD).
 ETEXI
 
-DEF("rotate", HAS_ARG, QEMU_OPTION_rotate,
+GDEF("rotate", HAS_ARG, QEMU_OPTION_rotate,
     "-rotate <deg>   rotate graphical output some deg left (only PXA LCD)\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -926,7 +929,7 @@ STEXI
 Rotate graphical output some deg left (only PXA LCD).
 ETEXI
 
-DEF("vga", HAS_ARG, QEMU_OPTION_vga,
+GDEF("vga", HAS_ARG, QEMU_OPTION_vga,
     "-vga [std|cirrus|vmware|qxl|xenfb|none]\n"
     "                select video card type\n", QEMU_ARCH_ALL)
 STEXI
@@ -957,7 +960,7 @@ Disable VGA card.
 @end table
 ETEXI
 
-DEF("full-screen", 0, QEMU_OPTION_full_screen,
+GDEF("full-screen", 0, QEMU_OPTION_full_screen,
     "-full-screen    start in full screen\n", QEMU_ARCH_ALL)
 STEXI
 @item -full-screen
@@ -965,7 +968,7 @@ STEXI
 Start in full screen.
 ETEXI
 
-DEF("g", 1, QEMU_OPTION_g ,
+GDEF("g", 1, QEMU_OPTION_g ,
     "-g WxH[xDEPTH]  Set the initial graphical resolution and depth\n",
     QEMU_ARCH_PPC | QEMU_ARCH_SPARC)
 STEXI
@@ -974,7 +977,7 @@ STEXI
 Set the initial graphical resolution and depth (PPC, SPARC only).
 ETEXI
 
-DEF("vnc", HAS_ARG, QEMU_OPTION_vnc ,
+GDEF("vnc", HAS_ARG, QEMU_OPTION_vnc ,
     "-vnc display    start a VNC server on display\n", QEMU_ARCH_ALL)
 STEXI
 @item -vnc @var{display}[,@var{option}[,@var{option}[,...]]]
@@ -1125,7 +1128,7 @@ STEXI
 @table @option
 ETEXI
 
-DEF("win2k-hack", 0, QEMU_OPTION_win2k_hack,
+GDEF("win2k-hack", 0, QEMU_OPTION_win2k_hack,
     "-win2k-hack     use it when installing Windows 2000 to avoid a disk full bug\n",
     QEMU_ARCH_I386)
 STEXI
@@ -1137,9 +1140,9 @@ slows down the IDE transfers).
 ETEXI
 
 HXCOMM Deprecated by -rtc
-DEF("rtc-td-hack", 0, QEMU_OPTION_rtc_td_hack, "", QEMU_ARCH_I386)
+GDEF("rtc-td-hack", 0, QEMU_OPTION_rtc_td_hack, "", QEMU_ARCH_I386)
 
-DEF("no-fd-bootchk", 0, QEMU_OPTION_no_fd_bootchk,
+GDEF("no-fd-bootchk", 0, QEMU_OPTION_no_fd_bootchk,
     "-no-fd-bootchk  disable boot signature checking for floppy disks\n",
     QEMU_ARCH_I386)
 STEXI
@@ -1150,7 +1153,7 @@ be needed to boot from old floppy disks.
 TODO: check reference to Bochs BIOS.
 ETEXI
 
-DEF("no-acpi", 0, QEMU_OPTION_no_acpi,
+GDEF("no-acpi", 0, QEMU_OPTION_no_acpi,
            "-no-acpi        disable ACPI\n", QEMU_ARCH_I386)
 STEXI
 @item -no-acpi
@@ -1160,7 +1163,7 @@ it if your guest OS complains about ACPI problems (PC target machine
 only).
 ETEXI
 
-DEF("no-hpet", 0, QEMU_OPTION_no_hpet,
+GDEF("no-hpet", 0, QEMU_OPTION_no_hpet,
     "-no-hpet        disable HPET\n", QEMU_ARCH_I386)
 STEXI
 @item -no-hpet
@@ -1168,7 +1171,7 @@ STEXI
 Disable HPET support.
 ETEXI
 
-DEF("acpitable", HAS_ARG, QEMU_OPTION_acpitable,
+GDEF("acpitable", HAS_ARG, QEMU_OPTION_acpitable,
     "-acpitable [sig=str][,rev=n][,oem_id=str][,oem_table_id=str][,oem_rev=n][,asl_compiler_id=str][,asl_compiler_rev=n][,{data|file}=file1[:file2]...]\n"
     "                ACPI table description\n", QEMU_ARCH_I386)
 STEXI
@@ -1182,7 +1185,7 @@ portion of the table is used, all header information is specified in the
 command line.
 ETEXI
 
-DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
+GDEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
     "-smbios file=binary\n"
     "                load SMBIOS entry from binary file\n"
     "-smbios type=0[,vendor=str][,version=str][,date=str][,release=%d.%d]\n"
@@ -1215,11 +1218,11 @@ ETEXI
 
 HXCOMM Legacy slirp options (now moved to -net user):
 #ifdef CONFIG_SLIRP
-DEF("tftp", HAS_ARG, QEMU_OPTION_tftp, "", QEMU_ARCH_ALL)
-DEF("bootp", HAS_ARG, QEMU_OPTION_bootp, "", QEMU_ARCH_ALL)
-DEF("redir", HAS_ARG, QEMU_OPTION_redir, "", QEMU_ARCH_ALL)
+GDEF("tftp", HAS_ARG, QEMU_OPTION_tftp, "", QEMU_ARCH_ALL)
+GDEF("bootp", HAS_ARG, QEMU_OPTION_bootp, "", QEMU_ARCH_ALL)
+GDEF("redir", HAS_ARG, QEMU_OPTION_redir, "", QEMU_ARCH_ALL)
 #ifndef _WIN32
-DEF("smb", HAS_ARG, QEMU_OPTION_smb, "", QEMU_ARCH_ALL)
+GDEF("smb", HAS_ARG, QEMU_OPTION_smb, "", QEMU_ARCH_ALL)
 #endif
 #endif
 
@@ -1925,7 +1928,7 @@ ETEXI
 
 DEFHEADING(Bluetooth(R) options:)
 
-DEF("bt", HAS_ARG, QEMU_OPTION_bt, \
+GDEF("bt", HAS_ARG, QEMU_OPTION_bt, \
     "-bt hci,null    dumb bluetooth HCI - doesn't respond to commands\n" \
     "-bt hci,host[:id]\n" \
     "                use host's HCI with the given name\n" \
@@ -2005,7 +2008,7 @@ for easier testing of various kernels.
 @table @option
 ETEXI
 
-DEF("kernel", HAS_ARG, QEMU_OPTION_kernel, \
+GDEF("kernel", HAS_ARG, QEMU_OPTION_kernel, \
     "-kernel bzImage use 'bzImage' as kernel image\n", QEMU_ARCH_ALL)
 STEXI
 @item -kernel @var{bzImage}
@@ -2014,7 +2017,7 @@ Use @var{bzImage} as kernel image. The kernel can be either a Linux kernel
 or in multiboot format.
 ETEXI
 
-DEF("append", HAS_ARG, QEMU_OPTION_append, \
+GDEF("append", HAS_ARG, QEMU_OPTION_append, \
     "-append cmdline use 'cmdline' as kernel command line\n", QEMU_ARCH_ALL)
 STEXI
 @item -append @var{cmdline}
@@ -2022,7 +2025,7 @@ STEXI
 Use @var{cmdline} as kernel command line
 ETEXI
 
-DEF("initrd", HAS_ARG, QEMU_OPTION_initrd, \
+GDEF("initrd", HAS_ARG, QEMU_OPTION_initrd, \
            "-initrd file    use 'file' as initial ram disk\n", QEMU_ARCH_ALL)
 STEXI
 @item -initrd @var{file}
@@ -2037,7 +2040,7 @@ Use @var{file1} and @var{file2} as modules and pass arg=foo as parameter to the
 first module.
 ETEXI
 
-DEF("dtb", HAS_ARG, QEMU_OPTION_dtb, \
+GDEF("dtb", HAS_ARG, QEMU_OPTION_dtb, \
     "-dtb    file    use 'file' as device tree image\n", QEMU_ARCH_ALL)
 STEXI
 @item -dtb @var{file}
@@ -2058,7 +2061,7 @@ STEXI
 @table @option
 ETEXI
 
-DEF("serial", HAS_ARG, QEMU_OPTION_serial, \
+GDEF("serial", HAS_ARG, QEMU_OPTION_serial, \
     "-serial dev     redirect the serial port to char device 'dev'\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -2187,7 +2190,7 @@ Three button serial mouse. Configure the guest to use Microsoft protocol.
 @end table
 ETEXI
 
-DEF("parallel", HAS_ARG, QEMU_OPTION_parallel, \
+GDEF("parallel", HAS_ARG, QEMU_OPTION_parallel, \
     "-parallel dev   redirect the parallel port to char device 'dev'\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -2204,7 +2207,7 @@ ports.
 Use @code{-parallel none} to disable all parallel ports.
 ETEXI
 
-DEF("monitor", HAS_ARG, QEMU_OPTION_monitor, \
+GDEF("monitor", HAS_ARG, QEMU_OPTION_monitor, \
     "-monitor dev    redirect the monitor to char device 'dev'\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -2215,7 +2218,7 @@ serial port).
 The default device is @code{vc} in graphical mode and @code{stdio} in
 non graphical mode.
 ETEXI
-DEF("qmp", HAS_ARG, QEMU_OPTION_qmp, \
+GDEF("qmp", HAS_ARG, QEMU_OPTION_qmp, \
     "-qmp dev        like -monitor but opens in 'control' mode\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -2232,7 +2235,7 @@ STEXI
 Setup monitor on chardev @var{name}.
 ETEXI
 
-DEF("debugcon", HAS_ARG, QEMU_OPTION_debugcon, \
+GDEF("debugcon", HAS_ARG, QEMU_OPTION_debugcon, \
     "-debugcon dev   redirect the debug console to char device 'dev'\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -2245,7 +2248,7 @@ The default device is @code{vc} in graphical mode and @code{stdio} in
 non graphical mode.
 ETEXI
 
-DEF("pidfile", HAS_ARG, QEMU_OPTION_pidfile, \
+GDEF("pidfile", HAS_ARG, QEMU_OPTION_pidfile, \
     "-pidfile file   write PID to 'file'\n", QEMU_ARCH_ALL)
 STEXI
 @item -pidfile @var{file}
@@ -2254,7 +2257,7 @@ Store the QEMU process PID in @var{file}. It is useful if you launch QEMU
 from a script.
 ETEXI
 
-DEF("singlestep", 0, QEMU_OPTION_singlestep, \
+GDEF("singlestep", 0, QEMU_OPTION_singlestep, \
     "-singlestep     always run in singlestep mode\n", QEMU_ARCH_ALL)
 STEXI
 @item -singlestep
@@ -2262,7 +2265,7 @@ STEXI
 Run the emulation in single step mode.
 ETEXI
 
-DEF("S", 0, QEMU_OPTION_S, \
+GDEF("S", 0, QEMU_OPTION_S, \
     "-S              freeze CPU at startup (use 'c' to start execution)\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -2271,7 +2274,7 @@ STEXI
 Do not start CPU at startup (you must type 'c' in the monitor).
 ETEXI
 
-DEF("gdb", HAS_ARG, QEMU_OPTION_gdb, \
+GDEF("gdb", HAS_ARG, QEMU_OPTION_gdb, \
     "-gdb dev        wait for gdb connection on 'dev'\n", QEMU_ARCH_ALL)
 STEXI
 @item -gdb @var{dev}
@@ -2285,7 +2288,7 @@ within gdb and establish the connection via a pipe:
 @end example
 ETEXI
 
-DEF("s", 0, QEMU_OPTION_s, \
+GDEF("s", 0, QEMU_OPTION_s, \
     "-s              shorthand for -gdb tcp::" DEFAULT_GDBSTUB_PORT "\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -2295,7 +2298,7 @@ Shorthand for -gdb tcp::1234, i.e. open a gdbserver on TCP port 1234
 (@pxref{gdb_usage}).
 ETEXI
 
-DEF("d", HAS_ARG, QEMU_OPTION_d, \
+GDEF("d", HAS_ARG, QEMU_OPTION_d, \
     "-d item1,...    output log to /tmp/qemu.log (use -d ? for a list of log items)\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -2304,7 +2307,7 @@ STEXI
 Output log in /tmp/qemu.log
 ETEXI
 
-DEF("D", HAS_ARG, QEMU_OPTION_D, \
+GDEF("D", HAS_ARG, QEMU_OPTION_D, \
     "-D logfile      output log to logfile (instead of the default /tmp/qemu.log)\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -2313,7 +2316,7 @@ STEXI
 Output log in logfile instead of /tmp/qemu.log
 ETEXI
 
-DEF("hdachs", HAS_ARG, QEMU_OPTION_hdachs, \
+GDEF("hdachs", HAS_ARG, QEMU_OPTION_hdachs, \
     "-hdachs c,h,s[,t]\n" \
     "                force hard disk 0 physical geometry and the optional BIOS\n" \
     "                translation (t=none or lba) (usually qemu can guess them)\n",
@@ -2328,7 +2331,7 @@ all those parameters. This option is useful for old MS-DOS disk
 images.
 ETEXI
 
-DEF("L", HAS_ARG, QEMU_OPTION_L, \
+GDEF("L", HAS_ARG, QEMU_OPTION_L, \
     "-L path         set the directory for the BIOS, VGA BIOS and keymaps\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -2337,7 +2340,7 @@ STEXI
 Set the directory for the BIOS, VGA BIOS and keymaps.
 ETEXI
 
-DEF("bios", HAS_ARG, QEMU_OPTION_bios, \
+GDEF("bios", HAS_ARG, QEMU_OPTION_bios, \
     "-bios file      set the filename for the BIOS\n", QEMU_ARCH_ALL)
 STEXI
 @item -bios @var{file}
@@ -2345,7 +2348,7 @@ STEXI
 Set the filename for the BIOS.
 ETEXI
 
-DEF("enable-kvm", 0, QEMU_OPTION_enable_kvm, \
+GDEF("enable-kvm", 0, QEMU_OPTION_enable_kvm, \
     "-enable-kvm     enable KVM full virtualization support\n", QEMU_ARCH_ALL)
 STEXI
 @item -enable-kvm
@@ -2354,13 +2357,13 @@ Enable KVM full virtualization support. This option is only available
 if KVM support is enabled when compiling.
 ETEXI
 
-DEF("xen-domid", HAS_ARG, QEMU_OPTION_xen_domid,
+GDEF("xen-domid", HAS_ARG, QEMU_OPTION_xen_domid,
     "-xen-domid id   specify xen guest domain id\n", QEMU_ARCH_ALL)
-DEF("xen-create", 0, QEMU_OPTION_xen_create,
+GDEF("xen-create", 0, QEMU_OPTION_xen_create,
     "-xen-create     create domain using xen hypercalls, bypassing xend\n"
     "                warning: should not be used when xend is in use\n",
     QEMU_ARCH_ALL)
-DEF("xen-attach", 0, QEMU_OPTION_xen_attach,
+GDEF("xen-attach", 0, QEMU_OPTION_xen_attach,
     "-xen-attach     attach to existing xen domain\n"
     "                xend will use this when starting qemu\n",
     QEMU_ARCH_ALL)
@@ -2378,7 +2381,7 @@ Attach to existing xen domain.
 xend will use this when starting qemu (XEN only).
 ETEXI
 
-DEF("no-reboot", 0, QEMU_OPTION_no_reboot, \
+GDEF("no-reboot", 0, QEMU_OPTION_no_reboot, \
     "-no-reboot      exit instead of rebooting\n", QEMU_ARCH_ALL)
 STEXI
 @item -no-reboot
@@ -2386,7 +2389,7 @@ STEXI
 Exit instead of rebooting.
 ETEXI
 
-DEF("no-shutdown", 0, QEMU_OPTION_no_shutdown, \
+GDEF("no-shutdown", 0, QEMU_OPTION_no_shutdown, \
     "-no-shutdown    stop before shutdown\n", QEMU_ARCH_ALL)
 STEXI
 @item -no-shutdown
@@ -2396,7 +2399,7 @@ This allows for instance switching to monitor to commit changes to the
 disk image.
 ETEXI
 
-DEF("loadvm", HAS_ARG, QEMU_OPTION_loadvm, \
+GDEF("loadvm", HAS_ARG, QEMU_OPTION_loadvm, \
     "-loadvm [tag|id]\n" \
     "                start right away with a saved state (loadvm in monitor)\n",
     QEMU_ARCH_ALL)
@@ -2407,7 +2410,7 @@ Start right away with a saved state (@code{loadvm} in monitor)
 ETEXI
 
 #ifndef _WIN32
-DEF("daemonize", 0, QEMU_OPTION_daemonize, \
+GDEF("daemonize", 0, QEMU_OPTION_daemonize, \
     "-daemonize      daemonize QEMU after initializing\n", QEMU_ARCH_ALL)
 #endif
 STEXI
@@ -2419,7 +2422,7 @@ This option is a useful way for external programs to launch QEMU without having
 to cope with initialization race conditions.
 ETEXI
 
-DEF("option-rom", HAS_ARG, QEMU_OPTION_option_rom, \
+GDEF("option-rom", HAS_ARG, QEMU_OPTION_option_rom, \
     "-option-rom rom load a file, rom, into the option ROM space\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -2429,7 +2432,7 @@ Load the contents of @var{file} as an option ROM.
 This option is useful to load things like EtherBoot.
 ETEXI
 
-DEF("clock", HAS_ARG, QEMU_OPTION_clock, \
+GDEF("clock", HAS_ARG, QEMU_OPTION_clock, \
     "-clock          force the use of the given methods for timer alarm.\n" \
     "                To see what timers are available use -clock ?\n",
     QEMU_ARCH_ALL)
@@ -2441,8 +2444,8 @@ are available use -clock ?.
 ETEXI
 
 HXCOMM Options deprecated by -rtc
-DEF("localtime", 0, QEMU_OPTION_localtime, "", QEMU_ARCH_ALL)
-DEF("startdate", HAS_ARG, QEMU_OPTION_startdate, "", QEMU_ARCH_ALL)
+GDEF("localtime", 0, QEMU_OPTION_localtime, "", QEMU_ARCH_ALL)
+GDEF("startdate", HAS_ARG, QEMU_OPTION_startdate, "", QEMU_ARCH_ALL)
 
 DEF("rtc", HAS_ARG, QEMU_OPTION_rtc, \
     "-rtc [base=utc|localtime|date][,clock=host|vm][,driftfix=none|slew]\n" \
@@ -2470,7 +2473,7 @@ many timer interrupts were not processed by the Windows guest and will
 re-inject them.
 ETEXI
 
-DEF("icount", HAS_ARG, QEMU_OPTION_icount, \
+GDEF("icount", HAS_ARG, QEMU_OPTION_icount, \
     "-icount [N|auto]\n" \
     "                enable virtual instruction counter with 2^N clock ticks per\n" \
     "                instruction\n", QEMU_ARCH_ALL)
@@ -2488,7 +2491,7 @@ order cores with complex cache hierarchies.  The number of instructions
 executed often has little or no correlation with actual performance.
 ETEXI
 
-DEF("watchdog", HAS_ARG, QEMU_OPTION_watchdog, \
+GDEF("watchdog", HAS_ARG, QEMU_OPTION_watchdog, \
     "-watchdog i6300esb|ib700\n" \
     "                enable virtual hardware watchdog [default=none]\n",
     QEMU_ARCH_ALL)
@@ -2509,7 +2512,7 @@ Use @code{-watchdog ?} to list available hardware models.  Only one
 watchdog can be enabled for a guest.
 ETEXI
 
-DEF("watchdog-action", HAS_ARG, QEMU_OPTION_watchdog_action, \
+GDEF("watchdog-action", HAS_ARG, QEMU_OPTION_watchdog_action, \
     "-watchdog-action reset|shutdown|poweroff|pause|debug|none\n" \
     "                action when watchdog fires [default=reset]\n",
     QEMU_ARCH_ALL)
@@ -2540,7 +2543,7 @@ Examples:
 @end table
 ETEXI
 
-DEF("echr", HAS_ARG, QEMU_OPTION_echr, \
+GDEF("echr", HAS_ARG, QEMU_OPTION_echr, \
     "-echr chr       set terminal escape character instead of ctrl-a\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -2560,7 +2563,7 @@ character to Control-t.
 @end table
 ETEXI
 
-DEF("virtioconsole", HAS_ARG, QEMU_OPTION_virtiocon, \
+GDEF("virtioconsole", HAS_ARG, QEMU_OPTION_virtiocon, \
     "-virtioconsole c\n" \
     "                set virtio console\n", QEMU_ARCH_ALL)
 STEXI
@@ -2573,7 +2576,7 @@ This option is maintained for backward compatibility.
 Please use @code{-device virtconsole} for the new way of invocation.
 ETEXI
 
-DEF("show-cursor", 0, QEMU_OPTION_show_cursor, \
+GDEF("show-cursor", 0, QEMU_OPTION_show_cursor, \
     "-show-cursor    show cursor\n", QEMU_ARCH_ALL)
 STEXI
 @item -show-cursor
@@ -2581,7 +2584,7 @@ STEXI
 Show cursor.
 ETEXI
 
-DEF("tb-size", HAS_ARG, QEMU_OPTION_tb_size, \
+GDEF("tb-size", HAS_ARG, QEMU_OPTION_tb_size, \
     "-tb-size n      set TB size\n", QEMU_ARCH_ALL)
 STEXI
 @item -tb-size @var{n}
@@ -2589,7 +2592,7 @@ STEXI
 Set TB size.
 ETEXI
 
-DEF("incoming", HAS_ARG, QEMU_OPTION_incoming, \
+GDEF("incoming", HAS_ARG, QEMU_OPTION_incoming, \
     "-incoming p     prepare for incoming migration, listen on port p\n",
     QEMU_ARCH_ALL)
 STEXI
@@ -2598,7 +2601,7 @@ STEXI
 Prepare for incoming migration, listen on @var{port}.
 ETEXI
 
-DEF("nodefaults", 0, QEMU_OPTION_nodefaults, \
+GDEF("nodefaults", 0, QEMU_OPTION_nodefaults, \
     "-nodefaults     don't create default devices\n", QEMU_ARCH_ALL)
 STEXI
 @item -nodefaults
@@ -2607,7 +2610,7 @@ Don't create default devices.
 ETEXI
 
 #ifndef _WIN32
-DEF("chroot", HAS_ARG, QEMU_OPTION_chroot, \
+GDEF("chroot", HAS_ARG, QEMU_OPTION_chroot, \
     "-chroot dir     chroot to dir just before starting the VM\n",
     QEMU_ARCH_ALL)
 #endif
@@ -2619,7 +2622,7 @@ directory.  Especially useful in combination with -runas.
 ETEXI
 
 #ifndef _WIN32
-DEF("runas", HAS_ARG, QEMU_OPTION_runas, \
+GDEF("runas", HAS_ARG, QEMU_OPTION_runas, \
     "-runas user     change to user id user just before starting the VM\n",
     QEMU_ARCH_ALL)
 #endif
@@ -2630,7 +2633,7 @@ Immediately before starting guest execution, drop root privileges, switching
 to the specified user.
 ETEXI
 
-DEF("prom-env", HAS_ARG, QEMU_OPTION_prom_env,
+GDEF("prom-env", HAS_ARG, QEMU_OPTION_prom_env,
     "-prom-env variable=value\n"
     "                set OpenBIOS nvram variables\n",
     QEMU_ARCH_PPC | QEMU_ARCH_SPARC)
@@ -2639,14 +2642,14 @@ STEXI
 @findex -prom-env
 Set OpenBIOS nvram @var{variable} to given @var{value} (PPC, SPARC only).
 ETEXI
-DEF("semihosting", 0, QEMU_OPTION_semihosting,
+GDEF("semihosting", 0, QEMU_OPTION_semihosting,
     "-semihosting    semihosting mode\n", QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA)
 STEXI
 @item -semihosting
 @findex -semihosting
 Semihosting mode (ARM, M68K, Xtensa only).
 ETEXI
-DEF("old-param", 0, QEMU_OPTION_old_param,
+GDEF("old-param", 0, QEMU_OPTION_old_param,
     "-old-param      old param mode\n", QEMU_ARCH_ARM)
 STEXI
 @item -old-param
@@ -2654,14 +2657,14 @@ STEXI
 Old param mode (ARM only).
 ETEXI
 
-DEF("readconfig", HAS_ARG, QEMU_OPTION_readconfig,
+GDEF("readconfig", HAS_ARG, QEMU_OPTION_readconfig,
     "-readconfig <file>\n", QEMU_ARCH_ALL)
 STEXI
 @item -readconfig @var{file}
 @findex -readconfig
 Read device configuration from @var{file}.
 ETEXI
-DEF("writeconfig", HAS_ARG, QEMU_OPTION_writeconfig,
+GDEF("writeconfig", HAS_ARG, QEMU_OPTION_writeconfig,
     "-writeconfig <file>\n"
     "                read/write config file\n", QEMU_ARCH_ALL)
 STEXI
@@ -2669,7 +2672,7 @@ STEXI
 @findex -writeconfig
 Write device configuration to @var{file}.
 ETEXI
-DEF("nodefconfig", 0, QEMU_OPTION_nodefconfig,
+GDEF("nodefconfig", 0, QEMU_OPTION_nodefconfig,
     "-nodefconfig\n"
     "                do not load default config files at startup\n",
     QEMU_ARCH_ALL)
diff --git a/vl.c b/vl.c
index 18cea4b..9a7ad40 100644
--- a/vl.c
+++ b/vl.c
@@ -1588,6 +1588,7 @@ typedef struct QEMUOption {
     int flags;
     int index;
     uint32_t arch_mask;
+    bool global;
 } QEMUOption;
 
 static const QEMUOption qemu_options[] = {
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 5/9] vl: enable system configuration to be used
  2012-03-19 15:09 [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Anthony Liguori
                   ` (3 preceding siblings ...)
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 4/9] vl: mark system configuration options in qemu-options.hx Anthony Liguori
@ 2012-03-19 15:09 ` Anthony Liguori
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 6/9] vl: parse all options via QemuOpts Anthony Liguori
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 26+ messages in thread
From: Anthony Liguori @ 2012-03-19 15:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Eric Blake, Eduardo Habkost, Gerd Hoffman

Now that we have options grouped, allow the [system] section to be used to set
these options.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 vl.c |   62 +++++++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 53 insertions(+), 9 deletions(-)

diff --git a/vl.c b/vl.c
index 9a7ad40..5e86311 100644
--- a/vl.c
+++ b/vl.c
@@ -2187,6 +2187,24 @@ static void qemu_run_machine_init_done_notifiers(void)
     notifier_list_notify(&machine_init_done_notifiers, NULL);
 }
 
+static const QEMUOption *find_opt_by_name(const char *name)
+{
+    const QEMUOption *popt;
+
+    popt = qemu_options;
+    for(;;) {
+        if (!popt->name) {
+            break;
+        }
+        if (!strcmp(popt->name, name)) {
+            return popt;
+        }
+        popt++;
+    }
+
+    return NULL;
+}
+
 static const QEMUOption *lookup_opt(int argc, char **argv,
                                     const char **poptarg, int *poptind)
 {
@@ -2200,15 +2218,10 @@ static const QEMUOption *lookup_opt(int argc, char **argv,
     /* Treat --foo the same as -foo.  */
     if (r[1] == '-')
         r++;
-    popt = qemu_options;
-    for(;;) {
-        if (!popt->name) {
-            error_report("invalid option");
-            exit(1);
-        }
-        if (!strcmp(popt->name, r + 1))
-            break;
-        popt++;
+    popt = find_opt_by_name(r + 1);
+    if (popt == NULL) {
+        error_report("invalid option");
+        exit(1);
     }
     if (popt->flags & HAS_ARG) {
         if (optind >= argc) {
@@ -2273,6 +2286,35 @@ typedef struct QemuOptions
     int defconfig;
 } QemuOptions;
 
+static void qemu_parse_option(int index, const char *optarg, QemuOptions *options);
+
+static int qemu_parse_system_option(const char *name, const char *value, void *opaque)
+{
+    QemuOptions *options = opaque;
+    const QEMUOption *popt;
+
+    popt = find_opt_by_name(name);
+    if (popt == NULL) {
+        return -1;
+    }
+
+    qemu_parse_option(popt->index, value, options);
+
+    return 0;
+}
+
+static int qemu_parse_system_section(QemuOpts *opts, void *opaque)
+{
+    QemuOptions *options = opaque;
+
+    return qemu_opt_foreach(opts, qemu_parse_system_option, options, 0);
+}
+
+static void qemu_parse_system_sections(QemuOptions *options)
+{
+    qemu_opts_foreach(qemu_find_opts("system"), qemu_parse_system_section, options, 1);
+}
+
 static void qemu_parse_option(int index, const char *optarg, QemuOptions *options)
 {
     QemuOpts *opts;
@@ -3143,6 +3185,8 @@ static void qemu_parse_options(int argc, char **argv, QemuOptions *options)
             qemu_parse_option(popt->index, optarg, options);
         }
     }
+
+    qemu_parse_system_sections(options);
 }
 
 int main(int argc, char **argv, char **envp)
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 6/9] vl: parse all options via QemuOpts
  2012-03-19 15:09 [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Anthony Liguori
                   ` (4 preceding siblings ...)
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 5/9] vl: enable system configuration to be used Anthony Liguori
@ 2012-03-19 15:09 ` Anthony Liguori
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 7/9] qmp: expose a command to query capabilities of config parser Anthony Liguori
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 26+ messages in thread
From: Anthony Liguori @ 2012-03-19 15:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Eric Blake, Eduardo Habkost, Gerd Hoffman

In order to have -writeconfig work as expected, we need to first store command
line options into a QemuOpts and then we can parse the QemuOpts just like any
other [system] section.

QemuOpts is careful to preserve order so the semantics of this should be
completely identical.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 vl.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/vl.c b/vl.c
index 5e86311..5337e58 100644
--- a/vl.c
+++ b/vl.c
@@ -3132,6 +3132,7 @@ static void qemu_parse_options(int argc, char **argv, QemuOptions *options)
 {
     int optind;
     const char *optarg;
+    QemuOpts *system_opts;
 
     /* first pass of option parsing */
     optind = 1;
@@ -3166,13 +3167,15 @@ static void qemu_parse_options(int argc, char **argv, QemuOptions *options)
         }
     }
 
+    system_opts = qemu_opts_create(qemu_find_opts("system"), NULL, 0);
+
     /* second pass of option parsing */
     optind = 1;
     for(;;) {
         if (optind >= argc)
             break;
         if (argv[optind][0] != '-') {
-	    options->hda_opts = drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS);
+            qemu_opt_set(system_opts, "hda", argv[optind++]);
         } else {
             const QEMUOption *popt;
 
@@ -3182,7 +3185,11 @@ static void qemu_parse_options(int argc, char **argv, QemuOptions *options)
                 exit(1);
             }
 
-            qemu_parse_option(popt->index, optarg, options);
+            if ((popt->flags & HAS_ARG)) {
+                qemu_opt_set(system_opts, popt->name, optarg);
+            } else {
+                qemu_opt_set_bool(system_opts, popt->name, true);
+            }
         }
     }
 
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 7/9] qmp: expose a command to query capabilities of config parser
  2012-03-19 15:09 [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Anthony Liguori
                   ` (5 preceding siblings ...)
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 6/9] vl: parse all options via QemuOpts Anthony Liguori
@ 2012-03-19 15:09 ` Anthony Liguori
  2012-03-19 20:10   ` Eric Blake
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 8/9] vl: add -query-capabilities Anthony Liguori
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 26+ messages in thread
From: Anthony Liguori @ 2012-03-19 15:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Eric Blake, Eduardo Habkost, Gerd Hoffman

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 qapi-schema.json |   66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-config.c    |   51 +++++++++++++++++++++++++++++++++++++++++
 qmp-commands.hx  |    5 ++++
 3 files changed, 122 insertions(+), 0 deletions(-)

diff --git a/qapi-schema.json b/qapi-schema.json
index 04fa84f..2a80ef6 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1663,3 +1663,69 @@
 { 'command': 'qom-list-types',
   'data': { '*implements': 'str', '*abstract': 'bool' },
   'returns': [ 'ObjectTypeInfo' ] }
+
+##
+# @ConfigOptionType
+#
+# An enumeration describing the type of a configuration file entry.
+#
+# @string: a UTF-8 string
+#
+# @bool: either 'on' or 'off'
+#
+# @number: an integer
+#
+# @size: an integer followed by either 'K', 'M', 'G', or 'T'.
+#
+# Since: 1.1
+##
+{ 'enum': 'ConfigOptionType'
+  'data': [ 'string', 'bool', 'number', 'size' ] }
+
+##
+# @ConfigOption
+#
+# An option within a configuration section.
+#
+# @name: the name of the configuration option
+#
+# @type: the type of the configuration option
+#
+# @help: an optional help description.  This should not be parsed or relied upon
+#        in any way.  Its content's may change in future versions of QEMU.
+#
+# Since: 1.1
+##
+{ 'type': 'ConfigOption',
+  'data': { 'name': 'str',
+            'type': 'ConfigOptionType',
+            '*help': 'str' } }
+
+##
+# @ConfigSection
+#
+# A section within a configuration file.
+#
+# @name:       the section name
+#
+# @parameters: a list of supported parameters
+#
+# Since: 1.1
+##
+{ 'type': 'ConfigSection',
+  'data': { 'name': 'str',
+            'parameters': [ 'ConfigOption' ] } }
+
+##
+# @query-config-capabilities
+#
+# Returns the current set of capabilities supported by the various QEMU commands
+# that work with configuration files.
+#
+# Returns: a list of @ConfigSections describe the currently supported
+#          configuration sections.
+#
+# Since: 1.1
+##
+{ 'command': 'query-config-capabilities',
+  'returns': [ 'ConfigSection' ] }
diff --git a/qemu-config.c b/qemu-config.c
index 5856e5a..447aad6 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -2,6 +2,7 @@
 #include "qemu-error.h"
 #include "qemu-option.h"
 #include "qemu-config.h"
+#include "qmp-commands.h"
 #include "hw/qdev.h"
 #include "gdbstub.h"
 #include "net.h"
@@ -866,3 +867,53 @@ int qemu_read_config_file(const char *filename)
 {
     return qemu_config_parse(vm_config_groups, filename);
 }
+
+ConfigSectionList *qmp_query_config_capabilities(Error **errp)
+{
+    ConfigSectionList *lst = NULL;
+    int i;
+
+    for (i = 0; vm_config_groups[i]; i++) {
+        QemuOptsList *olist = vm_config_groups[i];
+        ConfigSection *s = g_malloc0(sizeof(*s));
+        ConfigSectionList *e = g_malloc0(sizeof(*e));
+        QemuOptDesc *desc;
+
+        s->name = g_strdup(olist->name);
+        for (desc = olist->desc; desc->name; desc++) {
+            ConfigOption *o = g_malloc0(sizeof(*o));
+            ConfigOptionList *oe = g_malloc0(sizeof(*oe));
+
+            o->name = g_strdup(desc->name);
+            switch (desc->type) {
+            case QEMU_OPT_STRING:
+                o->type = CONFIG_OPTION_TYPE_STRING;
+                break;
+            case QEMU_OPT_BOOL:
+                o->type = CONFIG_OPTION_TYPE_BOOL;
+                break;
+            case QEMU_OPT_NUMBER:
+                o->type = CONFIG_OPTION_TYPE_NUMBER;
+                break;
+            case QEMU_OPT_SIZE:
+                o->type = CONFIG_OPTION_TYPE_SIZE;
+                break;
+            }
+
+            if (desc->help) {
+                o->has_help = true;
+                o->help = g_strdup(desc->help);
+            }
+
+            oe->value = o;
+            oe->next = s->parameters;
+            s->parameters = oe;
+        }
+
+        e->value = s;
+        e->next = lst;
+        lst = e;
+    }
+
+    return lst;
+}
diff --git a/qmp-commands.hx b/qmp-commands.hx
index dfe8a5b..8024995 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2125,3 +2125,8 @@ EQMP
         .args_type  = "implements:s?,abstract:b?",
         .mhandler.cmd_new = qmp_marshal_input_qom_list_types,
     },
+    {
+        .name       = "query-config-capabilities",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_config_capabilities,
+    },
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 8/9] vl: add -query-capabilities
  2012-03-19 15:09 [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Anthony Liguori
                   ` (6 preceding siblings ...)
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 7/9] qmp: expose a command to query capabilities of config parser Anthony Liguori
@ 2012-03-19 15:09 ` Anthony Liguori
  2012-03-20  7:49   ` Gerd Hoffmann
  2012-03-20 19:39   ` Eduardo Habkost
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 9/9] Add a management tool writer's guide Anthony Liguori
  2012-03-19 16:09 ` [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Paolo Bonzini
  9 siblings, 2 replies; 26+ messages in thread
From: Anthony Liguori @ 2012-03-19 15:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Eric Blake, Eduardo Habkost, Gerd Hoffman

This dumps the results of query-version, query-commands, and
query-config-capabilities into a single JSON object on stdout.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 qemu-options.hx |    4 ++++
 vl.c            |   27 +++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index 584dc76..4d760d8 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2710,6 +2710,10 @@ the @var{simple} tracing backend.
 @end table
 ETEXI
 
+DEF("query-capabilities", 0, QEMU_OPTION_query_capabilities,
+    "-query-capabilities  print QEMU capabilities and exit\n",
+    QEMU_ARCH_ALL)
+
 HXCOMM This is the last statement. Insert new options before this line!
 STEXI
 @end table
diff --git a/vl.c b/vl.c
index 5337e58..88626aa 100644
--- a/vl.c
+++ b/vl.c
@@ -2265,6 +2265,29 @@ int qemu_init_main_loop(void)
     return main_loop_init();
 }
 
+static void qemu_print_capabilities(void)
+{
+    QObject *version, *commands, *config;
+    QDict *dict;
+    QString *json;
+
+    qmp_marshal_input_query_version(NULL, NULL, &version);
+    qmp_marshal_input_query_commands(NULL, NULL, &commands);
+    qmp_marshal_input_query_config_capabilities(NULL, NULL, &config);
+
+    dict = qdict_new();
+    qdict_put_obj(dict, "version", version);
+    qdict_put_obj(dict, "commands", commands);
+    qdict_put_obj(dict, "config", config);
+
+    json = qobject_to_json_pretty(QOBJECT(dict));
+
+    printf("%s\n", qstring_get_str(json));
+
+    QDECREF(json);
+    QDECREF(dict);
+}
+
 typedef struct QemuOptions
 {
     QEMUMachine *machine;
@@ -3123,6 +3146,10 @@ static void qemu_parse_option(int index, const char *optarg, QemuOptions *option
             fclose(fp);
             break;
         }
+    case QEMU_OPTION_query_capabilities:
+        qemu_print_capabilities();
+        exit(0);
+        break;
     default:
         os_parse_cmd_args(index, optarg);
     }
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 9/9] Add a management tool writer's guide
  2012-03-19 15:09 [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Anthony Liguori
                   ` (7 preceding siblings ...)
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 8/9] vl: add -query-capabilities Anthony Liguori
@ 2012-03-19 15:09 ` Anthony Liguori
  2012-03-19 16:09 ` [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Paolo Bonzini
  9 siblings, 0 replies; 26+ messages in thread
From: Anthony Liguori @ 2012-03-19 15:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Eric Blake, Eduardo Habkost, Gerd Hoffman

I guess it's long overdue at this point, but let's use it to explain how to
properly use -query-capabilities.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 docs/management-tools.md |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+), 0 deletions(-)
 create mode 100644 docs/management-tools.md

diff --git a/docs/management-tools.md b/docs/management-tools.md
new file mode 100644
index 0000000..d879e48
--- /dev/null
+++ b/docs/management-tools.md
@@ -0,0 +1,31 @@
+Writing a QEMU Management Tool
+==============================
+
+This is a guide on writing a QEMU management tool.  This document outlines
+which interfaces the QEMU project exports and will support long term.
+
+Specifying options
+------------------
+
+The preferred way for a management tool to specify options to QEMU is to create
+a configuration file and use '-readconfig' on the command line.  We prefer this
+interface over direct use of command line options because this interface
+supports introspection in a machine friendly way.
+
+Determining if an option is supported
+-------------------------------------
+
+A management tool should use the '-query-capabilities' option to determine what
+the capabilities of the current QEMU executable is.  The 'config' section of
+the resulting JSON object describes all of the config sections that are
+currently supported.
+
+Many options currently fall into the 'system' section and some of these options
+have complex syntax.  Management tools should assume that these syntaxes will
+never change and never be extended.  Whenever there is a need to change or
+extend this syntax, we will first convert the option to use a stand alone
+section.
+
+While help text is available, the help text *should not* be parsed to attempt to
+determine if the option has changed.  The help text is exposed merely as a stop
+gap to help libvirt transition to this new format.
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes
  2012-03-19 15:09 [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Anthony Liguori
                   ` (8 preceding siblings ...)
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 9/9] Add a management tool writer's guide Anthony Liguori
@ 2012-03-19 16:09 ` Paolo Bonzini
  2012-03-19 16:31   ` Anthony Liguori
  2012-03-20 19:47   ` Eduardo Habkost
  9 siblings, 2 replies; 26+ messages in thread
From: Paolo Bonzini @ 2012-03-19 16:09 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Gerd Hoffman, Eric Blake, qemu-devel, Eduardo Habkost

Il 19/03/2012 16:09, Anthony Liguori ha scritto:
> Hi,
> 
> I didn't start out intending to write this series, but I end up here trying to
> resolve an issue in the gtk UI.

What issue? :)

> This series does some dramatic refactoring to -readconfig essentially throwing
> away the existing (trivial) implementation and replacing it with glib's
> GKeyFile support.

Nice.

> It also plumbs the existing command line options through QemuOpts via a special
> 'system' section.  This means that any command line option can be specified via
> readconfig and that the combination of -nodefconfig and -writeconfig should give
> you exactly the same guest in a repeatable fashion.

I don't like this because it turns command-line options into ABI.  Also,
it puts there some options for which -writeconfig is actually able to
produce a QemuOpts equivalent, such as -monitor.

I have a few patches here that convert almost every option that matters
into QemuOpts so that -writeconfig records it: -m, -bios, -localtime,
-S, -M, -smp, -numa, -nodefaults, -no-shutdown, -no-reboot.  The only
thing that is left basically is -display, where I chickened out.

> Finally, this series exposes a new -query-capabilities option which dumps the
> QemuOpts schema's via JSON to standard output (along with some other goodies
> like the version info and supported QMP commands).
> 
> The purpose of this series is to change the way management tools (esp libvirt)
> interact with QEMU to determine capabilities.  Instead of help parsing, libvirt
> should use -query-capabilities to figure out which options are supported and
> when new suboptions are available.
> 
> I would like to push this series into 1.1

I think it's too early.  However, we can definitely apply 1/2/7/8/9 now.

Paolo

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes
  2012-03-19 16:09 ` [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Paolo Bonzini
@ 2012-03-19 16:31   ` Anthony Liguori
  2012-03-19 16:33     ` Paolo Bonzini
  2012-03-20  7:54     ` Gerd Hoffmann
  2012-03-20 19:47   ` Eduardo Habkost
  1 sibling, 2 replies; 26+ messages in thread
From: Anthony Liguori @ 2012-03-19 16:31 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Anthony Liguori, Eric Blake, Gerd Hoffman, Eduardo Habkost,
	qemu-devel

On 03/19/2012 11:09 AM, Paolo Bonzini wrote:
> Il 19/03/2012 16:09, Anthony Liguori ha scritto:
>> Hi,
>>
>> I didn't start out intending to write this series, but I end up here trying to
>> resolve an issue in the gtk UI.
>
> What issue? :)

I rewrote the scaling support and did some usability testing with my 
unsuspecting wife...  To make a long story short, my take away was that I need a 
way to have persistent configuration options.  That got me looking at 
readconfig/writeconfig.

>
>> This series does some dramatic refactoring to -readconfig essentially throwing
>> away the existing (trivial) implementation and replacing it with glib's
>> GKeyFile support.
>
> Nice.
>
>> It also plumbs the existing command line options through QemuOpts via a special
>> 'system' section.  This means that any command line option can be specified via
>> readconfig and that the combination of -nodefconfig and -writeconfig should give
>> you exactly the same guest in a repeatable fashion.
>
> I don't like this because it turns command-line options into ABI.

It's already an ABI, no?

> Also,
> it puts there some options for which -writeconfig is actually able to
> produce a QemuOpts equivalent, such as -monitor.

That may be a bug depending on what your concern is.  Can you be more specific?

> I have a few patches here that convert almost every option that matters
> into QemuOpts so that -writeconfig records it: -m, -bios, -localtime,
> -S, -M, -smp, -numa, -nodefaults, -no-shutdown, -no-reboot.  The only
> thing that is left basically is -display, where I chickened out.

This series is complimentary to this.  You can still promote options to 
QemuOpts.  The advantage of this series is that we provide a programmatic way 
for libvirt to discover when this happens.

If you look at the management guide that I included, I made a strong statement 
that we promise to never extend existing options without first converting to 
QemuOpts.

>
>> Finally, this series exposes a new -query-capabilities option which dumps the
>> QemuOpts schema's via JSON to standard output (along with some other goodies
>> like the version info and supported QMP commands).
>>
>> The purpose of this series is to change the way management tools (esp libvirt)
>> interact with QEMU to determine capabilities.  Instead of help parsing, libvirt
>> should use -query-capabilities to figure out which options are supported and
>> when new suboptions are available.
>>
>> I would like to push this series into 1.1
>
> I think it's too early.  However, we can definitely apply 1/2/7/8/9 now.

Let's go through the discussion and see where we end up.  I was just stating my 
intentions so that folks reviewed appropriately.

But I realize there's a lot of discussion that needs to happen before we make 
this type of commitment for 1.1.

Regards,

Anthony Liguori

>
> Paolo
>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes
  2012-03-19 16:31   ` Anthony Liguori
@ 2012-03-19 16:33     ` Paolo Bonzini
  2012-03-19 16:41       ` Anthony Liguori
  2012-03-20  7:54     ` Gerd Hoffmann
  1 sibling, 1 reply; 26+ messages in thread
From: Paolo Bonzini @ 2012-03-19 16:33 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: Anthony Liguori, Eric Blake, Gerd Hoffman, Eduardo Habkost,
	qemu-devel

Il 19/03/2012 17:31, Anthony Liguori ha scritto:
>>> It also plumbs the existing command line options through QemuOpts via
>>> a special
>>> 'system' section.  This means that any command line option can be
>>> specified via
>>> readconfig and that the combination of -nodefconfig and -writeconfig
>>> should give
>>> you exactly the same guest in a repeatable fashion.
>>
>> I don't like this because it turns command-line options into ABI.
> 
> It's already an ABI, no?

Right, sorry.  Into configuration file ABI, which is supposed to be the
"cleaner" ABI.

>> Also, it puts there some options for which -writeconfig is actually
>> able to produce a QemuOpts equivalent, such as -monitor.
> 
> That may be a bug depending on what your concern is.  Can you be more
> specific?

If you write "-monitor stdio" with your series, do you get one or two
monitors in the resulting configuration file?

Paolo

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes
  2012-03-19 16:33     ` Paolo Bonzini
@ 2012-03-19 16:41       ` Anthony Liguori
  2012-03-19 16:45         ` Paolo Bonzini
  0 siblings, 1 reply; 26+ messages in thread
From: Anthony Liguori @ 2012-03-19 16:41 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Anthony Liguori, Eric Blake, Gerd Hoffman, Eduardo Habkost,
	qemu-devel

On 03/19/2012 11:33 AM, Paolo Bonzini wrote:
> Il 19/03/2012 17:31, Anthony Liguori ha scritto:
>>>> It also plumbs the existing command line options through QemuOpts via
>>>> a special
>>>> 'system' section.  This means that any command line option can be
>>>> specified via
>>>> readconfig and that the combination of -nodefconfig and -writeconfig
>>>> should give
>>>> you exactly the same guest in a repeatable fashion.
>>>
>>> I don't like this because it turns command-line options into ABI.
>>
>> It's already an ABI, no?
>
> Right, sorry.  Into configuration file ABI, which is supposed to be the
> "cleaner" ABI.

Right, the basic premise of this series is "perfect is the enemy of good".  I 
think we do ourselves more harm than good trying to come up with a clean new 
interface instead of just cleaning up the bits behind what we previously had.

If you look at the goodness that comes from taking the interface as we have it 
now instead of trying to arrive at the perfect interface, I think going with the 
good approach has a lot of short term return.

>
>>> Also, it puts there some options for which -writeconfig is actually
>>> able to produce a QemuOpts equivalent, such as -monitor.
>>
>> That may be a bug depending on what your concern is.  Can you be more
>> specific?
>
> If you write "-monitor stdio" with your series, do you get one or two
> monitors in the resulting configuration file?

Two, I now understand what you're saying.  Let me look into fixing that.  This 
is more about -writeconfig.  We need to record the origin of a particular 
QemuOpt and have -writeconfig spit out only things that came from -readconfig.

Essentially, we need "-writeconfig of what's been changed from -readconfig" and 
"-writeconfig that is used strictly with -nodefconfig".

One of the nice things about GKeyFile is that it has intelligence to preserve 
comments so we can make -writeconfig be very non-intrusive.

Regards,

Anthony Liguori

>
> Paolo

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes
  2012-03-19 16:41       ` Anthony Liguori
@ 2012-03-19 16:45         ` Paolo Bonzini
  2012-03-19 16:53           ` Anthony Liguori
  0 siblings, 1 reply; 26+ messages in thread
From: Paolo Bonzini @ 2012-03-19 16:45 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: Anthony Liguori, Eric Blake, Gerd Hoffman, Eduardo Habkost,
	qemu-devel

Il 19/03/2012 17:41, Anthony Liguori ha scritto:
> On 03/19/2012 11:33 AM, Paolo Bonzini wrote:
>> Il 19/03/2012 17:31, Anthony Liguori ha scritto:
>>>>> It also plumbs the existing command line options through QemuOpts via
>>>>> a special
>>>>> 'system' section.  This means that any command line option can be
>>>>> specified via
>>>>> readconfig and that the combination of -nodefconfig and -writeconfig
>>>>> should give
>>>>> you exactly the same guest in a repeatable fashion.
>>>>
>>>> I don't like this because it turns command-line options into ABI.
>>>
>>> It's already an ABI, no?
>>
>> Right, sorry.  Into configuration file ABI, which is supposed to be the
>> "cleaner" ABI.
> 
> Right, the basic premise of this series is "perfect is the enemy of
> good".  I think we do ourselves more harm than good trying to come up
> with a clean new interface instead of just cleaning up the bits behind
> what we previously had.

Yeah,it depends on what you consider good. :)  My direction was like
"let's cover 90% of the usecases with a decent syntax"; yours is "let's
cover 100% of the usecases even though the syntax may stink".

(There's time to convert -display before 1.1, which would make 99%).

>>>> Also, it puts there some options for which -writeconfig is actually
>>>> able to produce a QemuOpts equivalent, such as -monitor.
>>>
>>> That may be a bug depending on what your concern is.  Can you be more
>>> specific?
>>
>> If you write "-monitor stdio" with your series, do you get one or two
>> monitors in the resulting configuration file?
> 
> Two, I now understand what you're saying.  Let me look into fixing
> that.  This is more about -writeconfig.  We need to record the origin of
> a particular QemuOpt and have -writeconfig spit out only things that
> came from -readconfig.

I think it's simpler than that.  Just don't mark as gdef those options
that are backed internally by QemuOpts.

Paolo

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes
  2012-03-19 16:45         ` Paolo Bonzini
@ 2012-03-19 16:53           ` Anthony Liguori
  2012-03-19 17:03             ` Paolo Bonzini
  0 siblings, 1 reply; 26+ messages in thread
From: Anthony Liguori @ 2012-03-19 16:53 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: qemu-devel, Anthony Liguori, Eric Blake, Gerd Hoffman,
	Eduardo Habkost

On 03/19/2012 11:45 AM, Paolo Bonzini wrote:
> Il 19/03/2012 17:41, Anthony Liguori ha scritto:
>> On 03/19/2012 11:33 AM, Paolo Bonzini wrote:
>>> Il 19/03/2012 17:31, Anthony Liguori ha scritto:
>>>>>> It also plumbs the existing command line options through QemuOpts via
>>>>>> a special
>>>>>> 'system' section.  This means that any command line option can be
>>>>>> specified via
>>>>>> readconfig and that the combination of -nodefconfig and -writeconfig
>>>>>> should give
>>>>>> you exactly the same guest in a repeatable fashion.
>>>>>
>>>>> I don't like this because it turns command-line options into ABI.
>>>>
>>>> It's already an ABI, no?
>>>
>>> Right, sorry.  Into configuration file ABI, which is supposed to be the
>>> "cleaner" ABI.
>>
>> Right, the basic premise of this series is "perfect is the enemy of
>> good".  I think we do ourselves more harm than good trying to come up
>> with a clean new interface instead of just cleaning up the bits behind
>> what we previously had.
>
> Yeah,it depends on what you consider good. :)  My direction was like
> "let's cover 90% of the usecases with a decent syntax"; yours is "let's
> cover 100% of the usecases even though the syntax may stink".
>
> (There's time to convert -display before 1.1, which would make 99%).

So if we had 99% with good syntax and 1% with a syntax that stinks, that seems 
reasonable to me, no?

>>>>> Also, it puts there some options for which -writeconfig is actually
>>>>> able to produce a QemuOpts equivalent, such as -monitor.
>>>>
>>>> That may be a bug depending on what your concern is.  Can you be more
>>>> specific?
>>>
>>> If you write "-monitor stdio" with your series, do you get one or two
>>> monitors in the resulting configuration file?
>>
>> Two, I now understand what you're saying.  Let me look into fixing
>> that.  This is more about -writeconfig.  We need to record the origin of
>> a particular QemuOpt and have -writeconfig spit out only things that
>> came from -readconfig.
>
> I think it's simpler than that.  Just don't mark as gdef those options
> that are backed internally by QemuOpts.

That's already done.  But given the way the parsing works, gdef and def options 
are both stored in system's QemuOpts.  I can fix that though...

Regards,

Anthony Liguori

> Paolo
>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes
  2012-03-19 16:53           ` Anthony Liguori
@ 2012-03-19 17:03             ` Paolo Bonzini
  0 siblings, 0 replies; 26+ messages in thread
From: Paolo Bonzini @ 2012-03-19 17:03 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: qemu-devel, Anthony Liguori, Eric Blake, Gerd Hoffman,
	Eduardo Habkost

Il 19/03/2012 17:53, Anthony Liguori ha scritto:
>>
>> Yeah,it depends on what you consider good. :)  My direction was like
>> "let's cover 90% of the usecases with a decent syntax"; yours is "let's
>> cover 100% of the usecases even though the syntax may stink".
>>
>> (There's time to convert -display before 1.1, which would make 99%).
> 
> So if we had 99% with good syntax and 1% with a syntax that stinks, that
> seems reasonable to me, no?

Yeah, I suppose so. :)

Paolo

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 7/9] qmp: expose a command to query capabilities of config parser
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 7/9] qmp: expose a command to query capabilities of config parser Anthony Liguori
@ 2012-03-19 20:10   ` Eric Blake
  2012-03-19 20:19     ` Anthony Liguori
  0 siblings, 1 reply; 26+ messages in thread
From: Eric Blake @ 2012-03-19 20:10 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Gerd Hoffman, qemu-devel, Eduardo Habkost

[-- Attachment #1: Type: text/plain, Size: 1928 bytes --]

On 03/19/2012 09:09 AM, Anthony Liguori wrote:
> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
> ---
>  qapi-schema.json |   66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  qemu-config.c    |   51 +++++++++++++++++++++++++++++++++++++++++
>  qmp-commands.hx  |    5 ++++
>  3 files changed, 122 insertions(+), 0 deletions(-)
> 
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 04fa84f..2a80ef6 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -1663,3 +1663,69 @@
>  { 'command': 'qom-list-types',
>    'data': { '*implements': 'str', '*abstract': 'bool' },
>    'returns': [ 'ObjectTypeInfo' ] }
> +
> +##
> +# @ConfigOptionType
> +#
> +# An enumeration describing the type of a configuration file entry.
> +#
> +# @string: a UTF-8 string
> +#
> +# @bool: either 'on' or 'off'
> +#
> +# @number: an integer
> +#
> +# @size: an integer followed by either 'K', 'M', 'G', or 'T'.

Not quite - I found three different parsers, but none of them match this
description.  That is, qemu-option.c:parse_option_size() supports 'k'
and 'b', as well as omitting a suffix, but does not support 'm'.  Then
there's cmd.c:cvtnum(), which is case-insensitive, and adds 'p' and 'e',
but omits 'b'.  Then there's the 'o' type in monitor.c that defers to
cutils.c:strtosz(), which defaults to bytes but is case-insensitive and
supports 'b' but not 'p'.  Why are we using three different parsers, anyway?

Please be sure that your documentation exactly matches the code used by
the particular parser used for 'size', since it is is already confusing
as-is.

> +#
> +# @help: an optional help description.  This should not be parsed or relied upon
> +#        in any way.  Its content's may change in future versions of QEMU.

s/content's/contents/

-- 
Eric Blake   eblake@redhat.com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 620 bytes --]

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 7/9] qmp: expose a command to query capabilities of config parser
  2012-03-19 20:10   ` Eric Blake
@ 2012-03-19 20:19     ` Anthony Liguori
  2012-03-19 20:31       ` Eric Blake
  0 siblings, 1 reply; 26+ messages in thread
From: Anthony Liguori @ 2012-03-19 20:19 UTC (permalink / raw)
  To: Eric Blake; +Cc: Anthony Liguori, Gerd Hoffman, Eduardo Habkost, qemu-devel

On 03/19/2012 03:10 PM, Eric Blake wrote:
> On 03/19/2012 09:09 AM, Anthony Liguori wrote:
>> Signed-off-by: Anthony Liguori<aliguori@us.ibm.com>
>> ---
>>   qapi-schema.json |   66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   qemu-config.c    |   51 +++++++++++++++++++++++++++++++++++++++++
>>   qmp-commands.hx  |    5 ++++
>>   3 files changed, 122 insertions(+), 0 deletions(-)
>>
>> diff --git a/qapi-schema.json b/qapi-schema.json
>> index 04fa84f..2a80ef6 100644
>> --- a/qapi-schema.json
>> +++ b/qapi-schema.json
>> @@ -1663,3 +1663,69 @@
>>   { 'command': 'qom-list-types',
>>     'data': { '*implements': 'str', '*abstract': 'bool' },
>>     'returns': [ 'ObjectTypeInfo' ] }
>> +
>> +##
>> +# @ConfigOptionType
>> +#
>> +# An enumeration describing the type of a configuration file entry.
>> +#
>> +# @string: a UTF-8 string
>> +#
>> +# @bool: either 'on' or 'off'
>> +#
>> +# @number: an integer
>> +#
>> +# @size: an integer followed by either 'K', 'M', 'G', or 'T'.
>
> Not quite - I found three different parsers, but none of them match this
> description.

Heh, I was going by the documentation in the code:

     QEMU_OPT_SIZE,        /* size, accepts (K)ilo, (M)ega, (G)iga, (T)era 
postfix */


> That is, qemu-option.c:parse_option_size() supports 'k'
> and 'b', as well as omitting a suffix, but does not support 'm'.

TBH, I'd prefer to not document 'k' and 'b' and explicitly document that the 
suffix is optional and bytes is implied (which I thought was implied in my 
documentation, but I can see that it may not be).

I'd rather we support officially support one way of doing things and if we 
support more, do it under the mantra of being liberal in what we accept.

> Then
> there's cmd.c:cvtnum(), which is case-insensitive, and adds 'p' and 'e',
> but omits 'b'.  Then there's the 'o' type in monitor.c that defers to
> cutils.c:strtosz(), which defaults to bytes but is case-insensitive and
> supports 'b' but not 'p'.  Why are we using three different parsers, anyway?

Yes, I am aware of that, and yes, I'm going to fix it.  One bit at a time though.

> Please be sure that your documentation exactly matches the code used by
> the particular parser used for 'size', since it is is already confusing
> as-is.

Let's be careful about documenting what is the officially supported interface 
and what is possible with the given state of the code.


>> +#
>> +# @help: an optional help description.  This should not be parsed or relied upon
>> +#        in any way.  Its content's may change in future versions of QEMU.
>
> s/content's/contents/

Ack.

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 7/9] qmp: expose a command to query capabilities of config parser
  2012-03-19 20:19     ` Anthony Liguori
@ 2012-03-19 20:31       ` Eric Blake
  2012-03-19 20:41         ` Anthony Liguori
  0 siblings, 1 reply; 26+ messages in thread
From: Eric Blake @ 2012-03-19 20:31 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: Anthony Liguori, Gerd Hoffman, Eduardo Habkost, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 2464 bytes --]

On 03/19/2012 02:19 PM, Anthony Liguori wrote:
>>> +# @size: an integer followed by either 'K', 'M', 'G', or 'T'.
>>
>> Not quite - I found three different parsers, but none of them match this
>> description.
> 
> Heh, I was going by the documentation in the code:
> 
>     QEMU_OPT_SIZE,        /* size, accepts (K)ilo, (M)ega, (G)iga,
> (T)era postfix */
> 
> 
>> That is, qemu-option.c:parse_option_size() supports 'k'
>> and 'b', as well as omitting a suffix, but does not support 'm'.
> 
> TBH, I'd prefer to not document 'k' and 'b' and explicitly document that
> the suffix is optional and bytes is implied (which I thought was implied
> in my documentation, but I can see that it may not be).
> 
> I'd rather we support officially support one way of doing things and if
> we support more, do it under the mantra of being liberal in what we accept.

Okay, I can live with documenting less than we accept, but we definitely
need to mention that the suffix is optional, and that when omitted, the
unit is bytes (as originally written, I read it that the suffix was
mandatory, and that there was no way to request bytes).  I'm not sure
whether documenting an explicit 'b' for bytes helps or hurts, and I'm
not sure whether adding support for 'p' and 'e' as documented suffixes
makes sense.

> 
>> Then
>> there's cmd.c:cvtnum(), which is case-insensitive, and adds 'p' and 'e',
>> but omits 'b'.  Then there's the 'o' type in monitor.c that defers to
>> cutils.c:strtosz(), which defaults to bytes but is case-insensitive and
>> supports 'b' but not 'p'.  Why are we using three different parsers,
>> anyway?
> 
> Yes, I am aware of that, and yes, I'm going to fix it.  One bit at a
> time though.

Fair enough :)  It's just that I recently fixed a bug in libvirt where
it was using a human interface with no suffix and getting 'M' behavior,
where an explicit 'B' behavior fixed things to use bytes, and I was
quite put off by the inconsistencies and lack of documentation when I
finally discovered that a 'B' suffix did what I wanted.  I'm glad that
QMP defaults to 'B', not 'M'.  (Libvirt had its own fair share of
inconsistent scaling routines, where some interfaces default to 'k'
instead of bytes, and I recently consolidated libvirt to use a single
scaling routing for much the same reasons.)

-- 
Eric Blake   eblake@redhat.com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 620 bytes --]

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 7/9] qmp: expose a command to query capabilities of config parser
  2012-03-19 20:31       ` Eric Blake
@ 2012-03-19 20:41         ` Anthony Liguori
  0 siblings, 0 replies; 26+ messages in thread
From: Anthony Liguori @ 2012-03-19 20:41 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-devel, Anthony Liguori, Gerd Hoffman, Eduardo Habkost

On 03/19/2012 03:31 PM, Eric Blake wrote:
> On 03/19/2012 02:19 PM, Anthony Liguori wrote:
>>>> +# @size: an integer followed by either 'K', 'M', 'G', or 'T'.
>>>
>>> Not quite - I found three different parsers, but none of them match this
>>> description.
>>
>> Heh, I was going by the documentation in the code:
>>
>>      QEMU_OPT_SIZE,        /* size, accepts (K)ilo, (M)ega, (G)iga,
>> (T)era postfix */
>>
>>
>>> That is, qemu-option.c:parse_option_size() supports 'k'
>>> and 'b', as well as omitting a suffix, but does not support 'm'.
>>
>> TBH, I'd prefer to not document 'k' and 'b' and explicitly document that
>> the suffix is optional and bytes is implied (which I thought was implied
>> in my documentation, but I can see that it may not be).
>>
>> I'd rather we support officially support one way of doing things and if
>> we support more, do it under the mantra of being liberal in what we accept.
>
> Okay, I can live with documenting less than we accept, but we definitely
> need to mention that the suffix is optional, and that when omitted, the
> unit is bytes (as originally written, I read it that the suffix was
> mandatory, and that there was no way to request bytes).  I'm not sure
> whether documenting an explicit 'b' for bytes helps or hurts, and I'm
> not sure whether adding support for 'p' and 'e' as documented suffixes
> makes sense.

I'm not really concerned about 'p' and 'e' for now.  'T' still seems novel 
enough to me :-)

>>> Then
>>> there's cmd.c:cvtnum(), which is case-insensitive, and adds 'p' and 'e',
>>> but omits 'b'.  Then there's the 'o' type in monitor.c that defers to
>>> cutils.c:strtosz(), which defaults to bytes but is case-insensitive and
>>> supports 'b' but not 'p'.  Why are we using three different parsers,
>>> anyway?
>>
>> Yes, I am aware of that, and yes, I'm going to fix it.  One bit at a
>> time though.
>
> Fair enough :)  It's just that I recently fixed a bug in libvirt where
> it was using a human interface with no suffix and getting 'M' behavior,
> where an explicit 'B' behavior fixed things to use bytes, and I was
> quite put off by the inconsistencies and lack of documentation when I
> finally discovered that a 'B' suffix did what I wanted.

Yup, and hopefully qapi-schema.json is fixing the documentation problem here. 
For what it's worth, my aim is to refactor the QemuOpts definitions to be part 
of qapi-schema.json too such that they carry the same level of documentation 
(and self consistency).

This is the advantage of having a single centralized schema.  I think it has 
really helped make sure everything is consistently documented and specified. 
Having disjoint definitions and descriptions has led to a lot of inconsistency 
over time.

> I'm glad that
> QMP defaults to 'B', not 'M'.  (Libvirt had its own fair share of
> inconsistent scaling routines, where some interfaces default to 'k'
> instead of bytes, and I recently consolidated libvirt to use a single
> scaling routing for much the same reasons.)

You can thank Xen for the kb default :-)  That goes back to the libvir days.

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 8/9] vl: add -query-capabilities
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 8/9] vl: add -query-capabilities Anthony Liguori
@ 2012-03-20  7:49   ` Gerd Hoffmann
  2012-03-20 10:33     ` Daniel P. Berrange
  2012-03-20 19:39   ` Eduardo Habkost
  1 sibling, 1 reply; 26+ messages in thread
From: Gerd Hoffmann @ 2012-03-20  7:49 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Eric Blake, qemu-devel, Eduardo Habkost

On 03/19/12 16:09, Anthony Liguori wrote:
> This dumps the results of query-version, query-commands, and
> query-config-capabilities into a single JSON object on stdout.

I think libvirt needs a query-devices too.

cheers,
  Gerd

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes
  2012-03-19 16:31   ` Anthony Liguori
  2012-03-19 16:33     ` Paolo Bonzini
@ 2012-03-20  7:54     ` Gerd Hoffmann
  1 sibling, 0 replies; 26+ messages in thread
From: Gerd Hoffmann @ 2012-03-20  7:54 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: Paolo Bonzini, Anthony Liguori, Eric Blake, qemu-devel,
	Eduardo Habkost

  Hi,

>> I have a few patches here that convert almost every option that matters
>> into QemuOpts so that -writeconfig records it: -m, -bios, -localtime,
>> -S, -M, -smp, -numa, -nodefaults, -no-shutdown, -no-reboot.  The only
>> thing that is left basically is -display, where I chickened out.
> 
> This series is complimentary to this.  You can still promote options to
> QemuOpts.  The advantage of this series is that we provide a
> programmatic way for libvirt to discover when this happens.

It is still churn, especially considering that paolo has patches
already.  I'd suggest to go with your patches without [system] + paolo's
QemuOpts convert patches, then stick the remaining bits (if any) into
[system].

cheers,
  Gerd

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 8/9] vl: add -query-capabilities
  2012-03-20  7:49   ` Gerd Hoffmann
@ 2012-03-20 10:33     ` Daniel P. Berrange
  0 siblings, 0 replies; 26+ messages in thread
From: Daniel P. Berrange @ 2012-03-20 10:33 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Anthony Liguori, Eric Blake, qemu-devel, Eduardo Habkost

On Tue, Mar 20, 2012 at 08:49:11AM +0100, Gerd Hoffmann wrote:
> On 03/19/12 16:09, Anthony Liguori wrote:
> > This dumps the results of query-version, query-commands, and
> > query-config-capabilities into a single JSON object on stdout.
> 
> I think libvirt needs a query-devices too.

Currently we get capability like info in the following areas:

 * List of CPUs:

            $QEMU -cpu ?

 * List of machine types:

            $QEMU -M ?

 * List of devices & properties:

            $QEMU -device ? \
                  -device pci-assign,? \
                  -device virtio-blk-pci,? \
                  -device virtio-net-pci,? \
                  -device scsi-disk,?

As well as 80 odd other pieces of information[1] via -help, but lets not
get side tracked by those right now. What is proposed so far is a good
start, we can iteratively build on.

If we can get the above commands into JSON format too, that'd be nice
so that we can have one parser to rule them all.


Regards,
Daniel

[1] See the comments in the enum here for details of what we get from -help

    http://libvirt.org/git/?p=libvirt.git;a=blob;f=src/qemu/qemu_capabilities.h;hb=HEAD
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 8/9] vl: add -query-capabilities
  2012-03-19 15:09 ` [Qemu-devel] [PATCH 8/9] vl: add -query-capabilities Anthony Liguori
  2012-03-20  7:49   ` Gerd Hoffmann
@ 2012-03-20 19:39   ` Eduardo Habkost
  1 sibling, 0 replies; 26+ messages in thread
From: Eduardo Habkost @ 2012-03-20 19:39 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Eric Blake, qemu-devel, Gerd Hoffman

On Mon, Mar 19, 2012 at 10:09:22AM -0500, Anthony Liguori wrote:
> This dumps the results of query-version, query-commands, and
> query-config-capabilities into a single JSON object on stdout.
> 
> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>

What about a mode where no machine and devices are initialized at all,
but where config files are (optionally) loaded[1] and QMP commands can
be run?

It looks like too much work for 1.1, but I would like to see this
eventually. This would be the starting point for the day we would be
able to run an "empty" Qemu process, probe for features, set up
everything using QMP, and then start the actual virtual machine.

[1] I am asking for this specifically because I know libvirt will need
to probe for some things _after_ loading the config files. This is the
case for the cpudefs, but it may be true for other features and
capabilities too (probing for machine-type info would need it too, if we
moved them to config files some day).


That leads to another question: would it be acceptable to include data
that is depends on the loaded config files inside the
-query-config-capabilities output? (for example, the list of CPU models)
Or do you want to make -query-capabilities independent from the loaded
config data?

Let me try to explain the use case: some configuration options are
high-level and enable and disable a feature as a whole, but management
may want to know what are the low-level details that result from a
specific configuration combination. -writeconfig could help, but it
won't write that low-level data, it will write only the high-level
config it had read.

Example: you are going to ask Qemu to set up a specific CPU
cores/threads topology using "-smp", but then you want to know how
exactly the CPUID topology leafs will look like when you do that. You
_could_ calculate the resulting bits yourself based on your "-smp"
parameter (as the calculation is deterministic), but it would just
duplicate the CPUID generation logic that's already inside Qemu.

-- 
Eduardo

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes
  2012-03-19 16:09 ` [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Paolo Bonzini
  2012-03-19 16:31   ` Anthony Liguori
@ 2012-03-20 19:47   ` Eduardo Habkost
  1 sibling, 0 replies; 26+ messages in thread
From: Eduardo Habkost @ 2012-03-20 19:47 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Anthony Liguori, Eric Blake, Gerd Hoffman, qemu-devel

On Mon, Mar 19, 2012 at 05:09:57PM +0100, Paolo Bonzini wrote:
> Il 19/03/2012 16:09, Anthony Liguori ha scritto:
[...]
> > 
> > I would like to push this series into 1.1
> 
> I think it's too early.  However, we can definitely apply 1/2/7/8/9 now.

I like patch 3 a lot, too. It would open the door for further
refactoring of main(), which is badly needed IMO.

-- 
Eduardo

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2012-03-20 19:47 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-19 15:09 [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Anthony Liguori
2012-03-19 15:09 ` [Qemu-devel] [PATCH 1/9] qemu-config: fix -writeconfig when using qemu_opt_set_bool Anthony Liguori
2012-03-19 15:09 ` [Qemu-devel] [PATCH 2/9] qemu-config: friends don't let friends use sscanf Anthony Liguori
2012-03-19 15:09 ` [Qemu-devel] [PATCH 3/9] vl: refactor command line parsing to allow options to be set via config Anthony Liguori
2012-03-19 15:09 ` [Qemu-devel] [PATCH 4/9] vl: mark system configuration options in qemu-options.hx Anthony Liguori
2012-03-19 15:09 ` [Qemu-devel] [PATCH 5/9] vl: enable system configuration to be used Anthony Liguori
2012-03-19 15:09 ` [Qemu-devel] [PATCH 6/9] vl: parse all options via QemuOpts Anthony Liguori
2012-03-19 15:09 ` [Qemu-devel] [PATCH 7/9] qmp: expose a command to query capabilities of config parser Anthony Liguori
2012-03-19 20:10   ` Eric Blake
2012-03-19 20:19     ` Anthony Liguori
2012-03-19 20:31       ` Eric Blake
2012-03-19 20:41         ` Anthony Liguori
2012-03-19 15:09 ` [Qemu-devel] [PATCH 8/9] vl: add -query-capabilities Anthony Liguori
2012-03-20  7:49   ` Gerd Hoffmann
2012-03-20 10:33     ` Daniel P. Berrange
2012-03-20 19:39   ` Eduardo Habkost
2012-03-19 15:09 ` [Qemu-devel] [PATCH 9/9] Add a management tool writer's guide Anthony Liguori
2012-03-19 16:09 ` [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Paolo Bonzini
2012-03-19 16:31   ` Anthony Liguori
2012-03-19 16:33     ` Paolo Bonzini
2012-03-19 16:41       ` Anthony Liguori
2012-03-19 16:45         ` Paolo Bonzini
2012-03-19 16:53           ` Anthony Liguori
2012-03-19 17:03             ` Paolo Bonzini
2012-03-20  7:54     ` Gerd Hoffmann
2012-03-20 19:47   ` Eduardo Habkost

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).