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 <brijesh.singh@amd.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
This commit is contained in:
Brijesh Singh 2018-06-08 09:40:52 -05:00 committed by Erik Skultety
parent d4005609f3
commit 5dca09c170
5 changed files with 108 additions and 1 deletions

View File

@ -435,6 +435,10 @@
&lt;/gic&gt;
&lt;vmcoreinfo supported='yes'/&gt;
&lt;genid supported='yes'/&gt;
&lt;sev&gt;
&lt;cbitpos&gt;47&lt;/cbitpos&gt;
&lt;reduced-phys-bits&gt;1&lt;/reduced-phys-bits&gt;
&lt;/sev&gt;
&lt;/features&gt;
&lt;/domainCapabilities&gt;
</pre>
@ -467,5 +471,31 @@
<p>Reports whether the genid feature can be used by the domain.</p>
<h4><a id="elementsSEV">SEV capabilities</a></h4>
<p>AMD Secure Encrypted Virtualization (SEV) capabilities are exposed under
the <code>sev</code> 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.</p>
<p>
For more details on SEV feature see:
<a href="https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf">
SEV API spec</a> and <a href="http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf">
SEV White Paper</a>
</p>
<dl>
<dt><code>cbitpos</code></dt>
<dd>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.</dd>
<dt><code>reduced-phys-bits</code></dt>
<dd>When memory encryption is enabled, we lose certain bits in physical
address space. The number of bits we lose is hypervisor dependent.</dd>
</dl>
</body>
</html>

View File

@ -185,6 +185,9 @@
<ref name='gic'/>
<ref name='vmcoreinfo'/>
<ref name='vmgenid'/>
<optional>
<ref name='sev'/>
</optional>
</interleave>
</element>
</define>
@ -208,6 +211,17 @@
</element>
</define>
<define name='sev'>
<element name='sev'>
<element name='cbitpos'>
<data type='unsignedInt'/>
</element>
<element name='reduced-phys-bits'>
<data type='unsignedInt'/>
</element>
</element>
</define>
<define name='value'>
<zeroOrMore>
<element name='value'>

View File

@ -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, "<sev supported='yes'>\n");
virBufferAdjustIndent(buf, 2);
virBufferAsprintf(buf, "<cbitpos>%d</cbitpos>\n", sev->cbitpos);
virBufferAsprintf(buf, "<reduced-phys-bits>%d</reduced-phys-bits>\n",
sev->reduced_phys_bits);
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</sev>\n");
}
char *
virDomainCapsFormat(virDomainCapsPtr const caps)
@ -600,6 +617,7 @@ virDomainCapsFormat(virDomainCapsPtr const caps)
virBufferAsprintf(&buf, "<genid supported='%s'/>\n",
caps->genid ? "yes" : "no");
virDomainCapsFeatureSEVFormat(&buf, caps->sev);
virBufferAdjustIndent(&buf, -2);
virBufferAddLit(&buf, "</features>\n");

View File

@ -169,6 +169,7 @@ struct _virDomainCaps {
virDomainCapsFeatureGIC gic;
bool vmcoreinfo;
bool genid;
virSEVCapabilityPtr sev;
/* add new domain features here */
};

View File

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