From e8d21dedbb11e84476f54f7285e4758556f1395f Mon Sep 17 00:00:00 2001 Message-Id: From: Jason Baron Date: Fri, 12 Oct 2012 19:44:29 +0200 Subject: [PATCH 1/7] Introduce -machine command option. RH-Author: Jason Baron Message-id: <77448c75db32529cf80264e06ff59d6066e4b494.1350069767.git.jbaron@redhat.com> Patchwork-id: 43068 O-Subject: [RHEL 6.4 qemu-kvm PATCH v4 1/7] Introduce -machine command option. Bugzilla: 859447 RH-Acked-by: Markus Armbruster RH-Acked-by: Pavel Hrdina RH-Acked-by: Paolo Bonzini From: Anthony PERARD This option gives the ability to switch one "accelerator" like kvm, xen or the default one tcg. We can specify more than one accelerator by separate them by a colon. QEMU will try each one and use the first whose works. So, ./qemu -machine accel=xen:kvm:tcg which would try Xen support first, then KVM and finally TCG if none of the other works. By default, QEMU will use TCG. But we can specify another default in the global configuration file. Signed-off-by: Anthony PERARD Signed-off-by: Alexander Graf (cherry picked from commit 303d4e865b74402b49f52e975c396c952f063e58) Conflicts: qemu-options.hx qemu-config.c arch_init.h vl.c arch_init.c Removed xen (doc only) Changed default from tcg to kvm:tcg. Converted direct kvm_allowed variable access to kvm_enabled() wrapper Moved tcg_available() and kvm_available() definitions from arch_init.c -> vl.c, since RHEL6 doesn't have arch_init.c Signed-off-by: Jason Baron --- qemu-config.c | 14 ++++++ qemu-options.hx | 10 ++++ vl.c | 137 +++++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 138 insertions(+), 23 deletions(-) Signed-off-by: Michal Novotny --- qemu-config.c | 14 ++++++ qemu-options.hx | 10 +++++ vl.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 138 insertions(+), 23 deletions(-) diff --git a/qemu-config.c b/qemu-config.c index a7b2a58..ac5b4e6 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -419,6 +419,19 @@ QemuOptsList qemu_option_rom_opts = { }, }; +static QemuOptsList qemu_machine_opts = { + .name = "machine", + .head = QTAILQ_HEAD_INITIALIZER(qemu_machine_opts.head), + .desc = { + { + .name = "accel", + .type = QEMU_OPT_STRING, + .help = "accelerator list", + }, + { /* End of list */ } + }, +}; + QemuOptsList qemu_boot_opts = { .name = "boot-opts", .head = QTAILQ_HEAD_INITIALIZER(qemu_boot_opts.head), @@ -455,6 +468,7 @@ static QemuOptsList *vm_config_groups[] = { &qemu_cpudef_opts, &qemu_spice_opts, &qemu_option_rom_opts, + &qemu_machine_opts, &qemu_boot_opts, NULL, }; diff --git a/qemu-options.hx b/qemu-options.hx index 6c80eea..31dbfce 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1896,6 +1896,16 @@ Enable KVM full virtualization support. This option is only available if KVM support is enabled when compiling. ETEXI +DEF("machine", HAS_ARG, QEMU_OPTION_machine, \ + "-machine accel=accel1[:accel2] use an accelerator (kvm,tcg), default is kvm:tcg\n") +STEXI +@item -machine accel=@var{accels} +@findex -machine +This is use to enable an accelerator, in kvm,tcg. +By default, it use only kvm. If there a more than one accelerator +specified, the next one is used if the first don't work. +ETEXI + #ifdef CONFIG_XEN DEF("xen-domid", HAS_ARG, QEMU_OPTION_xen_domid, "-xen-domid id specify xen guest domain id\n") diff --git a/vl.c b/vl.c index fd662dd..bde1396 100644 --- a/vl.c +++ b/vl.c @@ -303,7 +303,8 @@ static void *boot_set_opaque; static NotifierList exit_notifiers = NOTIFIER_LIST_INITIALIZER(exit_notifiers); -int kvm_allowed = -1; +static int tcg_allowed = 1; +int kvm_allowed = 0; uint32_t xen_domid; enum xen_mode xen_mode = XEN_EMULATE; @@ -3560,14 +3561,14 @@ int qemu_cpu_self(void *env) void resume_all_vcpus(void) { - if (kvm_allowed) { + if (kvm_enabled()) { kvm_resume_all_threads(); } } void pause_all_vcpus(void) { - if (kvm_allowed) { + if (kvm_enabled()) { kvm_pause_all_threads(); } } @@ -4926,6 +4927,96 @@ static int debugcon_parse(const char *devname) return 0; } +static int kvm_available(void) +{ +#ifdef CONFIG_KVM + return 1; +#else + return 0; +#endif +} + +static int tcg_available(void) +{ + return 1; +} + +static int tcg_init(int smp_cpus) +{ + return 0; +} + +static struct { + const char *opt_name; + const char *name; + int (*available)(void); + int (*init)(int); + int *allowed; +} accel_list[] = { + { "tcg", "tcg", tcg_available, tcg_init, &tcg_allowed }, + { "kvm", "KVM", kvm_available, kvm_init, &kvm_allowed }, +}; + +static int configure_accelerator(void) +{ + const char *p = NULL; + char buf[10]; + int i, ret; + bool accel_initalised = 0; + bool init_failed = 0; + + QemuOptsList *list = qemu_find_opts("machine"); + if (!QTAILQ_EMPTY(&list->head)) { + p = qemu_opt_get(QTAILQ_FIRST(&list->head), "accel"); + } + + if (p == NULL) { + /* RHEL6 default "accelerator", kvm:tcg */ + p = "kvm:tcg"; + } + + while (!accel_initalised && *p != '\0') { + if (*p == ':') { + p++; + } + p = get_opt_name(buf, sizeof (buf), p, ':'); + for (i = 0; i < ARRAY_SIZE(accel_list); i++) { + if (strcmp(accel_list[i].opt_name, buf) == 0) { + ret = accel_list[i].init(smp_cpus); + if (ret < 0) { + init_failed = 1; + if (!accel_list[i].available()) { + printf("%s not supported for this target\n", + accel_list[i].name); + } else { + fprintf(stderr, "failed to initialize %s: %s\n", + accel_list[i].name, + strerror(-ret)); + } + } else { + accel_initalised = 1; + *(accel_list[i].allowed) = 1; + } + break; + } + } + if (i == ARRAY_SIZE(accel_list)) { + fprintf(stderr, "\"%s\" accelerator does not exist.\n", buf); + } + } + + if (!accel_initalised) { + fprintf(stderr, "No accelerator found!\n"); + exit(1); + } + + if (init_failed) { + fprintf(stderr, "Back to %s accelerator.\n", accel_list[i].name); + } + + return !accel_initalised; +} + void qemu_add_machine_init_done_notifier(Notifier *notify) { notifier_list_add(&machine_init_done_notifiers, notify); @@ -5630,11 +5721,15 @@ int main(int argc, char **argv, char **envp) #endif #ifdef CONFIG_KVM case QEMU_OPTION_enable_kvm: - kvm_allowed = 1; + olist = qemu_find_opts("machine"); + qemu_opts_reset(olist); + qemu_opts_parse(olist, "accel=kvm", 0); + break; + case QEMU_OPTION_no_kvm: + olist = qemu_find_opts("machine"); + qemu_opts_reset(olist); + qemu_opts_parse(olist, "accel=tcg", 0); break; - case QEMU_OPTION_no_kvm: - kvm_allowed = 0; - break; case QEMU_OPTION_no_kvm_irqchip: { kvm_irqchip = 0; kvm_pit = 0; @@ -5663,6 +5758,15 @@ int main(int argc, char **argv, char **envp) break; #endif #endif + case QEMU_OPTION_machine: + olist = qemu_find_opts("machine"); + qemu_opts_reset(olist); + opts = qemu_opts_parse(olist, optarg, 0); + if (!opts) { + fprintf(stderr, "parse error: %s\n", optarg); + exit(1); + } + break; case QEMU_OPTION_usb: usb_enabled = 1; break; @@ -6050,23 +6154,10 @@ int main(int argc, char **argv, char **envp) #endif if (fake_machine) { - kvm_allowed = 0; - } - if (kvm_allowed) { - int ret = kvm_init(smp_cpus); - if (ret < 0) { - if (kvm_allowed > 0) { -#ifndef CONFIG_KVM - printf("KVM not supported for this target\n"); -#else - fprintf(stderr, "failed to initialize KVM: %s\n", strerror(-ret)); -#endif - exit(1); - } - fprintf(stderr, "Could not initialize KVM, will disable KVM support\n"); - } - kvm_allowed = ret >= 0; + olist = qemu_find_opts("machine"); + qemu_opts_parse(olist, "accel=tcg", 0); } + configure_accelerator(); if (qemu_init_main_loop()) { fprintf(stderr, "qemu_init_main_loop failed\n"); -- 1.7.11.7