runtime: Add support for PEF

Protected Execution Facility(PEF) is the confidential computing
technology on ppc64le. This PR adds the support for it in Kata.
Also re-vendor govmm for the latest changes.

Fixes: #1881

Signed-off-by: Amulyam24 <amulmek1@in.ibm.com>
This commit is contained in:
Amulyam24 2021-05-25 14:29:42 +00:00
parent cc4748fa64
commit 37a426b4c6
6 changed files with 147 additions and 23 deletions

View File

@ -31,7 +31,7 @@ require (
github.com/gogo/googleapis v1.4.0 // indirect github.com/gogo/googleapis v1.4.0 // indirect
github.com/gogo/protobuf v1.3.1 github.com/gogo/protobuf v1.3.1
github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/go-multierror v1.0.0
github.com/kata-containers/govmm v0.0.0-20210428163604-f0e9a35308ee github.com/kata-containers/govmm v0.0.0-20210520142420-eb57f004d89f
github.com/mdlayher/vsock v0.0.0-20191108225356-d9c65923cb8f github.com/mdlayher/vsock v0.0.0-20191108225356-d9c65923cb8f
github.com/opencontainers/image-spec v1.0.1 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/opencontainers/runc v1.0.0-rc9.0.20200102164712-2b52db75279c github.com/opencontainers/runc v1.0.0-rc9.0.20200102164712-2b52db75279c

View File

@ -274,12 +274,10 @@ github.com/juju/errors v0.0.0-20180806074554-22422dad46e1/go.mod h1:W54LbzXuIE0b
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
github.com/juju/testing v0.0.0-20190613124551-e81189438503/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= github.com/juju/testing v0.0.0-20190613124551-e81189438503/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kata-containers/govmm v0.0.0-20210112013750-7d320e8f5dca h1:UdXFthwasAPnmv37gLJUEFsW9FaabYA+mM6FoSi8kzU=
github.com/kata-containers/govmm v0.0.0-20210112013750-7d320e8f5dca/go.mod h1:VmAHbsL5lLfzHW/MNL96NVLF840DNEV5i683kISgFKk=
github.com/kata-containers/govmm v0.0.0-20210329205824-7fbc685865d2 h1:oDJsQ5avmW8PFUkSJdsuaGL3SR4/YQRno51GNGl+IDU=
github.com/kata-containers/govmm v0.0.0-20210329205824-7fbc685865d2/go.mod h1:VmAHbsL5lLfzHW/MNL96NVLF840DNEV5i683kISgFKk=
github.com/kata-containers/govmm v0.0.0-20210428163604-f0e9a35308ee h1:M4N7AdSHgWz/ubV5AZQdeqmK+9Ztpea6oqeXgk8GCHk= github.com/kata-containers/govmm v0.0.0-20210428163604-f0e9a35308ee h1:M4N7AdSHgWz/ubV5AZQdeqmK+9Ztpea6oqeXgk8GCHk=
github.com/kata-containers/govmm v0.0.0-20210428163604-f0e9a35308ee/go.mod h1:VmAHbsL5lLfzHW/MNL96NVLF840DNEV5i683kISgFKk= github.com/kata-containers/govmm v0.0.0-20210428163604-f0e9a35308ee/go.mod h1:VmAHbsL5lLfzHW/MNL96NVLF840DNEV5i683kISgFKk=
github.com/kata-containers/govmm v0.0.0-20210520142420-eb57f004d89f h1:jXMZY7GIz5kSv3/Rdiesg1WMvgXJKNOk3KxwxgNWAVk=
github.com/kata-containers/govmm v0.0.0-20210520142420-eb57f004d89f/go.mod h1:VmAHbsL5lLfzHW/MNL96NVLF840DNEV5i683kISgFKk=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=

View File

@ -134,6 +134,9 @@ const (
// Loader is the Loader device driver. // Loader is the Loader device driver.
Loader DeviceDriver = "loader" Loader DeviceDriver = "loader"
// SpaprTPMProxy is used for enabling guest to run in secure mode on ppc64le.
SpaprTPMProxy DeviceDriver = "spapr-tpm-proxy"
) )
func isDimmSupported(config *Config) bool { func isDimmSupported(config *Config) bool {
@ -230,6 +233,14 @@ const (
// TDXGuest represents a TDX object // TDXGuest represents a TDX object
TDXGuest ObjectType = "tdx-guest" TDXGuest ObjectType = "tdx-guest"
// SEVGuest represents an SEV guest object
SEVGuest ObjectType = "sev-guest"
// SecExecGuest represents an s390x Secure Execution (Protected Virtualization in QEMU) object
SecExecGuest ObjectType = "s390-pv-guest"
// PEFGuest represent ppc64le PEF(Protected Execution Facility) object.
PEFGuest ObjectType = "pef-guest"
) )
// Object is a qemu object representation. // Object is a qemu object representation.
@ -258,37 +269,42 @@ type Object struct {
// File is the device file // File is the device file
File string File string
// CBitPos is the location of the C-bit in a guest page table entry
// This is only relevant for sev-guest objects
CBitPos uint32
// ReducedPhysBits is the reduction in the guest physical address space
// This is only relevant for sev-guest objects
ReducedPhysBits uint32
} }
// Valid returns true if the Object structure is valid and complete. // Valid returns true if the Object structure is valid and complete.
func (object Object) Valid() bool { func (object Object) Valid() bool {
switch object.Type { switch object.Type {
case MemoryBackendFile: case MemoryBackendFile:
if object.ID == "" || object.MemPath == "" || object.Size == 0 { return object.ID != "" && object.MemPath != "" && object.Size != 0
return false
}
case TDXGuest: case TDXGuest:
if object.ID == "" || object.File == "" || object.DeviceID == "" { return object.ID != "" && object.File != "" && object.DeviceID != ""
return false case SEVGuest:
} return object.ID != "" && object.File != "" && object.CBitPos != 0 && object.ReducedPhysBits != 0
case SecExecGuest:
return object.ID != ""
case PEFGuest:
return object.ID != "" && object.File != ""
default: default:
return false return false
} }
return true
} }
// QemuParams returns the qemu parameters built out of this Object device. // QemuParams returns the qemu parameters built out of this Object device.
func (object Object) QemuParams(config *Config) []string { func (object Object) QemuParams(config *Config) []string {
var objectParams []string var objectParams []string
var deviceParams []string var deviceParams []string
var driveParams []string
var qemuParams []string var qemuParams []string
deviceParams = append(deviceParams, string(object.Driver))
deviceParams = append(deviceParams, fmt.Sprintf(",id=%s", object.DeviceID))
switch object.Type { switch object.Type {
case MemoryBackendFile: case MemoryBackendFile:
objectParams = append(objectParams, string(object.Type)) objectParams = append(objectParams, string(object.Type))
@ -296,6 +312,8 @@ func (object Object) QemuParams(config *Config) []string {
objectParams = append(objectParams, fmt.Sprintf(",mem-path=%s", object.MemPath)) objectParams = append(objectParams, fmt.Sprintf(",mem-path=%s", object.MemPath))
objectParams = append(objectParams, fmt.Sprintf(",size=%d", object.Size)) objectParams = append(objectParams, fmt.Sprintf(",size=%d", object.Size))
deviceParams = append(deviceParams, string(object.Driver))
deviceParams = append(deviceParams, fmt.Sprintf(",id=%s", object.DeviceID))
deviceParams = append(deviceParams, fmt.Sprintf(",memdev=%s", object.ID)) deviceParams = append(deviceParams, fmt.Sprintf(",memdev=%s", object.ID))
case TDXGuest: case TDXGuest:
objectParams = append(objectParams, string(object.Type)) objectParams = append(objectParams, string(object.Type))
@ -303,14 +321,44 @@ func (object Object) QemuParams(config *Config) []string {
if object.Debug { if object.Debug {
objectParams = append(objectParams, ",debug=on") objectParams = append(objectParams, ",debug=on")
} }
deviceParams = append(deviceParams, string(object.Driver))
deviceParams = append(deviceParams, fmt.Sprintf(",id=%s", object.DeviceID))
deviceParams = append(deviceParams, fmt.Sprintf(",file=%s", object.File)) deviceParams = append(deviceParams, fmt.Sprintf(",file=%s", object.File))
case SEVGuest:
objectParams = append(objectParams, string(object.Type))
objectParams = append(objectParams, fmt.Sprintf(",id=%s", object.ID))
objectParams = append(objectParams, fmt.Sprintf(",cbitpos=%d", object.CBitPos))
objectParams = append(objectParams, fmt.Sprintf(",reduced-phys-bits=%d", object.ReducedPhysBits))
driveParams = append(driveParams, "if=pflash,format=raw,readonly=on")
driveParams = append(driveParams, fmt.Sprintf(",file=%s", object.File))
case SecExecGuest:
objectParams = append(objectParams, string(object.Type))
objectParams = append(objectParams, fmt.Sprintf(",id=%s", object.ID))
case PEFGuest:
objectParams = append(objectParams, string(object.Type))
objectParams = append(objectParams, fmt.Sprintf(",id=%s", object.ID))
deviceParams = append(deviceParams, string(object.Driver))
deviceParams = append(deviceParams, fmt.Sprintf(",id=%s", object.DeviceID))
deviceParams = append(deviceParams, fmt.Sprintf(",host-path=%s", object.File))
} }
qemuParams = append(qemuParams, "-device") if len(deviceParams) > 0 {
qemuParams = append(qemuParams, strings.Join(deviceParams, "")) qemuParams = append(qemuParams, "-device")
qemuParams = append(qemuParams, strings.Join(deviceParams, ""))
}
qemuParams = append(qemuParams, "-object") if len(objectParams) > 0 {
qemuParams = append(qemuParams, strings.Join(objectParams, "")) qemuParams = append(qemuParams, "-object")
qemuParams = append(qemuParams, strings.Join(objectParams, ""))
}
if len(driveParams) > 0 {
qemuParams = append(qemuParams, "-drive")
qemuParams = append(qemuParams, strings.Join(driveParams, ""))
}
return qemuParams return qemuParams
} }

View File

@ -222,7 +222,7 @@ github.com/hashicorp/errwrap
# github.com/hashicorp/go-multierror v1.0.0 # github.com/hashicorp/go-multierror v1.0.0
## explicit ## explicit
github.com/hashicorp/go-multierror github.com/hashicorp/go-multierror
# github.com/kata-containers/govmm v0.0.0-20210428163604-f0e9a35308ee # github.com/kata-containers/govmm v0.0.0-20210520142420-eb57f004d89f
## explicit ## explicit
github.com/kata-containers/govmm/qemu github.com/kata-containers/govmm/qemu
# github.com/konsorten/go-windows-terminal-sequences v1.0.1 # github.com/konsorten/go-windows-terminal-sequences v1.0.1

View File

@ -0,0 +1,17 @@
// Copyright (c) 2021 IBM
//
// SPDX-License-Identifier: Apache-2.0
package virtcontainers
import "os"
//Returns pefProtection if the firmware directory exists
func availableGuestProtection() (guestProtection, error) {
if d, err := os.Stat(pefSysFirmwareDir); err == nil && d.IsDir() {
return pefProtection, err
}
return noneProtection, nil
}

View File

@ -27,6 +27,14 @@ const defaultQemuMachineOptions = "accel=kvm,usb=off"
const qmpMigrationWaitTimeout = 5 * time.Second const qmpMigrationWaitTimeout = 5 * time.Second
const pefSysFirmwareDir = "/sys/firmware/ultravisor/"
const pefID = "pef0"
const tpmID = "tpm0"
const tpmHostPath = "/dev/tpmrm0"
var kernelParams = []Param{ var kernelParams = []Param{
{"rcupdate.rcu_expedited", "1"}, {"rcupdate.rcu_expedited", "1"},
{"reboot", "k"}, {"reboot", "k"},
@ -43,7 +51,7 @@ var supportedQemuMachine = govmmQemu.Machine{
// Logger returns a logrus logger appropriate for logging qemu messages // Logger returns a logrus logger appropriate for logging qemu messages
func (q *qemuPPC64le) Logger() *logrus.Entry { func (q *qemuPPC64le) Logger() *logrus.Entry {
return virtLog.WithField("subsystem", "qemu") return virtLog.WithField("subsystem", "qemuPPC64le")
} }
// MaxQemuVCPUs returns the maximum number of vCPUs supported // MaxQemuVCPUs returns the maximum number of vCPUs supported
@ -69,9 +77,16 @@ func newQemuArch(config HypervisorConfig) (qemuArch, error) {
kernelParamsNonDebug: kernelParamsNonDebug, kernelParamsNonDebug: kernelParamsNonDebug,
kernelParamsDebug: kernelParamsDebug, kernelParamsDebug: kernelParamsDebug,
kernelParams: kernelParams, kernelParams: kernelParams,
protection: noneProtection,
}, },
} }
if config.ConfidentialGuest {
if err := q.enableProtection(); err != nil {
return nil, err
}
}
q.handleImagePath(config) q.handleImagePath(config)
q.memoryOffset = config.MemOffset q.memoryOffset = config.MemOffset
@ -116,3 +131,49 @@ func (q *qemuPPC64le) appendBridges(devices []govmmQemu.Device) []govmmQemu.Devi
func (q *qemuPPC64le) appendIOMMU(devices []govmmQemu.Device) ([]govmmQemu.Device, error) { func (q *qemuPPC64le) appendIOMMU(devices []govmmQemu.Device) ([]govmmQemu.Device, error) {
return devices, fmt.Errorf("PPC64le does not support appending a vIOMMU") return devices, fmt.Errorf("PPC64le does not support appending a vIOMMU")
} }
// Enables guest protection
func (q *qemuPPC64le) enableProtection() error {
var err error
q.protection, err = availableGuestProtection()
if err != nil {
return err
}
switch q.protection {
case pefProtection:
if q.qemuMachine.Options != "" {
q.qemuMachine.Options += ","
}
q.qemuMachine.Options += fmt.Sprintf("confidential-guest-support=%s", pefID)
virtLog.WithFields(logrus.Fields{
"subsystem": "qemuPPC64le",
"machine": q.qemuMachine,
"kernel-params": q.kernelParams,
}).Info("Enabling PEF protection")
return nil
default:
return fmt.Errorf("This system doesn't support Confidential Computing (Guest Protection)")
}
}
// append protection device
func (q *qemuPPC64le) appendProtectionDevice(devices []govmmQemu.Device, firmware string) ([]govmmQemu.Device, string, error) {
switch q.protection {
case pefProtection:
return append(devices,
govmmQemu.Object{
Driver: govmmQemu.SpaprTPMProxy,
Type: govmmQemu.PEFGuest,
ID: pefID,
DeviceID: tpmID,
File: tpmHostPath,
}), firmware, nil
case noneProtection:
return devices, firmware, nil
default:
return devices, "", fmt.Errorf("Unsupported guest protection technology: %v", q.protection)
}
}