diff --git a/src/runtime/virtcontainers/hypervisor_amd64.go b/src/runtime/virtcontainers/hypervisor_amd64.go new file mode 100644 index 0000000000..4b75a08cfd --- /dev/null +++ b/src/runtime/virtcontainers/hypervisor_amd64.go @@ -0,0 +1,25 @@ +// Copyright (c) 2021 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +package virtcontainers + +import "os" + +// Implementation of this function is architecture specific +func availableGuestProtection() (guestProtection, error) { + flags, err := CPUFlags(procCPUInfo) + if err != nil { + return noneProtection, err + } + + // TDX is supported and properly loaded when the firmware directory exists or `tdx` is part of the CPU flags + if d, err := os.Stat(tdxSysFirmwareDir); (err == nil && d.IsDir()) || flags[tdxCPUFlag] { + return tdxProtection, nil + } + + // TODO: Add support for other technologies: SEV + + return noneProtection, nil +} diff --git a/src/runtime/virtcontainers/qemu_amd64.go b/src/runtime/virtcontainers/qemu_amd64.go index ec2e764083..37b0748b31 100644 --- a/src/runtime/virtcontainers/qemu_amd64.go +++ b/src/runtime/virtcontainers/qemu_amd64.go @@ -11,6 +11,7 @@ import ( "time" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" + "github.com/sirupsen/logrus" govmmQemu "github.com/kata-containers/govmm/qemu" ) @@ -20,6 +21,8 @@ type qemuAmd64 struct { qemuArchBase vmFactory bool + + devLoadersCount uint32 } const ( @@ -30,6 +33,10 @@ const ( defaultQemuMachineOptions = "accel=kvm,kernel_irqchip" qmpMigrationWaitTimeout = 5 * time.Second + + tdxSysFirmwareDir = "/sys/firmware/tdx_seam/" + + tdxCPUFlag = "tdx" ) var qemuPaths = map[string]string{ @@ -201,10 +208,52 @@ func (q *qemuAmd64) appendBridges(devices []govmmQemu.Device) []govmmQemu.Device // enable protection func (q *qemuAmd64) enableProtection() error { - return nil + var err error + q.protection, err = availableGuestProtection() + if err != nil { + return err + } + + switch q.protection { + case tdxProtection: + if q.qemuMachine.Options != "" { + q.qemuMachine.Options += "," + } + q.qemuMachine.Options += "kvm-type=tdx,confidential-guest-support=tdx" + q.kernelParams = append(q.kernelParams, Param{"tdx_guest", ""}) + virtLog.WithFields(logrus.Fields{ + "subsystem": "qemuAmd64", + "machine": q.qemuMachine, + "kernel-params": q.kernelParameters}). + Info("Enabling TDX guest protection") + return nil + + // TODO: Add support for other x86_64 technologies: SEV + + default: + return fmt.Errorf("This system doesn't support Confidential Computing (Guest Protection)") + } } // append protection device func (q *qemuAmd64) appendProtectionDevice(devices []govmmQemu.Device, firmware string) ([]govmmQemu.Device, string, error) { - return devices, firmware, nil + switch q.protection { + case tdxProtection: + id := q.devLoadersCount + q.devLoadersCount += 1 + return append(devices, + govmmQemu.Object{ + Driver: govmmQemu.Loader, + Type: govmmQemu.TDXGuest, + ID: "tdx", + DeviceID: fmt.Sprintf("fd%d", id), + Debug: false, + File: firmware, + }), "", nil + case noneProtection: + return devices, firmware, nil + + default: + return devices, "", fmt.Errorf("Unsupported guest protection technology: %v", q.protection) + } } diff --git a/src/runtime/virtcontainers/qemu_amd64_test.go b/src/runtime/virtcontainers/qemu_amd64_test.go index 1d321e9353..8772361cba 100644 --- a/src/runtime/virtcontainers/qemu_amd64_test.go +++ b/src/runtime/virtcontainers/qemu_amd64_test.go @@ -276,3 +276,53 @@ func TestQemuAmd64Microvm(t *testing.T) { assert.False(amd64.supportGuestMemoryHotplug()) } + +func TestQemuAmd64AppendProtectionDevice(t *testing.T) { + var devices []govmmQemu.Device + assert := assert.New(t) + + amd64 := newTestQemu(assert, QemuPC) + + id := amd64.(*qemuAmd64).devLoadersCount + firmware := "tdvf.fd" + var bios string + var err error + devices, bios, err = amd64.appendProtectionDevice(devices, firmware) + assert.NoError(err) + + // non-protection + assert.NotEmpty(bios) + + // pef protection + amd64.(*qemuAmd64).protection = pefProtection + devices, bios, err = amd64.appendProtectionDevice(devices, firmware) + assert.Error(err) + assert.Empty(bios) + + // sev protection + // TODO: update once it's supported + amd64.(*qemuAmd64).protection = sevProtection + devices, bios, err = amd64.appendProtectionDevice(devices, firmware) + assert.Error(err) + assert.Empty(bios) + + // tdxProtection + amd64.(*qemuAmd64).protection = tdxProtection + + devices, bios, err = amd64.appendProtectionDevice(devices, firmware) + assert.NoError(err) + assert.Empty(bios) + + expectedOut := []govmmQemu.Device{ + govmmQemu.Object{ + Driver: govmmQemu.Loader, + Type: govmmQemu.TDXGuest, + ID: "tdx", + DeviceID: fmt.Sprintf("fd%d", id), + Debug: false, + File: firmware, + }, + } + + assert.Equal(expectedOut, devices) +}