mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-06-27 15:57:09 +00:00
runtime: Support for AMD SEV-SNP VMs
This commit adds AMD SEV-SNP as a confidential guest option to the runtime. Information on required components such as OVMF, QEMU and a kernel supporting SEV-SNP are defined in the versions file and corresponding configs are added. Note: The CPU model 'host' provided by the current SNP-QEMU does not support all SNP capabilities yet, which is why this option is changed to EPYC-v4. Note: The guest's physical address space reduction specified with ReducedPhysBits is 1. Details are can be found in Section 15.34.6 here https://www.amd.com/system/files/TechDocs/24593.pdf Fixes #4437 Signed-off-by: Joana Pecholt <joana.pecholt@aisec.fraunhofer.de>
This commit is contained in:
parent
a2bbd29422
commit
22bda0838c
@ -231,6 +231,9 @@ const (
|
||||
// SEVGuest represents an SEV guest object
|
||||
SEVGuest ObjectType = "sev-guest"
|
||||
|
||||
// SNPGuest represents an SNP guest object
|
||||
SNPGuest ObjectType = "sev-snp-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.
|
||||
@ -295,6 +298,8 @@ func (object Object) Valid() bool {
|
||||
case TDXGuest:
|
||||
return object.ID != "" && object.File != "" && object.DeviceID != ""
|
||||
case SEVGuest:
|
||||
fallthrough
|
||||
case SNPGuest:
|
||||
return object.ID != "" && object.File != "" && object.CBitPos != 0 && object.ReducedPhysBits != 0
|
||||
case SecExecGuest:
|
||||
return object.ID != ""
|
||||
@ -349,6 +354,8 @@ func (object Object) QemuParams(config *Config) []string {
|
||||
deviceParams = append(deviceParams, fmt.Sprintf("config-firmware-volume=%s", object.FirmwareVolume))
|
||||
}
|
||||
case SEVGuest:
|
||||
fallthrough
|
||||
case SNPGuest:
|
||||
objectParams = append(objectParams, string(object.Type))
|
||||
objectParams = append(objectParams, fmt.Sprintf("id=%s", object.ID))
|
||||
objectParams = append(objectParams, fmt.Sprintf("cbitpos=%d", object.CBitPos))
|
||||
|
@ -422,6 +422,8 @@ func (clh *cloudHypervisor) enableProtection() error {
|
||||
|
||||
case sevProtection:
|
||||
return errors.New("SEV protection is not supported by Cloud Hypervisor")
|
||||
case snpProtection:
|
||||
return errors.New("SEV-SNP protection is not supported by Cloud Hypervisor")
|
||||
|
||||
default:
|
||||
return errors.New("This system doesn't support Confidentian Computing (Guest Protection)")
|
||||
|
@ -870,6 +870,11 @@ const (
|
||||
// Exclude from lint checking for it won't be used on arm64 code
|
||||
sevProtection
|
||||
|
||||
// AMD Secure Encrypted Virtualization - Secure Nested Paging (SEV-SNP)
|
||||
// https://developer.amd.com/sev/
|
||||
// Exclude from lint checking for it won't be used on arm64 code
|
||||
snpProtection
|
||||
|
||||
// IBM POWER 9 Protected Execution Facility
|
||||
// https://www.kernel.org/doc/html/latest/powerpc/ultravisor.html
|
||||
// Exclude from lint checking for it won't be used on arm64 code
|
||||
@ -886,6 +891,7 @@ var guestProtectionStr = [...]string{
|
||||
pefProtection: "pef",
|
||||
seProtection: "se",
|
||||
sevProtection: "sev",
|
||||
snpProtection: "snp",
|
||||
tdxProtection: "tdx",
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,8 @@ const (
|
||||
tdxCPUFlag = "tdx"
|
||||
|
||||
sevKvmParameterPath = "/sys/module/kvm_amd/parameters/sev"
|
||||
|
||||
snpKvmParameterPath = "/sys/module/kvm_amd/parameters/sev_snp"
|
||||
)
|
||||
|
||||
// Implementation of this function is architecture specific
|
||||
@ -26,6 +28,13 @@ func availableGuestProtection() (guestProtection, error) {
|
||||
if d, err := os.Stat(tdxSysFirmwareDir); (err == nil && d.IsDir()) || flags[tdxCPUFlag] {
|
||||
return tdxProtection, nil
|
||||
}
|
||||
// SEV-SNP is supported and enabled when the kvm module `sev_snp` parameter is set to `Y`
|
||||
if _, err := os.Stat(snpKvmParameterPath); err == nil {
|
||||
if c, err := os.ReadFile(snpKvmParameterPath); err == nil && len(c) > 0 && (c[0] == 'Y') {
|
||||
return snpProtection, nil
|
||||
}
|
||||
}
|
||||
// Only choose SEV if SEV-SNP unsupported
|
||||
// SEV is supported and enabled when the kvm module `sev` parameter is set to `1` (or `Y` for linux >= 5.12)
|
||||
if _, err := os.Stat(sevKvmParameterPath); err == nil {
|
||||
if c, err := os.ReadFile(sevKvmParameterPath); err == nil && len(c) > 0 && (c[0] == '1' || c[0] == 'Y') {
|
||||
|
@ -169,6 +169,21 @@ func (q *qemuAmd64) bridges(number uint32) {
|
||||
q.Bridges = genericBridges(number, q.qemuMachine.Type)
|
||||
}
|
||||
|
||||
func (q *qemuAmd64) cpuModel() string {
|
||||
var err error
|
||||
cpuModel := defaultCPUModel
|
||||
|
||||
// Temporary until QEMU cpu model 'host' supports AMD SEV-SNP
|
||||
protection, err := availableGuestProtection()
|
||||
if err == nil {
|
||||
if protection == snpProtection {
|
||||
cpuModel = "EPYC-v4"
|
||||
}
|
||||
}
|
||||
|
||||
return cpuModel
|
||||
}
|
||||
|
||||
func (q *qemuAmd64) memoryTopology(memoryMb, hostMemoryMb uint64, slots uint8) govmmQemu.Memory {
|
||||
return genericMemoryTopology(memoryMb, hostMemoryMb, slots, q.memoryOffset)
|
||||
}
|
||||
@ -219,6 +234,13 @@ func (q *qemuAmd64) enableProtection() error {
|
||||
q.qemuMachine.Options += "confidential-guest-support=sev"
|
||||
logger.Info("Enabling SEV guest protection")
|
||||
return nil
|
||||
case snpProtection:
|
||||
if q.qemuMachine.Options != "" {
|
||||
q.qemuMachine.Options += ","
|
||||
}
|
||||
q.qemuMachine.Options += "confidential-guest-support=snp"
|
||||
logger.Info("Enabling SNP guest protection")
|
||||
return nil
|
||||
|
||||
// TODO: Add support for other x86_64 technologies
|
||||
|
||||
@ -263,6 +285,16 @@ func (q *qemuAmd64) appendProtectionDevice(devices []govmmQemu.Device, firmware,
|
||||
CBitPos: cpuid.AMDMemEncrypt.CBitPosition,
|
||||
ReducedPhysBits: cpuid.AMDMemEncrypt.PhysAddrReduction,
|
||||
}), "", nil
|
||||
case snpProtection:
|
||||
return append(devices,
|
||||
govmmQemu.Object{
|
||||
Type: govmmQemu.SNPGuest,
|
||||
ID: "snp",
|
||||
Debug: false,
|
||||
File: firmware,
|
||||
CBitPos: cpuid.AMDMemEncrypt.CBitPosition,
|
||||
ReducedPhysBits: 1,
|
||||
}), "", nil
|
||||
case noneProtection:
|
||||
return devices, firmware, nil
|
||||
|
||||
|
@ -293,6 +293,26 @@ func TestQemuAmd64AppendProtectionDevice(t *testing.T) {
|
||||
|
||||
assert.Equal(expectedOut, devices)
|
||||
|
||||
// snp protection
|
||||
amd64.(*qemuAmd64).protection = snpProtection
|
||||
|
||||
devices, bios, err = amd64.appendProtectionDevice(devices, firmware, "")
|
||||
assert.NoError(err)
|
||||
assert.Empty(bios)
|
||||
|
||||
expectedOut = append(expectedOut,
|
||||
govmmQemu.Object{
|
||||
Type: govmmQemu.SNPGuest,
|
||||
ID: "snp",
|
||||
Debug: false,
|
||||
File: firmware,
|
||||
CBitPos: cpuid.AMDMemEncrypt.CBitPosition,
|
||||
ReducedPhysBits: 1,
|
||||
},
|
||||
)
|
||||
|
||||
assert.Equal(expectedOut, devices)
|
||||
|
||||
// tdxProtection
|
||||
amd64.(*qemuAmd64).protection = tdxProtection
|
||||
|
||||
|
@ -209,6 +209,13 @@ func TestQemuArm64AppendProtectionDevice(t *testing.T) {
|
||||
assert.Empty(bios)
|
||||
assert.NoError(err)
|
||||
|
||||
// SNP protection
|
||||
arm64.(*qemuArm64).protection = snpProtection
|
||||
devices, bios, err = arm64.appendProtectionDevice(devices, firmware, "")
|
||||
assert.Empty(devices)
|
||||
assert.Empty(bios)
|
||||
assert.NoError(err)
|
||||
|
||||
// TDX protection
|
||||
arm64.(*qemuArm64).protection = tdxProtection
|
||||
devices, bios, err = arm64.appendProtectionDevice(devices, firmware, "")
|
||||
|
@ -79,6 +79,12 @@ func TestQemuPPC64leAppendProtectionDevice(t *testing.T) {
|
||||
assert.Error(err)
|
||||
assert.Empty(bios)
|
||||
|
||||
//SNP protection
|
||||
ppc64le.(*qemuPPC64le).protection = snpProtection
|
||||
devices, bios, err = ppc64le.appendProtectionDevice(devices, firmware, "")
|
||||
assert.Error(err)
|
||||
assert.Empty(bios)
|
||||
|
||||
//TDX protection
|
||||
ppc64le.(*qemuPPC64le).protection = tdxProtection
|
||||
devices, bios, err = ppc64le.appendProtectionDevice(devices, firmware, "")
|
||||
|
@ -136,6 +136,12 @@ func TestQemuS390xAppendProtectionDevice(t *testing.T) {
|
||||
assert.Error(err)
|
||||
assert.Empty(bios)
|
||||
|
||||
// SNP protection
|
||||
s390x.(*qemuS390x).protection = snpProtection
|
||||
devices, bios, err = s390x.appendProtectionDevice(devices, firmware, "")
|
||||
assert.Error(err)
|
||||
assert.Empty(bios)
|
||||
|
||||
// Secure Execution protection
|
||||
s390x.(*qemuS390x).protection = seProtection
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user