From c67b9d2975f6c24a63a9ae3d11bcb1380dfde8b2 Mon Sep 17 00:00:00 2001 From: Snir Sheriber Date: Thu, 12 May 2022 14:26:51 +0300 Subject: [PATCH] qemu: allow using legacy serial device for the console This allows to get guest early boot logs which are usually missed when virtconsole is used. - It utilizes previous work on the govmm side: https://github.com/kata-containers/govmm/pull/203 - unit test added Fixes: #4237 Signed-off-by: Snir Sheriber --- src/runtime/config/configuration-qemu.toml.in | 3 + .../pkg/katautils/config-settings.go.in | 1 + src/runtime/pkg/katautils/config.go | 3 + src/runtime/virtcontainers/hypervisor.go | 3 + src/runtime/virtcontainers/qemu_amd64.go | 1 + src/runtime/virtcontainers/qemu_arch_base.go | 59 +++++++++++++------ .../virtcontainers/qemu_arch_base_test.go | 28 +++++++++ src/runtime/virtcontainers/qemu_arm64.go | 1 + src/runtime/virtcontainers/qemu_ppc64le.go | 1 + src/runtime/virtcontainers/qemu_s390x.go | 1 + 10 files changed, 82 insertions(+), 19 deletions(-) diff --git a/src/runtime/config/configuration-qemu.toml.in b/src/runtime/config/configuration-qemu.toml.in index e0dd09cf6b..09c219545d 100644 --- a/src/runtime/config/configuration-qemu.toml.in +++ b/src/runtime/config/configuration-qemu.toml.in @@ -389,6 +389,9 @@ valid_entropy_sources = @DEFVALIDENTROPYSOURCES@ # be default_memory. #enable_guest_swap = true +# use legacy serial for guest console if available and implemented for architecture. Default false +#use_legacy_serial = true + [factory] # VM templating support. Once enabled, new VMs are created from template # using vm cloning. They will share the same initial kernel, initramfs and diff --git a/src/runtime/pkg/katautils/config-settings.go.in b/src/runtime/pkg/katautils/config-settings.go.in index 09d6b5f30c..2aad22bd85 100644 --- a/src/runtime/pkg/katautils/config-settings.go.in +++ b/src/runtime/pkg/katautils/config-settings.go.in @@ -89,6 +89,7 @@ const defaultGuestSwap = false const defaultRootlessHypervisor = false const defaultDisableSeccomp = false const defaultVfioMode = "guest-kernel" +const defaultLegacySerial = false var defaultSGXEPCSize = int64(0) diff --git a/src/runtime/pkg/katautils/config.go b/src/runtime/pkg/katautils/config.go index ec02b4bc26..2a62c3d6c3 100644 --- a/src/runtime/pkg/katautils/config.go +++ b/src/runtime/pkg/katautils/config.go @@ -146,6 +146,7 @@ type hypervisor struct { Rootless bool `toml:"rootless"` DisableSeccomp bool `toml:"disable_seccomp"` DisableSeLinux bool `toml:"disable_selinux"` + LegacySerial bool `toml:"use_legacy_serial"` } type runtime struct { @@ -775,6 +776,7 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { ConfidentialGuest: h.ConfidentialGuest, GuestSwap: h.GuestSwap, Rootless: h.Rootless, + LegacySerial: h.LegacySerial, }, nil } @@ -1132,6 +1134,7 @@ func GetDefaultHypervisorConfig() vc.HypervisorConfig { GuestSwap: defaultGuestSwap, Rootless: defaultRootlessHypervisor, DisableSeccomp: defaultDisableSeccomp, + LegacySerial: defaultLegacySerial, } } diff --git a/src/runtime/virtcontainers/hypervisor.go b/src/runtime/virtcontainers/hypervisor.go index c689eae3c9..9de4dc0d0a 100644 --- a/src/runtime/virtcontainers/hypervisor.go +++ b/src/runtime/virtcontainers/hypervisor.go @@ -537,6 +537,9 @@ type HypervisorConfig struct { // Disable selinux from the hypervisor process DisableSeLinux bool + + // Use legacy serial for the guest console + LegacySerial bool } // vcpu mapping from vcpu number to thread number diff --git a/src/runtime/virtcontainers/qemu_amd64.go b/src/runtime/virtcontainers/qemu_amd64.go index 773af95e8a..61c18c68e4 100644 --- a/src/runtime/virtcontainers/qemu_amd64.go +++ b/src/runtime/virtcontainers/qemu_amd64.go @@ -122,6 +122,7 @@ func newQemuArch(config HypervisorConfig) (qemuArch, error) { disableNvdimm: config.DisableImageNvdimm, dax: true, protection: noneProtection, + legacySerial: config.LegacySerial, }, vmFactory: factory, } diff --git a/src/runtime/virtcontainers/qemu_arch_base.go b/src/runtime/virtcontainers/qemu_arch_base.go index 0b5d505203..a2873a2160 100644 --- a/src/runtime/virtcontainers/qemu_arch_base.go +++ b/src/runtime/virtcontainers/qemu_arch_base.go @@ -169,6 +169,7 @@ type qemuArchBase struct { vhost bool disableNvdimm bool dax bool + legacySerial bool } const ( @@ -318,29 +319,49 @@ func (q *qemuArchBase) memoryTopology(memoryMb, hostMemoryMb uint64, slots uint8 } func (q *qemuArchBase) appendConsole(_ context.Context, devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error) { - serial := govmmQemu.SerialDevice{ - Driver: govmmQemu.VirtioSerial, - ID: "serial0", - DisableModern: q.nestedRun, - MaxPorts: uint(2), + var serial, console govmmQemu.Device + var consoleKernelParams []Param + + if q.legacySerial { + serial = govmmQemu.LegacySerialDevice{ + Chardev: "charconsole0", + } + + console = govmmQemu.CharDevice{ + Driver: govmmQemu.LegacySerial, + Backend: govmmQemu.Socket, + DeviceID: "console0", + ID: "charconsole0", + Path: path, + } + + consoleKernelParams = []Param{ + {"console", "ttyS0"}, + } + } else { + serial = govmmQemu.SerialDevice{ + Driver: govmmQemu.VirtioSerial, + ID: "serial0", + DisableModern: q.nestedRun, + MaxPorts: uint(2), + } + + console = govmmQemu.CharDevice{ + Driver: govmmQemu.Console, + Backend: govmmQemu.Socket, + DeviceID: "console0", + ID: "charconsole0", + Path: path, + } + + consoleKernelParams = []Param{ + {"console", "hvc0"}, + {"console", "hvc1"}, + } } devices = append(devices, serial) - - console := govmmQemu.CharDevice{ - Driver: govmmQemu.Console, - Backend: govmmQemu.Socket, - DeviceID: "console0", - ID: "charconsole0", - Path: path, - } - devices = append(devices, console) - - consoleKernelParams := []Param{ - {"console", "hvc0"}, - {"console", "hvc1"}, - } q.kernelParams = append(q.kernelParams, consoleKernelParams...) return devices, nil diff --git a/src/runtime/virtcontainers/qemu_arch_base_test.go b/src/runtime/virtcontainers/qemu_arch_base_test.go index 2625a8a99d..57c97f773b 100644 --- a/src/runtime/virtcontainers/qemu_arch_base_test.go +++ b/src/runtime/virtcontainers/qemu_arch_base_test.go @@ -263,6 +263,34 @@ func TestQemuArchBaseAppendConsoles(t *testing.T) { assert.Contains(qemuArchBase.kernelParams, Param{"console", "hvc1"}) } +func TestQemuArchBaseAppendConsolesLegacy(t *testing.T) { + var devices []govmmQemu.Device + var err error + assert := assert.New(t) + qemuArchBase := newQemuArchBase() + qemuArchBase.legacySerial = true + + path := filepath.Join(filepath.Join(fs.MockRunStoragePath(), "test"), consoleSocket) + + expectedOut := []govmmQemu.Device{ + govmmQemu.LegacySerialDevice{ + Chardev: "charconsole0", + }, + govmmQemu.CharDevice{ + Driver: govmmQemu.LegacySerial, + Backend: govmmQemu.Socket, + DeviceID: "console0", + ID: "charconsole0", + Path: path, + }, + } + + devices, err = qemuArchBase.appendConsole(context.Background(), devices, path) + assert.NoError(err) + assert.Equal(expectedOut, devices) + assert.Contains(qemuArchBase.kernelParams, Param{"console", "ttyS0"}) +} + func TestQemuArchBaseAppendImage(t *testing.T) { var devices []govmmQemu.Device assert := assert.New(t) diff --git a/src/runtime/virtcontainers/qemu_arm64.go b/src/runtime/virtcontainers/qemu_arm64.go index f3a5576606..378b89c6d7 100644 --- a/src/runtime/virtcontainers/qemu_arm64.go +++ b/src/runtime/virtcontainers/qemu_arm64.go @@ -62,6 +62,7 @@ func newQemuArch(config HypervisorConfig) (qemuArch, error) { disableNvdimm: config.DisableImageNvdimm, dax: true, protection: noneProtection, + legacySerial: config.LegacySerial, }, } diff --git a/src/runtime/virtcontainers/qemu_ppc64le.go b/src/runtime/virtcontainers/qemu_ppc64le.go index cfff5329c1..27bac35818 100644 --- a/src/runtime/virtcontainers/qemu_ppc64le.go +++ b/src/runtime/virtcontainers/qemu_ppc64le.go @@ -74,6 +74,7 @@ func newQemuArch(config HypervisorConfig) (qemuArch, error) { kernelParamsDebug: kernelParamsDebug, kernelParams: kernelParams, protection: noneProtection, + legacySerial: config.LegacySerial, }, } diff --git a/src/runtime/virtcontainers/qemu_s390x.go b/src/runtime/virtcontainers/qemu_s390x.go index 210a341766..f0946698f7 100644 --- a/src/runtime/virtcontainers/qemu_s390x.go +++ b/src/runtime/virtcontainers/qemu_s390x.go @@ -66,6 +66,7 @@ func newQemuArch(config HypervisorConfig) (qemuArch, error) { kernelParamsNonDebug: kernelParamsNonDebug, kernelParamsDebug: kernelParamsDebug, kernelParams: kernelParams, + legacySerial: false, }, } // Set first bridge type to CCW