SEV-SNP is an enhancement of SEV/SEV-ES and thus it shares some
fields with it. Nevertheless, on XML level, it's yet another type
of <launchSecurity/>.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
docs/formatdomain.rst | 108 ++++++++++++++++++
src/conf/domain_conf.c | 73 ++++++++++++
src/conf/domain_conf.h | 15 +++
src/conf/domain_validate.c | 44 +++++++
src/conf/schemas/domaincommon.rng | 49 ++++++++
src/conf/virconftypes.h | 2 +
src/qemu/qemu_cgroup.c | 1 +
src/qemu/qemu_command.c | 4 +
src/qemu/qemu_driver.c | 1 +
src/qemu/qemu_firmware.c | 3 +
src/qemu/qemu_namespace.c | 1 +
src/qemu/qemu_process.c | 3 +
src/qemu/qemu_validate.c | 9 ++
src/security/security_dac.c | 2 +
...launch-security-sev-snp.x86_64-latest.args | 34 ++++++
.../launch-security-sev-snp.x86_64-latest.xml | 1 +
.../launch-security-sev-snp.xml | 47 ++++++++
tests/qemuxmlconftest.c | 2 +
18 files changed, 399 insertions(+)
create mode 100644 tests/qemuxmlconfdata/launch-security-sev-snp.x86_64-latest.args
create mode 120000 tests/qemuxmlconfdata/launch-security-sev-snp.x86_64-latest.xml
create mode 100644 tests/qemuxmlconfdata/launch-security-sev-snp.xml
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 00f861e385..5c09b87d2b 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -8867,6 +8867,114 @@ spec
<
https://support.amd.com/TechDocs/55766_SEV-KM_API_Specification.pdf>`__
session blob defined in the SEV API spec. See SEV spec LAUNCH_START section
for the session blob format.
+
+Some modern AMD processors support Secure Encrypted Virtualization with Secure
+Nested Paging enhancement, also known as SEV-SNP. :since:`Since 10.5.0` To
+enable it ``<launchSecurity type='sev-snp'>`` should be used. It shares
some
+attributes and elements with ``type='sev'`` but differs in others. Example
configuration:
+
+::
+
+ <domain>
+ ...
+ <launchSecurity type='sev-snp' authorKey='yes'
vcek='no'>
+ <cbitpos>47</cbitpos>
+ <reducedPhysBits>1</reducedPhysBits>
+ <policy>0x00030000</policy>
+ <guestVisibleWorkarounds>...</guestVisibleWorkarounds>
+ <idBlock>...</idBlock>
+ <idAuth>...</idAuth>
+ <hostData>.../hostData>
+ </launchSecurity>
+ ...
+ </domain>
+
+The ``<launchSecurity/>`` element accepts the following attributes:
+
+``kernelHashes``
+ The optional ``kernelHashes`` attribute indicates whether the
+ hashes of the kernel, ramdisk and command line should be included
+ in the measurement done by the firmware. This is only valid if
+ using direct kernel boot.
+
+``authorKey``
+ The optional ``authorKey`` attribute indicates whether ``<idAuth/>`` element
+ contains the 'AUTHOR_KEY' field defined SEV-SNP firmware ABI.
+
+``vcek``
+ The optional ``vcek`` attribute indicates whether the guest is allowed to
+ chose between VLEK (Versioned Loaded Endorsement Key) or VCEK (Versioned
+ Chip Endorsement Key) when requesting attestation reports from firmware.
+ Set this to ``no`` to disable the use of VCEK.
+
+Aforementioned SEV-SNP firmware ABI can be found here:
+`<https://www.amd.com/system/files/TechDocs/56860.pdf>`__
+
+The ``<launchSecurity/>`` element then accepts the following child elements:
+
+``cbitpos``
+ The required ``cbitpos`` element provides the C-bit (aka encryption bit)
+ location in guest page table entry. The value of ``cbitpos`` is hypervisor
+ dependent and can be obtained through the ``sev`` element from the domain
+ capabilities.
+``reducedPhysBits``
+ The required ``reducedPhysBits`` element provides the physical address bit
+ reduction. Similar to ``cbitpos`` the value of ``reduced-phys-bit`` is
+ hypervisor dependent and can be obtained through the ``sev`` element from the
+ domain capabilities.
+``policy``
+ The required ``policy`` element provides the guest policy which must be
+ maintained by the SEV-SNP firmware. This policy is enforced by the firmware
+ and restricts what configuration and operational commands can be performed
+ on this guest by the hypervisor. The guest policy provided during guest
+ launch is bound to the guest and cannot be changed throughout the lifetime
+ of the guest. The policy is also transmitted during snapshot and migration
+ flows and enforced on the destination platform. The guest policy is a 64bit
+ unsigned number with the fields shown in table (See section `4.3 Guest
+ Policy` in aforementioned firmware ABI specification):
+
+ ======
=========================================================================================
+ Bit(s) Description
+ ======
=========================================================================================
+ 63:25 Reserved. Must be zero.
+ 24 Ciphertext hiding must be enabled when set, otherwise may be enabled or
disabled.
+ 23 Running Average Power Limit (RAPL) must be disabled when set.
+ 22 Require AES 256 XTS for memory encryption when set, otherwise AES 128 XEX may
be allowed.
+ 21 CXL can be populated with devices or memory when set.
+ 20 Guest can be activated only on one socket when set.
+ 19 Debugging is allowed when set.
+ 18 Association with a migration agent is allowed when set.
+ 17 Reserved. Must be set.
+ 16 SMT is allowed.
+ 15:8 The minimum ABI major version required for this guest to run.
+ 7:0 The minimum ABI minor version required for this guest to run.
+ ======
=========================================================================================
+
+ The default value is hypervisor dependant and QEMU defaults to value 0x30000
+ meaning no minimum ABI major/minor version is required and SMT is allowed.
+
+``guestVisibleWorkarounds``
+ The optional ``guestVisibleWorkarounds`` element is a 16-byte,
+ base64-encoded blob to report hypervisor-defined workarounds, corresponding
+ to the 'GOSVW' parameter of the SNP_LAUNCH_START command defined in the
+ SEV-SNP firmware ABI.
+
+``idBlock``
+ The optional ``idBlock`` element is a 96-byte, base64-encoded blob to
+ provide the 'ID Block' structure for the SNP_LAUNCH_FINISH command defined
+ in the SEV-SNP firmware ABI.
+
+``idAuth``
+ The optional ``idAuth`` element is a 4096-byte, base64-encoded blob to
+ provide the 'ID Authentication Information Structure' for the
+ SNP_LAUNCH_FINISH command defined in the SEV-SNP firmware ABI.
+
+``hostData``
+ The optional ``hostData`` element is a 32-byte, base64-encoded, user-defined
+ blob to provide to the guest, as documented for the 'HOST_DATA' parameter of
+ the SNP_LAUNCH_FINISH command in the SEV-SNP firmware ABI.
+
+
Example configs
===============
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 102a011be8..cb1154b23f 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1509,6 +1509,7 @@ VIR_ENUM_IMPL(virDomainLaunchSecurity,
VIR_DOMAIN_LAUNCH_SECURITY_LAST,
"",
"sev",
+ "sev-snp",
"s390-pv",
);
@@ -3835,6 +3836,12 @@ virDomainSecDefFree(virDomainSecDef *def)
g_free(def->data.sev.dh_cert);
g_free(def->data.sev.session);
break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP:
+ g_free(def->data.sev_snp.guest_visible_workarounds);
+ g_free(def->data.sev_snp.id_block);
+ g_free(def->data.sev_snp.id_auth);
+ g_free(def->data.sev_snp.host_data);
+ break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
@@ -13676,6 +13683,36 @@ virDomainSEVDefParseXML(virDomainSEVDef *def,
}
+static int
+virDomainSEVSNPDefParseXML(virDomainSEVSNPDef *def,
+ xmlXPathContextPtr ctxt)
+{
+ if (virDomainSEVCommonDefParseXML(&def->common, ctxt) < 0)
+ return -1;
+
+ if (virXMLPropTristateBool(ctxt->node, "authorKey", VIR_XML_PROP_NONE,
+ &def->author_key) < 0)
+ return -1;
+
+ if (virXMLPropTristateBool(ctxt->node, "vcek", VIR_XML_PROP_NONE,
+ &def->vcek) < 0)
+ return -1;
+
+ if (virXPathULongLongBase("string(./policy)", ctxt, 16,
&def->policy) < 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("failed to get launch security policy"));
+ return -1;
+ }
+
+ def->guest_visible_workarounds =
virXPathString("string(./guestVisibleWorkarounds)", ctxt);
+ def->id_block = virXPathString("string(./idBlock)", ctxt);
+ def->id_auth = virXPathString("string(./idAuth)", ctxt);
+ def->host_data = virXPathString("string(./hostData)", ctxt);
+
+ return 0;
+}
+
+
static virDomainSecDef *
virDomainSecDefParseXML(xmlNodePtr lsecNode,
xmlXPathContextPtr ctxt)
@@ -13695,6 +13732,10 @@ virDomainSecDefParseXML(xmlNodePtr lsecNode,
if (virDomainSEVDefParseXML(&sec->data.sev, ctxt) < 0)
return NULL;
break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP:
+ if (virDomainSEVSNPDefParseXML(&sec->data.sev_snp, ctxt) < 0)
+ return NULL;
+ break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
break;
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
@@ -26683,6 +26724,34 @@ virDomainSEVDefFormat(virBuffer *attrBuf,
}
+static void
+virDomainSEVSNPDefFormat(virBuffer *attrBuf,
+ virBuffer *childBuf,
+ virDomainSEVSNPDef *def)
+{
+ virDomainSEVCommonDefFormat(attrBuf, childBuf, &def->common);
+
+ if (def->author_key != VIR_TRISTATE_BOOL_ABSENT) {
+ virBufferAsprintf(attrBuf, " authorKey='%s'",
+ virTristateBoolTypeToString(def->author_key));
+ }
+
+ if (def->vcek != VIR_TRISTATE_BOOL_ABSENT) {
+ virBufferAsprintf(attrBuf, " vcek='%s'",
+ virTristateBoolTypeToString(def->vcek));
+ }
+
+ virBufferAsprintf(childBuf, "<policy>0x%08llx</policy>\n",
def->policy);
+
+ virBufferEscapeString(childBuf,
+
"<guestVisibleWorkarounds>%s</guestVisibleWorkarounds>\n",
+ def->guest_visible_workarounds);
+ virBufferEscapeString(childBuf, "<idBlock>%s</idBlock>\n",
def->id_block);
+ virBufferEscapeString(childBuf, "<idAuth>%s</idAuth>\n",
def->id_auth);
+ virBufferEscapeString(childBuf, "<hostData>%s</hostData>\n",
def->host_data);
+}
+
+
static void
virDomainSecDefFormat(virBuffer *buf, virDomainSecDef *sec)
{
@@ -26700,6 +26769,10 @@ virDomainSecDefFormat(virBuffer *buf, virDomainSecDef *sec)
virDomainSEVDefFormat(&attrBuf, &childBuf, &sec->data.sev);
break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP:
+ virDomainSEVSNPDefFormat(&attrBuf, &childBuf,
&sec->data.sev_snp);
+ break;
+
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
break;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index c6c3c2e2a5..2818a9f1f5 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2860,6 +2860,7 @@ struct _virDomainKeyWrapDef {
typedef enum {
VIR_DOMAIN_LAUNCH_SECURITY_NONE,
VIR_DOMAIN_LAUNCH_SECURITY_SEV,
+ VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP,
VIR_DOMAIN_LAUNCH_SECURITY_PV,
VIR_DOMAIN_LAUNCH_SECURITY_LAST,
@@ -2882,10 +2883,24 @@ struct _virDomainSEVDef {
unsigned int policy;
};
+
+struct _virDomainSEVSNPDef {
+ virDomainSEVCommonDef common;
+ unsigned long long policy;
+ char *guest_visible_workarounds;
+ char *id_block;
+ char *id_auth;
+ char *host_data;
+ virTristateBool author_key;
+ virTristateBool vcek;
+};
+
+
struct _virDomainSecDef {
virDomainLaunchSecurity sectype;
union {
virDomainSEVDef sev;
+ virDomainSEVSNPDef sev_snp;
} data;
};
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 395e036e8f..0661caef68 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -1800,6 +1800,47 @@ virDomainDefValidateIOThreads(const virDomainDef *def)
}
+#define CHECK_BASE64_LEN(val, elemName, exp_len) \
+{ \
+ size_t len; \
+ g_autofree unsigned char *tmp = NULL; \
+ if (val && (tmp = g_base64_decode(val, &len)) && len != exp_len)
{ \
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \
+ _("Unexpected length of '%1$s', expected %2$u got
%3$zu"), \
+ elemName, exp_len, len); \
+ return -1; \
+ } \
+}
+
+static int
+virDomainDefLaunchSecurityValidate(const virDomainDef *def)
+{
+ virDomainSEVSNPDef *sev_snp;
+
+ if (!def->sec)
+ return 0;
+
+ switch (def->sec->sectype) {
+ case VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP:
+ sev_snp = &def->sec->data.sev_snp;
+
+ CHECK_BASE64_LEN(sev_snp->guest_visible_workarounds,
"guestVisibleWorkarounds", 16);
+ CHECK_BASE64_LEN(sev_snp->id_block, "idBlock", 96);
+ CHECK_BASE64_LEN(sev_snp->id_auth, "idAuth", 4096);
+ CHECK_BASE64_LEN(sev_snp->host_data, "hostData", 32);
+ break;
+
+ case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
+ case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
+ case VIR_DOMAIN_LAUNCH_SECURITY_PV:
+ case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
+ }
+
+ return 0;
+}
+
+#undef CHECK_BASE64_LEN
+
static int
virDomainDefValidateInternal(const virDomainDef *def,
virDomainXMLOption *xmlopt)
@@ -1855,6 +1896,9 @@ virDomainDefValidateInternal(const virDomainDef *def,
if (virDomainDefValidateIOThreads(def) < 0)
return -1;
+ if (virDomainDefLaunchSecurityValidate(def) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index 9a7649df1c..844a931deb 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -515,6 +515,9 @@
<group>
<ref name="launchSecuritySEV"/>
</group>
+ <group>
+ <ref name="launchSecuritySEVSNP"/>
+ </group>
<group>
<attribute name="type">
<value>s390-pv</value>
@@ -569,6 +572,52 @@
</interleave>
</define>
+ <define name="launchSecuritySEVSNP">
+ <attribute name="type">
+ <value>sev-snp</value>
+ </attribute>
+ <optional>
+ <attribute name="kernelHashes">
+ <ref name="virYesNo"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="authorKey">
+ <ref name="virYesNo"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="vcek">
+ <ref name="virYesNo"/>
+ </attribute>
+ </optional>
+ <interleave>
+ <ref name="launchSecuritySEVCommon"/>
+ <element name="policy">
+ <ref name="hexuint"/>
+ </element>
+ <optional>
+ <element name="guestVisibleWorkarounds">
+ <data type="string"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="idBlock">
+ <data type="string"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="idAuth">
+ <data type="string"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="hostData">
+ <data type="string"/>
+ </element>
+ </optional>
+ </interleave>
+ </define>
<!--
Enable or disable perf events for the domain. For each
of the events the following rules apply:
diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h
index 34bb1e262f..d8e7c5278c 100644
--- a/src/conf/virconftypes.h
+++ b/src/conf/virconftypes.h
@@ -214,6 +214,8 @@ typedef struct _virDomainSEVCommonDef virDomainSEVCommonDef;
typedef struct _virDomainSEVDef virDomainSEVDef;
+typedef struct _virDomainSEVSNPDef virDomainSEVSNPDef;
+
typedef struct _virDomainSecDef virDomainSecDef;
typedef struct _virDomainShmemDef virDomainShmemDef;
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 9e559c7c4f..23b7e6b4e8 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -848,6 +848,7 @@ qemuSetupDevicesCgroup(virDomainObj *vm)
if (vm->def->sec) {
switch (vm->def->sec->sectype) {
case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
+ case VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP:
if (qemuSetupSEVCgroup(vm) < 0)
return -1;
break;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 1879fa608c..8d83417bb6 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7062,6 +7062,8 @@ qemuBuildMachineCommandLine(virCommand *cmd,
virBufferAddLit(&buf, ",memory-encryption=lsec0");
}
break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP:
+ break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
virBufferAddLit(&buf, ",confidential-guest-support=lsec0");
break;
@@ -9781,6 +9783,8 @@ qemuBuildSecCommandLine(virDomainObj *vm, virCommand *cmd,
case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
return qemuBuildSEVCommandLine(vm, cmd, &sec->data.sev);
break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP:
+ break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
return qemuBuildPVCommandLine(vm, cmd);
break;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 1a71857147..fc1704f4fc 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -19128,6 +19128,7 @@ qemuDomainGetLaunchSecurityInfo(virDomainPtr domain,
switch (vm->def->sec->sectype) {
case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
+ case VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP:
if (qemuDomainGetSEVInfo(vm, params, nparams, flags) < 0)
goto cleanup;
break;
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 8946dc1aa5..262eeecc5c 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -1338,6 +1338,9 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
return false;
}
break;
+
+ case VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP:
+ break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
break;
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c
index fb7c9329dd..bbe3d5a1f7 100644
--- a/src/qemu/qemu_namespace.c
+++ b/src/qemu/qemu_namespace.c
@@ -653,6 +653,7 @@ qemuDomainSetupLaunchSecurity(virDomainObj *vm,
switch (sec->sectype) {
case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
+ case VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP:
VIR_DEBUG("Setting up launch security for SEV");
*paths = g_slist_prepend(*paths, g_strdup(QEMU_DEV_SEV));
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index d14975180a..b9b6ccf1de 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -6744,6 +6744,7 @@ qemuProcessPrepareDomain(virQEMUDriver *driver,
if (vm->def->sec) {
switch (vm->def->sec->sectype) {
case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
+ case VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP:
VIR_DEBUG("Updating SEV platform info");
if (qemuProcessUpdateSEVInfo(vm) < 0)
return -1;
@@ -6818,6 +6819,8 @@ qemuProcessPrepareLaunchSecurityGuestInput(virDomainObj *vm)
switch (sec->sectype) {
case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
return qemuProcessPrepareSEVGuestInput(vm);
+ case VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP:
+ break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
return 0;
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 05ee477456..3cfcceafc9 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -1325,6 +1325,15 @@ qemuValidateDomainDef(const virDomainDef *def,
return -1;
}
break;
+
+ case VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP:
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_SNP_GUEST)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("SEV SNP launch security is not supported with this
QEMU binary"));
+ return -1;
+ }
+ break;
+
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_CONFIDENTAL_GUEST_SUPPORT)
||
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_S390_PV_GUEST)) {
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index d0864313c1..1a3b51a298 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -1954,6 +1954,7 @@ virSecurityDACRestoreAllLabel(virSecurityManager *mgr,
if (def->sec) {
switch (def->sec->sectype) {
case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
+ case VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP:
if (virSecurityDACRestoreSEVLabel(mgr, def) < 0)
rc = -1;
break;
@@ -2187,6 +2188,7 @@ virSecurityDACSetAllLabel(virSecurityManager *mgr,
if (def->sec) {
switch (def->sec->sectype) {
case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
+ case VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP:
if (virSecurityDACSetSEVLabel(mgr, def) < 0)
return -1;
break;
diff --git a/tests/qemuxmlconfdata/launch-security-sev-snp.x86_64-latest.args
b/tests/qemuxmlconfdata/launch-security-sev-snp.x86_64-latest.args
new file mode 100644
index 0000000000..37ac58edb8
--- /dev/null
+++ b/tests/qemuxmlconfdata/launch-security-sev-snp.x86_64-latest.args
@@ -0,0 +1,34 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \
+XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \
+XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object
'{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}'
\
+-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
+-accel kvm \
+-cpu qemu64 \
+-m size=219136k \
+-object
'{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}'
\
+-overcommit mem-lock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-boot strict=on \
+-device
'{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}'
\
+-blockdev
'{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","read-only":false}'
\
+-device
'{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-storage","id":"ide0-0-0","bootindex":1}'
\
+-audiodev
'{"id":"audio1","driver":"none"}' \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxmlconfdata/launch-security-sev-snp.x86_64-latest.xml
b/tests/qemuxmlconfdata/launch-security-sev-snp.x86_64-latest.xml
new file mode 120000
index 0000000000..0159cc057b
--- /dev/null
+++ b/tests/qemuxmlconfdata/launch-security-sev-snp.x86_64-latest.xml
@@ -0,0 +1 @@
+launch-security-sev-snp.xml
\ No newline at end of file
diff --git a/tests/qemuxmlconfdata/launch-security-sev-snp.xml
b/tests/qemuxmlconfdata/launch-security-sev-snp.xml
new file mode 100644
index 0000000000..b277d7de1b
--- /dev/null
+++ b/tests/qemuxmlconfdata/launch-security-sev-snp.xml
@@ -0,0 +1,47 @@
+<domain type='kvm'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <cpu mode='custom' match='exact' check='none'>
+ <model fallback='forbid'>qemu64</model>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0' model='piix3-uhci'>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x01' function='0x2'/>
+ </controller>
+ <controller type='ide' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x01' function='0x1'/>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <audio id='1' type='none'/>
+ <memballoon model='none'/>
+ </devices>
+ <launchSecurity type='sev-snp' authorKey='yes'
vcek='no'>
+ <cbitpos>47</cbitpos>
+ <reducedPhysBits>1</reducedPhysBits>
+ <policy>0x00030000</policy>
+
<guestVisibleWorkarounds>bGlidmlydGxpYnZpcnRsaQ==</guestVisibleWorkarounds>
+
<idBlock>bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZp</idBlock>
+
<idAuth>bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnZpcnRsaWJ2aXJ0bA==</idAuth>
+ <hostData>bGlidmlydGxpYnZpcnRsaWJ2aXJ0bGlidmlydGxpYnY=</hostData>
+ </launchSecurity>
+</domain>
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index 5700ea314f..6733e73479 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -2849,6 +2849,8 @@ mymain(void)
QEMU_CAPS_SEV_GUEST,
QEMU_CAPS_LAST);
+ DO_TEST_CAPS_ARCH_LATEST("launch-security-sev-snp", "x86_64");
+
DO_TEST_CAPS_ARCH_LATEST("launch-security-s390-pv", "s390x");
DO_TEST_CAPS_LATEST("vhost-user-fs-fd-memory");
--
2.44.2