[libvirt] [PATCH 2/4] qemu: introduce SEV feature in hypervisor capabilities

Brijesh Singh brijesh.singh at amd.com
Tue Feb 27 16:29:26 UTC 2018



On 02/27/2018 02:15 AM, Peter Krempa wrote:
> On Mon, Feb 26, 2018 at 11:53:34 -0600, Brijesh Singh wrote:
>> 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
>> 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 at amd.com>
>> ---
>>   docs/formatdomaincaps.html.in  | 31 +++++++++++++++++++++++++++++++
>>   docs/schemas/domaincaps.rng    | 10 ++++++++++
>>   src/conf/domain_capabilities.c | 19 +++++++++++++++++++
>>   src/conf/domain_capabilities.h | 11 +++++++++++
>>   src/qemu/qemu_capabilities.c   | 41 ++++++++++++++++++++++++++++++++++++++++-
>>   5 files changed, 111 insertions(+), 1 deletion(-)
>>
>> diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in
>> index 6bfcaf61caae..8f833477772c 100644
>> --- a/docs/formatdomaincaps.html.in
>> +++ b/docs/formatdomaincaps.html.in
>> @@ -417,6 +417,12 @@
>>           <value>3</value>
>>         </enum>
>>       </gic>
>> +    <sev supported='yes'>
>> +      <pdh> </pdh>
>> +      <cert-chain> </cert-chain>
>> +      <cbitpos> </cbitpos>
>> +      <reduced-phys-bits> </reduced-phys-bits>
>> +    </sev>
>>     </features>
>>   </domainCapabilities>
>>   </pre>
>> @@ -441,5 +447,30 @@
>>         <code>gic</code> element.</dd>
>>       </dl>
>>   
>> +    <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.
> 
> So is it likely that anything similar will be introduced by other
> manufacturers too? I'd like to avoid having these to be per-manufacturer
> specific. Can we change this to be more generic?

How about something like:

<memory-encryption type='sev'>
  <pdh> ..</pdh>
  ....
  ....
</memory-encryption>

if other manufacture implements memory encryption then we can introduce 
a new type to handle new memory encryption feature. The inputs to the 
memory encryption type is going to be vendor-specific.



> 
>> +    </p>
>> +
>> +    <dl>
>> +      <dt><code>pdh</code></dt>
>> +      <dd>Platform diffie-hellman key, which can be exported to remote entities
>> +      which wish to establish a secure transport context with the SEV platform
>> +      in order to transmit data securely. The key is encoded in base64</dd>
>> +      <dt><code>cert-chain</code></dt>
>> +      <dd> Platform certificate chain -- which includes platform endorsement key
>> +      (PEK), owners certificate authory (OCA) and chip endorsement key (CEK).
>> +      The certificate chain is encoded in base64.</dd>
>> +      <dt><code>cbitpos</code></dt>
>> +      <dd> C-bit position in page-table entry</dd>
>> +      <dt><code>reduced-phys-bits</code></dt>
>> +      <dd> Physical Address bit reduction</dd>
> 
> So these really are not clear from this description.
> 

I will add some more details to clarify this.


>> +    </dl>
>> +
>>     </body>
>>   </html>
>> diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng
>> index 39053181eb9a..6ce8d296c703 100644
>> --- a/docs/schemas/domaincaps.rng
>> +++ b/docs/schemas/domaincaps.rng
>> @@ -184,6 +184,16 @@
>>       </element>
>>     </define>
>>   
>> +  <define name='sev'>
>> +    <element name='sev'>
>> +      <ref name='supported'/>
>> +      <ref name='pdh'/>
>> +      <ref name='cert-chain'/>
>> +      <ref name='cbitpos'/>
>> +      <ref name='reduced-phys-bits'/>
> 
> You are not really defining these names anywhere. This will most
> probably break the schema test.
> 

I must admit that I am new to libvirt hence need some help. Sorry I am 
not able to follow your this comment. Do I need to update domaincap.rng 
or not ? If yes, where do I need to define the names so that we don't 
break the schema test. Any tips is appreciated. thanks



>> +    </element>
>> +  </define>
>> +
>>     <define name='value'>
>>       <zeroOrMore>
>>         <element name='value'>
>> diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
>> index f7d9be50f82d..6a7a30877042 100644
>> --- a/src/conf/domain_capabilities.c
>> +++ b/src/conf/domain_capabilities.c
>> @@ -549,6 +549,24 @@ virDomainCapsFeatureGICFormat(virBufferPtr buf,
>>       FORMAT_EPILOGUE(gic);
>>   }
>>   
>> +static void
>> +virDomainCapsFeatureSEVFormat(virBufferPtr buf,
>> +                              virDomainCapsFeatureSEVPtr const sev)
>> +{
>> +    FORMAT_PROLOGUE(sev);
> 
> If the feature is not supported, you should not format an empty element
> here. Just skip it completely.


OK, actually I was taking similar approach as 'gic' support -- which 
leaves the empty element in case if gic is not present. Will now take 
your recommendation and skip it completely.


> 
>> +
>> +    if (sev->supported) {
>> +        virBufferAsprintf(buf, "<cbitpos>%d</cbitpos>\n", sev->cbitpos);
>> +        virBufferAsprintf(buf, "<reduced-phys-bits>%d</reduced-phys-bits>\n",
>> +                          sev->reduced_phys_bits);
>> +        virBufferAsprintf(buf, "<pdh>%s</pdh>\n", sev->pdh);
>> +        virBufferAsprintf(buf, "<cert-chain>%s</cert-chain>\n",
>> +                          sev->cert_chain);
>> +    }
>> +
>> +    FORMAT_EPILOGUE(sev);
>> +}
>> +
>>   
>>   char *
>>   virDomainCapsFormat(virDomainCapsPtr const caps)
>> @@ -587,6 +605,7 @@ virDomainCapsFormat(virDomainCapsPtr const caps)
>>       virBufferAdjustIndent(&buf, 2);
>>   
>>       virDomainCapsFeatureGICFormat(&buf, &caps->gic);
>> +    virDomainCapsFeatureSEVFormat(&buf, &caps->sev);
>>   
>>       virBufferAdjustIndent(&buf, -2);
>>       virBufferAddLit(&buf, "</features>\n");
>> diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
>> index e13a7fd6ba1b..aed5ec28e9cc 100644
>> --- a/src/conf/domain_capabilities.h
>> +++ b/src/conf/domain_capabilities.h
>> @@ -102,6 +102,16 @@ struct _virDomainCapsFeatureGIC {
>>       virDomainCapsEnum version; /* Info about virGICVersion */
>>   };
>>   
>> +typedef struct _virDomainCapsFeatureSEV virDomainCapsFeatureSEV;
>> +typedef virDomainCapsFeatureSEV *virDomainCapsFeatureSEVPtr;
>> +struct _virDomainCapsFeatureSEV {
>> +    bool supported;
>> +    char *pdh;  /* host platform-diffie hellman key */
>> +    char *cert_chain;  /* PDH certificate chain */
>> +    int cbitpos;
>> +    int reduced_phys_bits;
> 
> This structure is basically the same as the one in the qemu driver.
> Can't you just use this one in the qemu driver?


Yes they are same structure, will reuse it.



> 
>> +};
>> +
>>   typedef enum {
>>       VIR_DOMCAPS_CPU_USABLE_UNKNOWN,
>>       VIR_DOMCAPS_CPU_USABLE_YES,
>> @@ -171,6 +181,7 @@ struct _virDomainCaps {
>>       /* add new domain devices here */
>>   
>>       virDomainCapsFeatureGIC gic;
>> +    virDomainCapsFeatureSEV sev;
>>       /* add new domain features here */
>>   };
>>   
>> diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
>> index 2c680528deb8..ee8c542679eb 100644
>> --- a/src/qemu/qemu_capabilities.c
>> +++ b/src/qemu/qemu_capabilities.c
>> @@ -5880,6 +5880,44 @@ virQEMUCapsSupportsGICVersion(virQEMUCapsPtr qemuCaps,
>>       return false;
>>   }
>>   
>> +/**
>> + * 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.
> 
> This function would not be necessary in that case.
> 
>> + *
>> + * Returns: 0 on success, <0 on failure
>> + */
>> +static int
>> +virQEMUCapsFillDomainFeatureSEVCaps(virQEMUCapsPtr qemuCaps,
>> +                                    virDomainCapsPtr domCaps)
>> +{
>> +    virDomainCapsFeatureSEVPtr sev = &domCaps->sev;
>> +    virSEVCapability *cap = qemuCaps->sevCapabilities;
>> +
>> +    if (!cap)
>> +        return 0;
>> +
>> +    sev->supported = cap->sev;
>> +
>> +    if (VIR_STRDUP(sev->pdh, cap->pdh) < 0)
>> +        goto failed;
>> +
>> +    if (VIR_STRDUP(sev->cert_chain, cap->cert_chain) < 0)
>> +        goto failed;
>> +
>> +    sev->cbitpos = cap->cbitpos;
>> +    sev->reduced_phys_bits = cap->reduced_phys_bits;
>> +
>> +    return 0;
>> +failed:
>> +    sev->supported = false;
>> +    return 0;
> 
> So why does this function return anything? Also we prefer the 'error'
> label in this case.
> 

The function was modeled after gic feature which always returns 0 
regardless whether gic is available or not. Similarly we don't want to 
fail just because SEV feature is not available. I can look into 
improving this.




More information about the libvir-list mailing list