virtcontainers: Support TDX

Add support for Intel TDX confidential guests

fixes #1332

Signed-off-by: Julio Montes <julio.montes@intel.com>
This commit is contained in:
Julio Montes 2021-05-05 09:37:15 -05:00
parent 0affe8860d
commit 4f61f4b490
3 changed files with 126 additions and 2 deletions

View File

@ -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
}

View File

@ -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 {
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) {
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)
}
}

View File

@ -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)
}