Patchwork [07/22] machine: introduce -machine option

login
register
mail settings
Submitter Anthony Liguori
Date June 7, 2010, 11:51 p.m.
Message ID <1275954730-8196-8-git-send-email-aliguori@us.ibm.com>
Download mbox | patch
Permalink /patch/54905/
State New
Headers show

Comments

Anthony Liguori - June 7, 2010, 11:51 p.m.
This introduces a new -machine option that can be used to tweak machine specific
parameters.  One unusal feature of -machine is that there is only one machine
instance and all uses of -machine are combined together.  The last operation
to a parameter is given priority.

This let's a configuration file specify a set of default machine properties that
can then be overridden by a user.

This patch also makes -M a syntactic helper for -machine.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>

Patch

diff --git a/hw/boards.h b/hw/boards.h
index 728908b..0092557 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -35,6 +35,10 @@  extern QEMUMachine *current_machine;
 
 #define COMMON_MACHINE_OPTS() 		\
     {                                   \
+        .name = "driver",               \
+        .type = QEMU_OPT_STRING,        \
+    },                                  \
+    {                                   \
         .name = "ram_size",             \
         .type = QEMU_OPT_SIZE,          \
     },{                                 \
diff --git a/qemu-config.c b/qemu-config.c
index 3679a9f..a0cb34f 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -338,6 +338,7 @@  QemuOptsList qemu_cpudef_opts = {
 
 QemuOptsList qemu_machine_opts = {
     .name = "machine",
+    .implied_opt_name = "driver",
     .head = QTAILQ_HEAD_INITIALIZER(qemu_machine_opts.head),
     .desc = {
         { /* end of list */ }
diff --git a/qemu-option.c b/qemu-option.c
index b990cf5..61a2613 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -794,6 +794,27 @@  int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname
     return 0;
 }
 
+QemuOpts *qemu_opts_parsev(QemuOptsList *list, const char *params,
+                           va_list ap)
+{
+    char buffer[4096];
+    vsnprintf(buffer, sizeof(buffer), params, ap);
+    return qemu_opts_parse(list, buffer, 0);
+}
+
+QemuOpts *qemu_opts_parsef(QemuOptsList *list, const char *params,
+                           ...)
+{
+    va_list ap;
+    QemuOpts *opts;
+
+    va_start(ap, params);
+    opts = qemu_opts_parsev(list, params, ap);
+    va_end(ap);
+
+    return opts;
+}
+
 QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
                           int permit_abbrev)
 {
diff --git a/qemu-option.h b/qemu-option.h
index 4a6717c..85ab58e 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -129,6 +129,8 @@  void qemu_opts_del(QemuOpts *opts);
 int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc);
 int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname);
 QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, int permit_abbrev);
+QemuOpts *qemu_opts_parsev(QemuOptsList *list, const char *params, va_list ap);
+QemuOpts *qemu_opts_parsef(QemuOptsList *list, const char *params, ...);
 QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict);
 QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict);
 
diff --git a/qemu-options.hx b/qemu-options.hx
index a6928b7..32fd32a 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -35,6 +35,14 @@  STEXI
 Select the emulated @var{machine} (@code{-M ?} for list)
 ETEXI
 
+DEF("machine", HAS_ARG, QEMU_OPTION_machine,
+    "-machine machine[,opt=val...] select emulated machine\n", QEMU_ARCH_ALL)
+STEXI
+@item -machine @var{machine}[,@var{opt}=@var{val}...]
+@findex -machine
+Select the emulated @var{machine}
+ETEXI
+
 DEF("cpu", HAS_ARG, QEMU_OPTION_cpu,
     "-cpu cpu        select CPU (-cpu ? for list)\n", QEMU_ARCH_ALL)
 STEXI
diff --git a/vl.c b/vl.c
index 4fc4c20..001adbe 100644
--- a/vl.c
+++ b/vl.c
@@ -2555,6 +2555,24 @@  static QemuOptDesc common_machine_opts[] = {
     { /* end of list */ },
 };
 
+static int machine_combine_opt(const char *name, const char *value, void *opaque)
+{
+    QemuOpts *base_opts = opaque;
+    qemu_opt_set(base_opts, name, value);
+    return 0;
+}
+
+static int machine_combine_opts(QemuOpts *opts, void *opaque)
+{
+    QemuOpts *base_opts = opaque;
+
+    if (base_opts == opts) {
+        return 0;
+    }
+
+    return qemu_opt_foreach(opts, machine_combine_opt, base_opts, 0);
+}
+
 int main(int argc, char **argv, char **envp)
 {
     const char *gdbstub_dev = NULL;
@@ -2571,7 +2589,7 @@  int main(int argc, char **argv, char **envp)
     int optind;
     const char *optarg;
     const char *loadvm = NULL;
-    QEMUMachine *machine;
+    QEMUMachine *machine = NULL;
     const char *cpu_model;
 #ifndef _WIN32
     int fds[2];
@@ -2587,6 +2605,7 @@  int main(int argc, char **argv, char **envp)
 #endif
     int show_vnc_port = 0;
     int defconfig = 1;
+    QemuOpts *machine_opts = NULL;
 
     error_set_progname(argv[0]);
 
@@ -2626,7 +2645,6 @@  int main(int argc, char **argv, char **envp)
 #endif
 
     module_call_init(MODULE_INIT_MACHINE);
-    machine = find_default_machine();
     cpu_model = NULL;
     initrd_filename = NULL;
     ram_size = 0;
@@ -2698,8 +2716,7 @@  int main(int argc, char **argv, char **envp)
             }
             switch(popt->index) {
             case QEMU_OPTION_M:
-                machine = find_machine(optarg);
-                if (!machine) {
+                if (strcmp(optarg, "?") == 0) {
                     QEMUMachine *m;
                     printf("Supported machines are:\n");
                     for(m = first_machine; m != NULL; m = m->next) {
@@ -2710,7 +2727,13 @@  int main(int argc, char **argv, char **envp)
                                m->name, m->desc,
                                m->is_default ? " (default)" : "");
                     }
-                    exit(*optarg != '?');
+                    exit(0);
+                }
+                qemu_opts_parsef(&qemu_machine_opts, "driver=%s", optarg);
+                break;
+            case QEMU_OPTION_machine:
+                if (!qemu_opts_parse(&qemu_machine_opts, optarg, 1)) {
+                    exit(1);
                 }
                 break;
             case QEMU_OPTION_cpu:
@@ -3431,6 +3454,26 @@  int main(int argc, char **argv, char **envp)
         data_dir = CONFIG_QEMU_SHAREDIR;
     }
 
+    /* Combine all -machine options into one option group */
+    machine_opts = qemu_opts_create(&qemu_machine_opts, NULL, 0);
+    qemu_opts_foreach(&qemu_machine_opts, machine_combine_opts, machine_opts, 0);
+
+    if (!qemu_opt_get(machine_opts, "driver")) {
+        machine = find_default_machine();
+    } else {
+        machine = find_machine(qemu_opt_get(machine_opts, "driver"));
+    }
+
+    if (machine->opts_desc) {
+        if (qemu_opts_validate(machine_opts, machine->opts_desc) < 0) {
+            exit(1);
+        }
+    } else {
+        if (qemu_opts_validate(machine_opts, common_machine_opts) < 0) {
+            exit(1);
+        }
+    }
+    
     /*
      * Default to max_cpus = smp_cpus, in case the user doesn't
      * specify a max_cpus value.
@@ -3723,47 +3766,36 @@  int main(int argc, char **argv, char **envp)
     }
     qemu_add_globals();
 
-    opts = qemu_opts_create(&qemu_machine_opts, NULL, 0);
     if (kernel_filename) {
-        qemu_opt_set(opts, "kernel", kernel_filename);
+        qemu_opt_set(machine_opts, "kernel", kernel_filename);
         if (kernel_cmdline) {
-            qemu_opt_set(opts, "cmdline", kernel_cmdline);
+            qemu_opt_set(machine_opts, "cmdline", kernel_cmdline);
         }
         if (initrd_filename) {
-            qemu_opt_set(opts, "initrd", initrd_filename);
+            qemu_opt_set(machine_opts, "initrd", initrd_filename);
         }
     }
 
-    qemu_opt_set(opts, "boot_device", boot_devices);
+    qemu_opt_set(machine_opts, "boot_device", boot_devices);
 
     if (cpu_model) {
-        qemu_opt_set(opts, "cpu", cpu_model);
+        qemu_opt_set(machine_opts, "cpu", cpu_model);
     }
 
     if (ram_size) {
         char buffer[64];
         snprintf(buffer, sizeof(buffer),
                  "%" PRId64, ram_size);
-        qemu_opt_set(opts, "ram_size", buffer);
+        qemu_opt_set(machine_opts, "ram_size", buffer);
     }
 
     if (acpi_enabled == 0) {
-        qemu_opt_set(opts, "acpi", "off");
+        qemu_opt_set(machine_opts, "acpi", "off");
     }
 
-    if (machine->opts_desc) {
-        if (qemu_opts_validate(opts, machine->opts_desc) < 0) {
-            exit(1);
-        }
-    } else {
-        if (qemu_opts_validate(opts, common_machine_opts) < 0) {
-            exit(1);
-        }
-    }
-    
-    machine->init(opts);
+    machine->init(machine_opts);
 
-    qemu_opts_del(opts);
+    qemu_opts_del(machine_opts);
 
     cpu_synchronize_all_post_init();