From 5dca09c170e26d572cab9b7b80a4347d4dc1907e Mon Sep 17 00:00:00 2001 From: Brijesh Singh Date: Fri, 8 Jun 2018 09:40:52 -0500 Subject: [PATCH] conf: Expose SEV feature in domain capabilities Extend hypervisor capabilities to include sev feature. When available, hypervisor supports launching an encrypted VM on AMD platform. The sev feature tag provides additional details like Platform Diffie-Hellman (PDH) key and certificate chain which can be used by the guest owner to establish a cryptographic session with the SEV firmware to negotiate keys used for attestation or to provide secret during launch. Signed-off-by: Brijesh Singh Reviewed-by: Erik Skultety --- docs/formatdomaincaps.html.in | 30 ++++++++++++++++++++++ docs/schemas/domaincaps.rng | 14 +++++++++++ src/conf/domain_capabilities.c | 18 +++++++++++++ src/conf/domain_capabilities.h | 1 + src/qemu/qemu_capabilities.c | 46 +++++++++++++++++++++++++++++++++- 5 files changed, 108 insertions(+), 1 deletion(-) diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in index e0814cb9a2..6be553a114 100644 --- a/docs/formatdomaincaps.html.in +++ b/docs/formatdomaincaps.html.in @@ -435,6 +435,10 @@ </gic> <vmcoreinfo supported='yes'/> <genid supported='yes'/> + <sev> + <cbitpos>47</cbitpos> + <reduced-phys-bits>1</reduced-phys-bits> + </sev> </features> </domainCapabilities> @@ -467,5 +471,31 @@

Reports whether the genid feature can be used by the domain.

+

SEV capabilities

+ +

AMD Secure Encrypted Virtualization (SEV) capabilities are exposed under + the sev element. + SEV is an extension to the AMD-V architecture which supports running + virtual machines (VMs) under the control of a hypervisor. When supported, + guest owner can create a VM whose memory contents will be transparently + encrypted with a key unique to that VM.

+ +

+ For more details on SEV feature see: + + SEV API spec and + SEV White Paper +

+ +
+
cbitpos
+
When memory encryption is enabled, one of the physical address bits + (aka the C-bit) is utilized to mark if a memory page is protected. The + C-bit position is Hypervisor dependent.
+
reduced-phys-bits
+
When memory encryption is enabled, we lose certain bits in physical + address space. The number of bits we lose is hypervisor dependent.
+
+ diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng index 5ceabb0a80..1d0a2e17aa 100644 --- a/docs/schemas/domaincaps.rng +++ b/docs/schemas/domaincaps.rng @@ -185,6 +185,9 @@ + + + @@ -208,6 +211,17 @@ + + + + + + + + + + + diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index 3589777524..ec469bfb9a 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -88,6 +88,7 @@ virDomainCapsDispose(void *obj) VIR_FREE(caps->machine); virObjectUnref(caps->cpu.custom); virCPUDefFree(caps->cpu.hostModel); + virSEVCapabilitiesFree(caps->sev); virDomainCapsStringValuesFree(&caps->os.loader.values); } @@ -554,6 +555,22 @@ virDomainCapsFeatureGICFormat(virBufferPtr buf, FORMAT_EPILOGUE(gic); } +static void +virDomainCapsFeatureSEVFormat(virBufferPtr buf, + virSEVCapabilityPtr const sev) +{ + if (!sev) + return; + + virBufferAddLit(buf, "\n"); + virBufferAdjustIndent(buf, 2); + virBufferAsprintf(buf, "%d\n", sev->cbitpos); + virBufferAsprintf(buf, "%d\n", + sev->reduced_phys_bits); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); +} + char * virDomainCapsFormat(virDomainCapsPtr const caps) @@ -600,6 +617,7 @@ virDomainCapsFormat(virDomainCapsPtr const caps) virBufferAsprintf(&buf, "\n", caps->genid ? "yes" : "no"); + virDomainCapsFeatureSEVFormat(&buf, caps->sev); virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "\n"); diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index 56c1903cf4..755de1365f 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -169,6 +169,7 @@ struct _virDomainCaps { virDomainCapsFeatureGIC gic; bool vmcoreinfo; bool genid; + virSEVCapabilityPtr sev; /* add new domain features here */ }; diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 8b3ffe1afe..1803ed9875 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -5157,6 +5157,48 @@ virQEMUCapsFillDomainFeatureGICCaps(virQEMUCapsPtr qemuCaps, } +/** + * virQEMUCapsFillDomainFeatureSEVCaps: + * @qemuCaps: QEMU capabilities + * @domCaps: domain capabilities + * + * Take the information about SEV capabilities that has been obtained + * using the 'query-sev-capabilities' QMP command and stored in @qemuCaps + * and convert it to a form suitable for @domCaps. + * + * Returns: 0 on success, -1 on failure + */ +static int +virQEMUCapsFillDomainFeatureSEVCaps(virQEMUCapsPtr qemuCaps, + virDomainCapsPtr domCaps) +{ + virSEVCapability *sev; + virSEVCapability *cap = qemuCaps->sevCapabilities; + int ret = -1; + + if (!cap) + return 0; + + if (VIR_ALLOC(sev) < 0) + return -1; + + if (VIR_STRDUP(sev->pdh, cap->pdh) < 0) + goto cleanup; + + if (VIR_STRDUP(sev->cert_chain, cap->cert_chain) < 0) + goto cleanup; + + sev->cbitpos = cap->cbitpos; + sev->reduced_phys_bits = cap->reduced_phys_bits; + VIR_STEAL_PTR(domCaps->sev, sev); + + ret = 0; + cleanup: + virSEVCapabilitiesFree(sev); + return ret; +} + + int virQEMUCapsFillDomainCaps(virCapsPtr caps, virDomainCapsPtr domCaps, @@ -5194,8 +5236,10 @@ virQEMUCapsFillDomainCaps(virCapsPtr caps, virQEMUCapsFillDomainDeviceGraphicsCaps(qemuCaps, graphics) < 0 || virQEMUCapsFillDomainDeviceVideoCaps(qemuCaps, video) < 0 || virQEMUCapsFillDomainDeviceHostdevCaps(qemuCaps, hostdev) < 0 || - virQEMUCapsFillDomainFeatureGICCaps(qemuCaps, domCaps) < 0) + virQEMUCapsFillDomainFeatureGICCaps(qemuCaps, domCaps) < 0 || + virQEMUCapsFillDomainFeatureSEVCaps(qemuCaps, domCaps) < 0) return -1; + return 0; }