diff --git a/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES index 331326db4..7fa7d0a67 100644 --- a/docs/C_SOURCE_FILES +++ b/docs/C_SOURCE_FILES @@ -309,6 +309,9 @@ src/actions-6.c src/actions-support.c src/actions-variants.c src/alloc.c +src/appliance-cpu.c +src/appliance-kcmdline.c +src/appliance-uefi.c src/appliance.c src/available.c src/bindtests.c diff --git a/po/POTFILES b/po/POTFILES index 96a6435af..7a468c3b2 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -381,6 +381,9 @@ src/actions-6.c src/actions-support.c src/actions-variants.c src/alloc.c +src/appliance-cpu.c +src/appliance-kcmdline.c +src/appliance-uefi.c src/appliance.c src/available.c src/bindtests.c diff --git a/src/Makefile.am b/src/Makefile.am index 8150d9955..c315c5d8d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -82,6 +82,9 @@ libguestfs_la_SOURCES = \ actions-variants.c \ alloc.c \ appliance.c \ + appliance-cpu.c \ + appliance-kcmdline.c \ + appliance-uefi.c \ available.c \ bindtests.c \ canonical-name.c \ diff --git a/src/appliance-cpu.c b/src/appliance-cpu.c new file mode 100644 index 000000000..724120beb --- /dev/null +++ b/src/appliance-cpu.c @@ -0,0 +1,90 @@ +/* libguestfs + * Copyright (C) 2009-2016 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * The appliance choice of CPU model. + */ + +#include + +#include +#include + +#include "guestfs.h" +#include "guestfs-internal.h" + +/** + * Return the right CPU model to use as the qemu C<-cpu> parameter or + * its equivalent in libvirt. This returns: + * + * =over 4 + * + * =item C<"host"> + * + * The literal string C<"host"> means use C<-cpu host>. + * + * =item some string + * + * Some string such as C<"cortex-a57"> means use C<-cpu cortex-a57>. + * + * =item C + * + * C means no C<-cpu> option at all. Note returning C + * does not indicate an error. + * + * =back + * + * This is made unnecessarily hard and fragile because of two stupid + * choices in QEMU: + * + * =over 4 + * + * =item * + * + * The default for C is to emulate a + * C (WTF?). + * + * =item * + * + * We don't know for sure if KVM will work, but C<-cpu host> is broken + * with TCG, so we almost always pass a broken C<-cpu> flag if KVM is + * semi-broken in any way. + * + * =back + */ +const char * +guestfs_int_get_cpu_model (int kvm) +{ +#if defined(__aarch64__) + /* With -M virt, the default -cpu is cortex-a15. Stupid. */ + if (kvm) + return "host"; + else + return "cortex-a57"; +#else + /* On most architectures, it is faster to pass the CPU host model to + * the appliance, allowing maximum speed for things like checksums + * and encryption. Only do this with KVM. It is broken in subtle + * ways on TCG, and fairly pointless when you're emulating anyway. + */ + if (kvm) + return "host"; + else + return NULL; +#endif +} diff --git a/src/appliance-kcmdline.c b/src/appliance-kcmdline.c new file mode 100644 index 000000000..677166888 --- /dev/null +++ b/src/appliance-kcmdline.c @@ -0,0 +1,219 @@ +/* libguestfs + * Copyright (C) 2009-2016 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * The appliance kernel command line. + */ + +#include + +#include +#include +#include +#include + +#include "c-ctype.h" + +#include "guestfs.h" +#include "guestfs-internal.h" + +/** + * Check that the $TERM environment variable is reasonable before + * we pass it through to the appliance. + */ +static bool +valid_term (const char *term) +{ + size_t len = strlen (term); + + if (len == 0 || len > 16) + return false; + + while (len > 0) { + char c = *term++; + len--; + if (!c_isalnum (c) && c != '-' && c != '_') + return false; + } + + return true; +} + +#if defined(__powerpc64__) +#define SERIAL_CONSOLE "console=hvc0 console=ttyS0" +#elif defined(__arm__) || defined(__aarch64__) +#define SERIAL_CONSOLE "console=ttyAMA0" +#else +#define SERIAL_CONSOLE "console=ttyS0" +#endif + +#if defined(__aarch64__) +#define EARLYPRINTK "earlyprintk=pl011,0x9000000" +#endif + +/** + * Construct the Linux command line passed to the appliance. This is + * used by the C and C backends, and is simply + * located in this file because it's a convenient place for this + * common code. + * + * The C parameter must be the full device name of the + * appliance disk and must have already been adjusted to take into + * account virtio-blk or virtio-scsi; eg C. + * + * The C parameter can contain the following flags logically + * or'd together (or 0): + * + * =over 4 + * + * =item C + * + * If we are launching a qemu TCG guest (ie. KVM is known to be + * disabled or unavailable). If you don't know, don't pass this flag. + * + * =back + * + * Note that this function returns a newly allocated buffer which must + * be freed by the caller. + */ +char * +guestfs_int_appliance_command_line (guestfs_h *g, const char *appliance_dev, + int flags) +{ + CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (argv); + char *term = getenv ("TERM"); + bool tcg = flags & APPLIANCE_COMMAND_LINE_IS_TCG; + char *ret; + + /* We assemble the kernel command line by simply joining the final + * list of strings with spaces. This means (a) the strings are not + * quoted (it's not clear if the kernel can handle quoting in any + * case), and (b) we can append multiple parameters in a single + * argument, as we must do for the g->append parameter. + */ + + /* Force kernel to panic if daemon exits. */ + guestfs_int_add_string (g, &argv, "panic=1"); + +#ifdef __arm__ + guestfs_int_add_sprintf (g, &argv, "mem=%dM", g->memsize); +#endif + +#ifdef __i386__ + /* Workaround for RHBZ#857026. */ + guestfs_int_add_string (g, &argv, "noapic"); +#endif + + /* Serial console. */ + guestfs_int_add_string (g, &argv, SERIAL_CONSOLE); + +#ifdef EARLYPRINTK + /* Get messages from early boot. */ + guestfs_int_add_string (g, &argv, EARLYPRINTK); +#endif + +#ifdef __aarch64__ + guestfs_int_add_string (g, &argv, "ignore_loglevel"); + + /* This option turns off the EFI RTC device. QEMU VMs don't + * currently provide EFI, and if the device is compiled in it + * will try to call the EFI function GetTime unconditionally + * (causing a call to NULL). However this option requires a + * non-upstream patch. + */ + guestfs_int_add_string (g, &argv, "efi-rtc=noprobe"); +#endif + + /* RHBZ#1404287 */ + guestfs_int_add_string (g, &argv, "edd=off"); + + /* For slow systems (RHBZ#480319, RHBZ#1096579). */ + guestfs_int_add_string (g, &argv, "udevtimeout=6000"); + + /* Same as above, for newer udevd. */ + guestfs_int_add_string (g, &argv, "udev.event-timeout=6000"); + + /* Fix for RHBZ#502058. */ + guestfs_int_add_string (g, &argv, "no_timer_check"); + + if (tcg) { + const int lpj = guestfs_int_get_lpj (g); + if (lpj > 0) + guestfs_int_add_sprintf (g, &argv, "lpj=%d", lpj); + } + + /* Display timestamp before kernel messages. */ + guestfs_int_add_string (g, &argv, "printk.time=1"); + + /* Saves us about 5 MB of RAM. */ + guestfs_int_add_string (g, &argv, "cgroup_disable=memory"); + + /* Disable USB, only saves about 1ms. */ + guestfs_int_add_string (g, &argv, "usbcore.nousb"); + + /* Disable crypto tests, saves 28ms. */ + guestfs_int_add_string (g, &argv, "cryptomgr.notests"); + + /* Don't synch TSCs when using SMP. Saves 21ms for each secondary vCPU. */ + guestfs_int_add_string (g, &argv, "tsc=reliable"); + + /* Don't scan all 8250 UARTS. */ + guestfs_int_add_string (g, &argv, "8250.nr_uarts=1"); + + /* Tell supermin about the appliance device. */ + if (appliance_dev) + guestfs_int_add_sprintf (g, &argv, "root=%s", appliance_dev); + + /* SELinux - deprecated setting, never worked and should not be enabled. */ + if (g->selinux) + guestfs_int_add_string (g, &argv, "selinux=1 enforcing=0"); + else + guestfs_int_add_string (g, &argv, "selinux=0"); + + /* Quiet/verbose. */ + if (g->verbose) + guestfs_int_add_string (g, &argv, "guestfs_verbose=1"); + else + guestfs_int_add_string (g, &argv, "quiet"); + + /* Network. */ + if (g->enable_network) + guestfs_int_add_string (g, &argv, "guestfs_network=1"); + + /* TERM environment variable. */ + if (term && valid_term (term)) + guestfs_int_add_sprintf (g, &argv, "TERM=%s", term); + else + guestfs_int_add_string (g, &argv, "TERM=linux"); + + /* Handle identifier. */ + if (STRNEQ (g->identifier, "")) + guestfs_int_add_sprintf (g, &argv, "guestfs_identifier=%s", g->identifier); + + /* Append extra arguments. */ + if (g->append) + guestfs_int_add_string (g, &argv, g->append); + + guestfs_int_end_stringsbuf (g, &argv); + + /* Caller frees. */ + ret = guestfs_int_join_strings (" ", argv.argv); + if (ret == NULL) + g->abort_cb (); + return ret; +} diff --git a/src/appliance-uefi.c b/src/appliance-uefi.c new file mode 100644 index 000000000..c1a0284a0 --- /dev/null +++ b/src/appliance-uefi.c @@ -0,0 +1,105 @@ +/* libguestfs + * Copyright (C) 2010-2016 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * Find the UEFI firmware needed to boot the appliance. + * + * See also F (autogenerated file) containing the + * firmware file locations. + */ + +#include + +#include +#include +#include + +#include "guestfs.h" +#include "guestfs-internal.h" + +/** + * Return the location of firmware needed to boot the appliance. This + * is aarch64 only currently, since that's the only architecture where + * UEFI is mandatory (and that only for RHEL). + * + * C<*code> is initialized with the path to the read-only UEFI code + * file. C<*vars> is initialized with the path to a copy of the UEFI + * vars file (which is cleaned up automatically on exit). + * + * If C<*code> == C<*vars> == C then no UEFI firmware is + * available. + * + * C<*code> and C<*vars> should be freed by the caller. + * + * If the function returns C<-1> then there was a real error which + * should cause appliance building to fail (no UEFI firmware is not an + * error). + * + * See also F:find_uefi_firmware + */ +int +guestfs_int_get_uefi (guestfs_h *g, char **code, char **vars, int *flags) +{ +#ifdef __aarch64__ + size_t i; + + for (i = 0; guestfs_int_uefi_aarch64_firmware[i].code != NULL; ++i) { + const char *codefile = guestfs_int_uefi_aarch64_firmware[i].code; + const char *code_debug_file = + guestfs_int_uefi_aarch64_firmware[i].code_debug; + const char *varsfile = guestfs_int_uefi_aarch64_firmware[i].vars; + + if (access (codefile, R_OK) == 0 && access (varsfile, R_OK) == 0) { + CLEANUP_CMD_CLOSE struct command *copycmd = guestfs_int_new_command (g); + char *varst; + int r; + + /* Make a copy of NVRAM variables file. You can't just map it + * into the address space read-only as that triggers a different + * path inside UEFI. + */ + varst = safe_asprintf (g, "%s/vars.fd.%d", g->tmpdir, ++g->unique); + guestfs_int_cmd_add_arg (copycmd, "cp"); + guestfs_int_cmd_add_arg (copycmd, varsfile); + guestfs_int_cmd_add_arg (copycmd, varst); + r = guestfs_int_cmd_run (copycmd); + if (r == -1 || !WIFEXITED (r) || WEXITSTATUS (r) != 0) { + free (varst); + return -1; + } + + /* If debugging is enabled and we can find the code file with + * debugging enabled, use that instead. + */ + if (g->verbose && access (code_debug_file, R_OK) == 0) + codefile = code_debug_file; + + /* Caller frees. */ + *code = safe_strdup (g, codefile); + *vars = varst; + *flags = guestfs_int_uefi_aarch64_firmware[i].flags; + return 0; + } + } +#endif + + /* Not found. */ + *code = *vars = NULL; + *flags = 0; + return 0; +} diff --git a/src/appliance.c b/src/appliance.c index 94f42aca0..9b603d094 100644 --- a/src/appliance.c +++ b/src/appliance.c @@ -404,75 +404,3 @@ dir_contains_files (guestfs_h *g, const char *dir, ...) va_end (args); return 1; } - -/** - * Return the location of firmware needed to boot the appliance. This - * is aarch64 only currently, since that's the only architecture where - * UEFI is mandatory (and that only for RHEL). - * - * C<*code> is initialized with the path to the read-only UEFI code - * file. C<*vars> is initialized with the path to a copy of the UEFI - * vars file (which is cleaned up automatically on exit). - * - * If C<*code> == C<*vars> == C then no UEFI firmware is - * available. - * - * C<*code> and C<*vars> should be freed by the caller. - * - * If the function returns C<-1> then there was a real error which - * should cause appliance building to fail (no UEFI firmware is not an - * error). - * - * See also F:find_uefi_firmware - */ -int -guestfs_int_get_uefi (guestfs_h *g, char **code, char **vars, int *flags) -{ -#ifdef __aarch64__ - size_t i; - - for (i = 0; guestfs_int_uefi_aarch64_firmware[i].code != NULL; ++i) { - const char *codefile = guestfs_int_uefi_aarch64_firmware[i].code; - const char *code_debug_file = - guestfs_int_uefi_aarch64_firmware[i].code_debug; - const char *varsfile = guestfs_int_uefi_aarch64_firmware[i].vars; - - if (access (codefile, R_OK) == 0 && access (varsfile, R_OK) == 0) { - CLEANUP_CMD_CLOSE struct command *copycmd = guestfs_int_new_command (g); - char *varst; - int r; - - /* Make a copy of NVRAM variables file. You can't just map it - * into the address space read-only as that triggers a different - * path inside UEFI. - */ - varst = safe_asprintf (g, "%s/vars.fd.%d", g->tmpdir, ++g->unique); - guestfs_int_cmd_add_arg (copycmd, "cp"); - guestfs_int_cmd_add_arg (copycmd, varsfile); - guestfs_int_cmd_add_arg (copycmd, varst); - r = guestfs_int_cmd_run (copycmd); - if (r == -1 || !WIFEXITED (r) || WEXITSTATUS (r) != 0) { - free (varst); - return -1; - } - - /* If debugging is enabled and we can find the code file with - * debugging enabled, use that instead. - */ - if (g->verbose && access (code_debug_file, R_OK) == 0) - codefile = code_debug_file; - - /* Caller frees. */ - *code = safe_strdup (g, codefile); - *vars = varst; - *flags = guestfs_int_uefi_aarch64_firmware[i].flags; - return 0; - } - } -#endif - - /* Not found. */ - *code = *vars = NULL; - *flags = 0; - return 0; -} diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h index 51d3512e1..175015b21 100644 --- a/src/guestfs-internal.h +++ b/src/guestfs-internal.h @@ -831,14 +831,20 @@ extern const char *guestfs_int_drive_protocol_to_string (enum drive_protocol pro /* appliance.c */ extern int guestfs_int_build_appliance (guestfs_h *g, char **kernel, char **initrd, char **appliance); + +/* appliance-cpu.c */ +const char *guestfs_int_get_cpu_model (int kvm); + +/* appliance-kcmdline.c */ +extern char *guestfs_int_appliance_command_line (guestfs_h *g, const char *appliance_dev, int flags); +#define APPLIANCE_COMMAND_LINE_IS_TCG 1 + +/* appliance-uefi.c */ extern int guestfs_int_get_uefi (guestfs_h *g, char **code, char **vars, int *flags); /* launch.c */ extern int64_t guestfs_int_timeval_diff (const struct timeval *x, const struct timeval *y); extern void guestfs_int_launch_send_progress (guestfs_h *g, int perdozen); -extern char *guestfs_int_appliance_command_line (guestfs_h *g, const char *appliance_dev, int flags); -#define APPLIANCE_COMMAND_LINE_IS_TCG 1 -const char *guestfs_int_get_cpu_model (int kvm); int guestfs_int_create_socketname (guestfs_h *g, const char *filename, char (*sockname)[UNIX_PATH_MAX]); extern void guestfs_int_register_backend (const char *name, const struct backend_ops *); extern int guestfs_int_set_backend (guestfs_h *g, const char *method); diff --git a/src/launch.c b/src/launch.c index 3f7740afc..eaa14ccb6 100644 --- a/src/launch.c +++ b/src/launch.c @@ -29,7 +29,6 @@ #include #include -#include #include #include #include @@ -287,253 +286,6 @@ guestfs_impl_config (guestfs_h *g, return 0; } -/** - * Check that the $TERM environment variable is reasonable before - * we pass it through to the appliance. - */ -static bool -valid_term (const char *term) -{ - size_t len = strlen (term); - - if (len == 0 || len > 16) - return false; - - while (len > 0) { - char c = *term++; - len--; - if (!c_isalnum (c) && c != '-' && c != '_') - return false; - } - - return true; -} - -#if defined(__powerpc64__) -#define SERIAL_CONSOLE "console=hvc0 console=ttyS0" -#elif defined(__arm__) || defined(__aarch64__) -#define SERIAL_CONSOLE "console=ttyAMA0" -#else -#define SERIAL_CONSOLE "console=ttyS0" -#endif - -#if defined(__aarch64__) -#define EARLYPRINTK "earlyprintk=pl011,0x9000000" -#endif - -/** - * Construct the Linux command line passed to the appliance. This is - * used by the C and C backends, and is simply - * located in this file because it's a convenient place for this - * common code. - * - * The C parameter must be the full device name of the - * appliance disk and must have already been adjusted to take into - * account virtio-blk or virtio-scsi; eg C. - * - * The C parameter can contain the following flags logically - * or'd together (or 0): - * - * =over 4 - * - * =item C - * - * If we are launching a qemu TCG guest (ie. KVM is known to be - * disabled or unavailable). If you don't know, don't pass this flag. - * - * =back - * - * Note that this function returns a newly allocated buffer which must - * be freed by the caller. - */ -char * -guestfs_int_appliance_command_line (guestfs_h *g, const char *appliance_dev, - int flags) -{ - CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (argv); - char *term = getenv ("TERM"); - bool tcg = flags & APPLIANCE_COMMAND_LINE_IS_TCG; - char *ret; - - /* We assemble the kernel command line by simply joining the final - * list of strings with spaces. This means (a) the strings are not - * quoted (it's not clear if the kernel can handle quoting in any - * case), and (b) we can append multiple parameters in a single - * argument, as we must do for the g->append parameter. - */ - - /* Force kernel to panic if daemon exits. */ - guestfs_int_add_string (g, &argv, "panic=1"); - -#ifdef __arm__ - guestfs_int_add_sprintf (g, &argv, "mem=%dM", g->memsize); -#endif - -#ifdef __i386__ - /* Workaround for RHBZ#857026. */ - guestfs_int_add_string (g, &argv, "noapic"); -#endif - - /* Serial console. */ - guestfs_int_add_string (g, &argv, SERIAL_CONSOLE); - -#ifdef EARLYPRINTK - /* Get messages from early boot. */ - guestfs_int_add_string (g, &argv, EARLYPRINTK); -#endif - -#ifdef __aarch64__ - guestfs_int_add_string (g, &argv, "ignore_loglevel"); - - /* This option turns off the EFI RTC device. QEMU VMs don't - * currently provide EFI, and if the device is compiled in it - * will try to call the EFI function GetTime unconditionally - * (causing a call to NULL). However this option requires a - * non-upstream patch. - */ - guestfs_int_add_string (g, &argv, "efi-rtc=noprobe"); -#endif - - /* RHBZ#1404287 */ - guestfs_int_add_string (g, &argv, "edd=off"); - - /* For slow systems (RHBZ#480319, RHBZ#1096579). */ - guestfs_int_add_string (g, &argv, "udevtimeout=6000"); - - /* Same as above, for newer udevd. */ - guestfs_int_add_string (g, &argv, "udev.event-timeout=6000"); - - /* Fix for RHBZ#502058. */ - guestfs_int_add_string (g, &argv, "no_timer_check"); - - if (tcg) { - const int lpj = guestfs_int_get_lpj (g); - if (lpj > 0) - guestfs_int_add_sprintf (g, &argv, "lpj=%d", lpj); - } - - /* Display timestamp before kernel messages. */ - guestfs_int_add_string (g, &argv, "printk.time=1"); - - /* Saves us about 5 MB of RAM. */ - guestfs_int_add_string (g, &argv, "cgroup_disable=memory"); - - /* Disable USB, only saves about 1ms. */ - guestfs_int_add_string (g, &argv, "usbcore.nousb"); - - /* Disable crypto tests, saves 28ms. */ - guestfs_int_add_string (g, &argv, "cryptomgr.notests"); - - /* Don't synch TSCs when using SMP. Saves 21ms for each secondary vCPU. */ - guestfs_int_add_string (g, &argv, "tsc=reliable"); - - /* Don't scan all 8250 UARTS. */ - guestfs_int_add_string (g, &argv, "8250.nr_uarts=1"); - - /* Tell supermin about the appliance device. */ - if (appliance_dev) - guestfs_int_add_sprintf (g, &argv, "root=%s", appliance_dev); - - /* SELinux - deprecated setting, never worked and should not be enabled. */ - if (g->selinux) - guestfs_int_add_string (g, &argv, "selinux=1 enforcing=0"); - else - guestfs_int_add_string (g, &argv, "selinux=0"); - - /* Quiet/verbose. */ - if (g->verbose) - guestfs_int_add_string (g, &argv, "guestfs_verbose=1"); - else - guestfs_int_add_string (g, &argv, "quiet"); - - /* Network. */ - if (g->enable_network) - guestfs_int_add_string (g, &argv, "guestfs_network=1"); - - /* TERM environment variable. */ - if (term && valid_term (term)) - guestfs_int_add_sprintf (g, &argv, "TERM=%s", term); - else - guestfs_int_add_string (g, &argv, "TERM=linux"); - - /* Handle identifier. */ - if (STRNEQ (g->identifier, "")) - guestfs_int_add_sprintf (g, &argv, "guestfs_identifier=%s", g->identifier); - - /* Append extra arguments. */ - if (g->append) - guestfs_int_add_string (g, &argv, g->append); - - guestfs_int_end_stringsbuf (g, &argv); - - /* Caller frees. */ - ret = guestfs_int_join_strings (" ", argv.argv); - if (ret == NULL) - g->abort_cb (); - return ret; -} - -/** - * Return the right CPU model to use as the qemu C<-cpu> parameter or - * its equivalent in libvirt. This returns: - * - * =over 4 - * - * =item C<"host"> - * - * The literal string C<"host"> means use C<-cpu host>. - * - * =item some string - * - * Some string such as C<"cortex-a57"> means use C<-cpu cortex-a57>. - * - * =item C - * - * C means no C<-cpu> option at all. Note returning C - * does not indicate an error. - * - * =back - * - * This is made unnecessarily hard and fragile because of two stupid - * choices in QEMU: - * - * =over 4 - * - * =item * - * - * The default for C is to emulate a - * C (WTF?). - * - * =item * - * - * We don't know for sure if KVM will work, but C<-cpu host> is broken - * with TCG, so we almost always pass a broken C<-cpu> flag if KVM is - * semi-broken in any way. - * - * =back - */ -const char * -guestfs_int_get_cpu_model (int kvm) -{ -#if defined(__aarch64__) - /* With -M virt, the default -cpu is cortex-a15. Stupid. */ - if (kvm) - return "host"; - else - return "cortex-a57"; -#else - /* On most architectures, it is faster to pass the CPU host model to - * the appliance, allowing maximum speed for things like checksums - * and encryption. Only do this with KVM. It is broken in subtle - * ways on TCG, and fairly pointless when you're emulating anyway. - */ - if (kvm) - return "host"; - else - return NULL; -#endif -} - /** * Create the path for a socket with the selected filename in the * tmpdir.