vmspawn: Add --console-transport= option to select serial vs virtio-serial
Add a --console-transport= option that selects between virtio-serial (the default, appearing as /dev/hvc0) and a regular serial port (appearing as /dev/ttyS0 or /dev/ttyAMA0 depending on architecture). This is primarily useful for testing purposes, for example to test sd-stub's automatic console= kernel command line parameter handling. It allows verifying that the guest OS correctly handles serial console configurations without virtio. When serial transport is selected, -serial chardev:console is used on the QEMU command line to connect the chardev to the platform's default serial device. This cannot be done via the QEMU config file as on some platforms (e.g. ARM) the serial device is a sysbus device that can only be connected via serial_hd() which is populated by -serial.
This commit is contained in:
committed by
Daan De Meyer
parent
eb584f164f
commit
a586648800
@@ -712,6 +712,20 @@
|
||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--console-transport=<replaceable>TRANSPORT</replaceable></option></term>
|
||||
|
||||
<listitem><para>Configures the transport to use for the VM console. Takes one of
|
||||
<literal>virtio</literal> or <literal>serial</literal>. Defaults to <literal>virtio</literal>.
|
||||
<literal>virtio</literal> uses a virtio-serial device, which appears as
|
||||
<filename>/dev/hvc0</filename> in the VM. <literal>serial</literal> uses a regular serial port,
|
||||
which appears as <filename>/dev/ttyS0</filename> (or <filename>/dev/ttyAMA0</filename> on ARM) in the VM. This option only has an effect in
|
||||
<option>--console=interactive</option>, <option>--console=read-only</option>, and
|
||||
<option>--console=native</option> modes.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v262"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--background=<replaceable>COLOR</replaceable></option></term>
|
||||
|
||||
|
||||
@@ -37,3 +37,10 @@ static const char *const console_mode_table[_CONSOLE_MODE_MAX] = {
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(console_mode, ConsoleMode);
|
||||
|
||||
static const char *const console_transport_table[_CONSOLE_TRANSPORT_MAX] = {
|
||||
[CONSOLE_TRANSPORT_VIRTIO] = "virtio",
|
||||
[CONSOLE_TRANSPORT_SERIAL] = "serial",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(console_transport, ConsoleTransport);
|
||||
|
||||
@@ -42,6 +42,13 @@ typedef enum ConsoleMode {
|
||||
_CONSOLE_MODE_INVALID = -EINVAL,
|
||||
} ConsoleMode;
|
||||
|
||||
typedef enum ConsoleTransport {
|
||||
CONSOLE_TRANSPORT_VIRTIO, /* virtio-serial (hvc0) */
|
||||
CONSOLE_TRANSPORT_SERIAL, /* regular serial port (ttyS0/ttyAMA0) */
|
||||
_CONSOLE_TRANSPORT_MAX,
|
||||
_CONSOLE_TRANSPORT_INVALID = -EINVAL,
|
||||
} ConsoleTransport;
|
||||
|
||||
typedef enum SettingsMask {
|
||||
SETTING_START_MODE = UINT64_C(1) << 0,
|
||||
SETTING_MACHINE_ID = UINT64_C(1) << 6,
|
||||
@@ -53,5 +60,6 @@ typedef enum SettingsMask {
|
||||
} SettingsMask;
|
||||
|
||||
DECLARE_STRING_TABLE_LOOKUP(console_mode, ConsoleMode);
|
||||
DECLARE_STRING_TABLE_LOOKUP(console_transport, ConsoleTransport);
|
||||
DECLARE_STRING_TABLE_LOOKUP(disk_type, DiskType);
|
||||
DECLARE_STRING_TABLE_LOOKUP(image_format, ImageFormat);
|
||||
|
||||
@@ -49,6 +49,12 @@
|
||||
# define QEMU_MACHINE_TYPE "none"
|
||||
#endif
|
||||
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
# define QEMU_SERIAL_CONSOLE_NAME "ttyAMA0"
|
||||
#else
|
||||
# define QEMU_SERIAL_CONSOLE_NAME "ttyS0"
|
||||
#endif
|
||||
|
||||
typedef struct OvmfConfig {
|
||||
char *path;
|
||||
char *format;
|
||||
|
||||
+38
-12
@@ -137,6 +137,7 @@ static int arg_tpm = -1;
|
||||
static char *arg_linux = NULL;
|
||||
static char **arg_initrds = NULL;
|
||||
static ConsoleMode arg_console_mode = CONSOLE_INTERACTIVE;
|
||||
static ConsoleTransport arg_console_transport = CONSOLE_TRANSPORT_VIRTIO;
|
||||
static NetworkStack arg_network_stack = NETWORK_STACK_NONE;
|
||||
static MachineCredentialContext arg_credentials = {};
|
||||
static uid_t arg_uid_shift = UID_INVALID, arg_uid_range = 0x10000U;
|
||||
@@ -291,6 +292,8 @@ static int help(void) {
|
||||
"\n%3$sInput/Output:%4$s\n"
|
||||
" --console=MODE Console mode (interactive, native, gui, read-only\n"
|
||||
" or headless)\n"
|
||||
" --console-transport=TRANSPORT\n"
|
||||
" Console transport (virtio or serial)\n"
|
||||
" --background=COLOR Set ANSI color for background\n"
|
||||
"\n%3$sCredentials:%4$s\n"
|
||||
" --set-credential=ID:VALUE\n"
|
||||
@@ -375,6 +378,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_USER,
|
||||
ARG_IMAGE_FORMAT,
|
||||
ARG_IMAGE_DISK_TYPE,
|
||||
ARG_CONSOLE_TRANSPORT,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@@ -402,6 +406,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "linux", required_argument, NULL, ARG_LINUX },
|
||||
{ "initrd", required_argument, NULL, ARG_INITRD },
|
||||
{ "console", required_argument, NULL, ARG_CONSOLE },
|
||||
{ "console-transport", required_argument, NULL, ARG_CONSOLE_TRANSPORT },
|
||||
{ "qemu-gui", no_argument, NULL, ARG_QEMU_GUI }, /* compat option */
|
||||
{ "network-tap", no_argument, NULL, 'n' },
|
||||
{ "network-user-mode", no_argument, NULL, ARG_NETWORK_USER_MODE },
|
||||
@@ -578,6 +583,13 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
break;
|
||||
|
||||
case ARG_CONSOLE_TRANSPORT:
|
||||
arg_console_transport = console_transport_from_string(optarg);
|
||||
if (arg_console_transport < 0)
|
||||
return log_error_errno(arg_console_transport, "Failed to parse specified console transport: %s", optarg);
|
||||
|
||||
break;
|
||||
|
||||
case ARG_QEMU_GUI:
|
||||
arg_console_mode = CONSOLE_GUI;
|
||||
break;
|
||||
@@ -2588,11 +2600,6 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = qemu_config_section(config_file, "device", "vmspawn-virtio-serial-pci",
|
||||
"driver", "virtio-serial-pci");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Enable mux for native console so the QEMU monitor is accessible via Ctrl-a c */
|
||||
r = qemu_config_section(config_file, "chardev", "console",
|
||||
"backend", "serial",
|
||||
@@ -2601,12 +2608,6 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = qemu_config_section(config_file, "device", "virtconsole0",
|
||||
"driver", "virtconsole",
|
||||
"chardev", "console");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (arg_console_mode == CONSOLE_NATIVE) {
|
||||
r = qemu_config_section(config_file, "mon", "mon0",
|
||||
"chardev", "console");
|
||||
@@ -2655,6 +2656,29 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
if (!IN_SET(arg_console_mode, CONSOLE_GUI, CONSOLE_HEADLESS)) {
|
||||
if (arg_console_transport == CONSOLE_TRANSPORT_SERIAL) {
|
||||
/* Use -serial to connect the chardev to the platform's default serial
|
||||
* device (e.g. isa-serial on x86, PL011 on ARM). On some platforms the
|
||||
* serial device is a sysbus device that can only be connected via
|
||||
* serial_hd() which is populated by -serial, not via the config file. */
|
||||
r = strv_extend_many(&cmdline, "-serial", "chardev:console");
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
} else {
|
||||
r = qemu_config_section(config_file, "device", "vmspawn-virtio-serial-pci",
|
||||
"driver", "virtio-serial-pci");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = qemu_config_section(config_file, "device", "virtconsole0",
|
||||
"driver", "virtconsole",
|
||||
"chardev", "console");
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
r = qemu_config_section(config_file, "drive", "ovmf-code",
|
||||
"if", "pflash",
|
||||
"format", ovmf_config_format(ovmf_config),
|
||||
@@ -3028,7 +3052,9 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
|
||||
}
|
||||
|
||||
if (!IN_SET(arg_console_mode, CONSOLE_GUI, CONSOLE_HEADLESS)) {
|
||||
r = strv_prepend(&arg_kernel_cmdline_extra, "console=hvc0");
|
||||
r = strv_prepend(&arg_kernel_cmdline_extra,
|
||||
arg_console_transport == CONSOLE_TRANSPORT_SERIAL ?
|
||||
"console=" QEMU_SERIAL_CONSOLE_NAME : "console=hvc0");
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user