Changeset
docs/drvqemu.html.in                               |   3 +-
docs/formatdomain.html.in                          | 115 ++++++++++++++++
docs/formatdomaincaps.html.in                      |  30 ++++
docs/schemas/domaincaps.rng                        |  14 ++
docs/schemas/domaincommon.rng                      |  37 +++++
include/libvirt/libvirt-domain.h                   |  17 +++
include/libvirt/libvirt-host.h                     |  42 ++++++
src/conf/domain_capabilities.c                     |  30 ++++
src/conf/domain_capabilities.h                     |  13 ++
src/conf/domain_conf.c                             | 133 ++++++++++++++++++
src/conf/domain_conf.h                             |  27 ++++
src/driver-hypervisor.h                            |  14 ++
src/libvirt-domain.c                               |  48 +++++++
src/libvirt-host.c                                 |  49 +++++++
src/libvirt_private.syms                           |   1 +
src/libvirt_public.syms                            |   2 +
src/qemu/qemu.conf                                 |   2 +-
src/qemu/qemu_capabilities.c                       |  90 +++++++++++-
src/qemu/qemu_capabilities.h                       |   6 +
src/qemu/qemu_capspriv.h                           |   4 +
src/qemu/qemu_cgroup.c                             |   2 +-
src/qemu/qemu_command.c                            |  41 ++++++
src/qemu/qemu_driver.c                             | 151 +++++++++++++++++++++
src/qemu/qemu_monitor.c                            |  18 +++
src/qemu/qemu_monitor.h                            |   6 +
src/qemu/qemu_monitor_json.c                       | 121 +++++++++++++++++
src/qemu/qemu_monitor_json.h                       |   5 +
src/qemu/qemu_process.c                            |  62 +++++++++
src/qemu/test_libvirtd_qemu.aug.in                 |   1 +
src/remote/remote_daemon_dispatch.c                |  91 +++++++++++++
src/remote/remote_driver.c                         |  80 +++++++++++
src/remote/remote_protocol.x                       |  39 +++++-
src/remote_protocol-structs                        |  23 ++++
tests/genericxml2xmlindata/launch-security-sev.xml |  24 ++++
tests/genericxml2xmltest.c                         |   2 +
.../caps_2.12.0.x86_64.replies                     |  10 ++
tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml  |   3 +-
tests/qemuxml2argvdata/launch-security-sev.args    |  29 ++++
tests/qemuxml2argvdata/launch-security-sev.xml     |  37 +++++
tests/qemuxml2argvtest.c                           |   4 +
40 files changed, 1420 insertions(+), 6 deletions(-)
create mode 100644 tests/genericxml2xmlindata/launch-security-sev.xml
create mode 100644 tests/qemuxml2argvdata/launch-security-sev.args
create mode 100644 tests/qemuxml2argvdata/launch-security-sev.xml
Git apply log
Switched to a new branch '20180608144101.34228-1-brijesh.singh@amd.com'
Applying: qemu: provide support to query the SEV capability
Applying: conf: expose SEV feature in domain capabilities
Applying: libvirt: Introduce virNodeGetSEVInfo public API
Applying: remote: implement the remote protocol for virNodeGetSEVInfo()
Applying: qemu: Implement the driver backend for virNodeGetSEVInfo()
Applying: conf: introduce launch-security element in domain
Applying: qemu/cgroup: add /dev/sev in shared devices list
Applying: qemu: add support to launch SEV guest
Applying: libvirt: Introduce virDomainGetLaunchSecurityInfo public API
Applying: remote: implement the remote protocol for launch security
Applying: qemu: Implement the driver backend for virDomainGetLaunchSecurityInfo
To https://github.com/patchew-project/libvirt
 + c64ef74...7494772 patchew/20180608144101.34228-1-brijesh.singh@amd.com -> patchew/20180608144101.34228-1-brijesh.singh@amd.com (forced update)
Test passed: syntax-check

loading

[libvirt] [PATCH v9 00/11] x86: Secure Encrypted Virtualization (AMD)
Posted by Brijesh Singh, 2 weeks ago
This patch series provides support for launching an encrypted guest using
AMD's new Secure Encrypted  Virtualization (SEV) feature.

SEV is an extension to the AMD-V architecture which supports running
multiple VMs under the control of a hypervisor. When enabled, SEV feature
allows the memory contents of a virtual machine (VM) to be transparently
encrypted with a key unique to the guest VM.

At very high level the flow looks this:

1. mgmt tool calls virConnectGetDomainCapabilities. This returns an XML document
that includes the following

<feature>
...
  <sev supported='yes'>
    <cbitpos> </cbitpos>
    <reduced-phys-bits> </reduced-phys-bits>
  </sev>
</feature>

If <sev> is provided then we indicate that hypervisor is capable of launching
SEV guest. mgmt tool can call virNodeGetSEVCapabilities() to get the additional
informations like PDH and certificate chain etc.

2. (optional) mgmt tool can provide the PDH and Cert-chain to guest owner in case
if guest owner wish to establish a secure connection with SEV firmware to
negotiate a key used for validating the measurement.

3. mgmt tool requests to start a guest calling virCreateXML(), passing \
VIR_DOMAIN_START_PAUSED. The xml would include

<launch-security type='sev'>
  <cbitpos>47</cbitpos> 
  <reduced-phys-bits>1</reduced-phys-bits>
  <policy>0x1</policy>

  (optional)
  <dh-cert> </dh-cert> /* Guest owners Diffie-Hellman key */
  <session> </session> /* Guest owners Session blob */
</launch-security>

4. Libvirt generate the QEMU cli arg to enable the SEV feature, a typical
args looks like this:

# $QEMU ..
-machine memory-encryption=sev0 \
-object sev-guest,id=sev0,dh-cert-file=<file>....

5. Libvirt generates lifecycle VIR_DOMAIN_EVENT_SUSPENDED_PAUSED event

6. mgmt tool gets the VIR_DOMAIN_EVENT_SUSPENDED_PAUSED and calls \
virDomainGetLaunchSecretInfo() to retrieve the measurement of encrypted memory.

7. (optional) mgmt tool can provide the measurement value to guest owner, which can
validate the measurement and gives GO/NO-GO answer. If mgmt tool gets GO then
it resumes the guest otherwise it calls destroy() to kill the guest.

8. mgmt tool resumes the guest

TODO:
* SEV guest require to use DMA apis for the virtio devices. In order to use the DMA
apis the virtio devices must have this tag

<driver iommu=on ats=on>

It is a bit unclear to me where these changes need to go. Do we need to
modify the libvirt to automatically add these when SEV is enabled or
we ask mgmt tool to make sure that it creates XML with right tag to enable
the DMA APIs for virtio devices. I am looking for some suggestions.

Using these patches we have succesfully booted and tested a guest both with and
without SEV enabled.

SEV Firmware API spec is available at:
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf

Changes sicne v8:
* rename qemuGetSEVInfo -> qemuGetSEVInfoToParams
* use virQEMUCapsCacheLookupByArch to get qemuCaps

Change since v7:
* rename virNodeSEVCapability() -> virNodeSEVInfo()
* rebase the series

Changes since v6:
* add API to get SEV PDH and Certificate chain data
* drop virsh command changes. We can revisit this later when we have
  more visibility on setter.

Change since v5:
* drop the seperate test patch and merge the code with other patches.
* rename the xml from sev -> launch-security-sev
* make policy field mandatory
* address multiple feedback from previous reviews.

Changes since v4:
* add /dev/sev in shared device list

Changes since v3:
* rename QEMU_CAPS_SEV -> QEMU_CAPS_SEV_GUEST
* update caps_2.12.0.x86_64.replies to include query-sev-capabilities data

Changes since v2:
* make cbitpos, policy and reduced-phys-bits as unsigned int
* update virDomainGetLaunchSecurityInfo to accept virTypedParameterPtr *params
instead of virTypedParameterPtr params.

Changes since v1:
* rename <sev> -> <launch-security> for domain
* add more information about policy and other fields in domaincaps.html
* split the domain_conf support in two patches
* add virDomainGetLaunchInfo() to retrieve the SEV measurement
* extend virsh command to show the domain's launch security information
* add test cases to validate newly added <launch-security> element
* fix issues reported with 'make check' and 'make syntax-check'

The complete git tree is available at:
https://github.com/codomania/libvirt/tree/v9

Brijesh Singh (11):
  qemu: provide support to query the SEV capability
  conf: expose SEV feature in domain capabilities
  libvirt: Introduce virNodeGetSEVInfo public API
  remote: implement the remote protocol for virNodeGetSEVInfo()
  qemu: Implement the driver backend for virNodeGetSEVInfo()
  conf: introduce launch-security element in domain
  qemu/cgroup: add /dev/sev in shared devices list
  qemu: add support to launch SEV guest
  libvirt: Introduce virDomainGetLaunchSecurityInfo public API
  remote: implement the remote protocol for launch security
  qemu: Implement the driver backend for virDomainGetLaunchSecurityInfo

 docs/drvqemu.html.in                               |   3 +-
 docs/formatdomain.html.in                          | 115 ++++++++++++++++
 docs/formatdomaincaps.html.in                      |  30 ++++
 docs/schemas/domaincaps.rng                        |  14 ++
 docs/schemas/domaincommon.rng                      |  37 +++++
 include/libvirt/libvirt-domain.h                   |  17 +++
 include/libvirt/libvirt-host.h                     |  42 ++++++
 src/conf/domain_capabilities.c                     |  30 ++++
 src/conf/domain_capabilities.h                     |  13 ++
 src/conf/domain_conf.c                             | 133 ++++++++++++++++++
 src/conf/domain_conf.h                             |  27 ++++
 src/driver-hypervisor.h                            |  14 ++
 src/libvirt-domain.c                               |  48 +++++++
 src/libvirt-host.c                                 |  49 +++++++
 src/libvirt_private.syms                           |   1 +
 src/libvirt_public.syms                            |   2 +
 src/qemu/qemu.conf                                 |   2 +-
 src/qemu/qemu_capabilities.c                       |  90 +++++++++++-
 src/qemu/qemu_capabilities.h                       |   6 +
 src/qemu/qemu_capspriv.h                           |   4 +
 src/qemu/qemu_cgroup.c                             |   2 +-
 src/qemu/qemu_command.c                            |  41 ++++++
 src/qemu/qemu_driver.c                             | 151 +++++++++++++++++++++
 src/qemu/qemu_monitor.c                            |  18 +++
 src/qemu/qemu_monitor.h                            |   6 +
 src/qemu/qemu_monitor_json.c                       | 121 +++++++++++++++++
 src/qemu/qemu_monitor_json.h                       |   5 +
 src/qemu/qemu_process.c                            |  62 +++++++++
 src/qemu/test_libvirtd_qemu.aug.in                 |   1 +
 src/remote/remote_daemon_dispatch.c                |  91 +++++++++++++
 src/remote/remote_driver.c                         |  80 +++++++++++
 src/remote/remote_protocol.x                       |  39 +++++-
 src/remote_protocol-structs                        |  23 ++++
 tests/genericxml2xmlindata/launch-security-sev.xml |  24 ++++
 tests/genericxml2xmltest.c                         |   2 +
 .../caps_2.12.0.x86_64.replies                     |  10 ++
 tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml  |   3 +-
 tests/qemuxml2argvdata/launch-security-sev.args    |  29 ++++
 tests/qemuxml2argvdata/launch-security-sev.xml     |  37 +++++
 tests/qemuxml2argvtest.c                           |   4 +
 40 files changed, 1420 insertions(+), 6 deletions(-)
 create mode 100644 tests/genericxml2xmlindata/launch-security-sev.xml
 create mode 100644 tests/qemuxml2argvdata/launch-security-sev.args
 create mode 100644 tests/qemuxml2argvdata/launch-security-sev.xml

-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v9 00/11] x86: Secure Encrypted Virtualization (AMD)
Posted by Brijesh Singh, 2 weeks ago
Re: Jano's below comment

(Also, some of the patches have double "<< >>" around your e-mail,
how did that happen?)

I am not sure what I am doing that is causing the double "<< >>" around 
my email address in some patches. I tried fixing it after I saw Jano 
note but it somehow happens again...I have no explanation on what is 
going on. Whoever commits the series, can you please remove one of the 
quote from the my email address, Or I can try fixing it and resend the 
series. Please let me know. thanks


On 06/08/2018 09:40 AM, Brijesh Singh wrote:
> This patch series provides support for launching an encrypted guest using
> AMD's new Secure Encrypted  Virtualization (SEV) feature.
> 
> SEV is an extension to the AMD-V architecture which supports running
> multiple VMs under the control of a hypervisor. When enabled, SEV feature
> allows the memory contents of a virtual machine (VM) to be transparently
> encrypted with a key unique to the guest VM.
> 
> At very high level the flow looks this:
> 
> 1. mgmt tool calls virConnectGetDomainCapabilities. This returns an XML document
> that includes the following
> 
> <feature>
> ...
>    <sev supported='yes'>
>      <cbitpos> </cbitpos>
>      <reduced-phys-bits> </reduced-phys-bits>
>    </sev>
> </feature>
> 
> If <sev> is provided then we indicate that hypervisor is capable of launching
> SEV guest. mgmt tool can call virNodeGetSEVCapabilities() to get the additional
> informations like PDH and certificate chain etc.
> 
> 2. (optional) mgmt tool can provide the PDH and Cert-chain to guest owner in case
> if guest owner wish to establish a secure connection with SEV firmware to
> negotiate a key used for validating the measurement.
> 
> 3. mgmt tool requests to start a guest calling virCreateXML(), passing \
> VIR_DOMAIN_START_PAUSED. The xml would include
> 
> <launch-security type='sev'>
>    <cbitpos>47</cbitpos>
>    <reduced-phys-bits>1</reduced-phys-bits>
>    <policy>0x1</policy>
> 
>    (optional)
>    <dh-cert> </dh-cert> /* Guest owners Diffie-Hellman key */
>    <session> </session> /* Guest owners Session blob */
> </launch-security>
> 
> 4. Libvirt generate the QEMU cli arg to enable the SEV feature, a typical
> args looks like this:
> 
> # $QEMU ..
> -machine memory-encryption=sev0 \
> -object sev-guest,id=sev0,dh-cert-file=<file>....
> 
> 5. Libvirt generates lifecycle VIR_DOMAIN_EVENT_SUSPENDED_PAUSED event
> 
> 6. mgmt tool gets the VIR_DOMAIN_EVENT_SUSPENDED_PAUSED and calls \
> virDomainGetLaunchSecretInfo() to retrieve the measurement of encrypted memory.
> 
> 7. (optional) mgmt tool can provide the measurement value to guest owner, which can
> validate the measurement and gives GO/NO-GO answer. If mgmt tool gets GO then
> it resumes the guest otherwise it calls destroy() to kill the guest.
> 
> 8. mgmt tool resumes the guest
> 
> TODO:
> * SEV guest require to use DMA apis for the virtio devices. In order to use the DMA
> apis the virtio devices must have this tag
> 
> <driver iommu=on ats=on>
> 
> It is a bit unclear to me where these changes need to go. Do we need to
> modify the libvirt to automatically add these when SEV is enabled or
> we ask mgmt tool to make sure that it creates XML with right tag to enable
> the DMA APIs for virtio devices. I am looking for some suggestions.
> 
> Using these patches we have succesfully booted and tested a guest both with and
> without SEV enabled.
> 
> SEV Firmware API spec is available at:
> https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf
> 
> Changes sicne v8:
> * rename qemuGetSEVInfo -> qemuGetSEVInfoToParams
> * use virQEMUCapsCacheLookupByArch to get qemuCaps
> 
> Change since v7:
> * rename virNodeSEVCapability() -> virNodeSEVInfo()
> * rebase the series
> 
> Changes since v6:
> * add API to get SEV PDH and Certificate chain data
> * drop virsh command changes. We can revisit this later when we have
>    more visibility on setter.
> 
> Change since v5:
> * drop the seperate test patch and merge the code with other patches.
> * rename the xml from sev -> launch-security-sev
> * make policy field mandatory
> * address multiple feedback from previous reviews.
> 
> Changes since v4:
> * add /dev/sev in shared device list
> 
> Changes since v3:
> * rename QEMU_CAPS_SEV -> QEMU_CAPS_SEV_GUEST
> * update caps_2.12.0.x86_64.replies to include query-sev-capabilities data
> 
> Changes since v2:
> * make cbitpos, policy and reduced-phys-bits as unsigned int
> * update virDomainGetLaunchSecurityInfo to accept virTypedParameterPtr *params
> instead of virTypedParameterPtr params.
> 
> Changes since v1:
> * rename <sev> -> <launch-security> for domain
> * add more information about policy and other fields in domaincaps.html
> * split the domain_conf support in two patches
> * add virDomainGetLaunchInfo() to retrieve the SEV measurement
> * extend virsh command to show the domain's launch security information
> * add test cases to validate newly added <launch-security> element
> * fix issues reported with 'make check' and 'make syntax-check'
> 
> The complete git tree is available at:
> https://github.com/codomania/libvirt/tree/v9
> 
> Brijesh Singh (11):
>    qemu: provide support to query the SEV capability
>    conf: expose SEV feature in domain capabilities
>    libvirt: Introduce virNodeGetSEVInfo public API
>    remote: implement the remote protocol for virNodeGetSEVInfo()
>    qemu: Implement the driver backend for virNodeGetSEVInfo()
>    conf: introduce launch-security element in domain
>    qemu/cgroup: add /dev/sev in shared devices list
>    qemu: add support to launch SEV guest
>    libvirt: Introduce virDomainGetLaunchSecurityInfo public API
>    remote: implement the remote protocol for launch security
>    qemu: Implement the driver backend for virDomainGetLaunchSecurityInfo
> 
>   docs/drvqemu.html.in                               |   3 +-
>   docs/formatdomain.html.in                          | 115 ++++++++++++++++
>   docs/formatdomaincaps.html.in                      |  30 ++++
>   docs/schemas/domaincaps.rng                        |  14 ++
>   docs/schemas/domaincommon.rng                      |  37 +++++
>   include/libvirt/libvirt-domain.h                   |  17 +++
>   include/libvirt/libvirt-host.h                     |  42 ++++++
>   src/conf/domain_capabilities.c                     |  30 ++++
>   src/conf/domain_capabilities.h                     |  13 ++
>   src/conf/domain_conf.c                             | 133 ++++++++++++++++++
>   src/conf/domain_conf.h                             |  27 ++++
>   src/driver-hypervisor.h                            |  14 ++
>   src/libvirt-domain.c                               |  48 +++++++
>   src/libvirt-host.c                                 |  49 +++++++
>   src/libvirt_private.syms                           |   1 +
>   src/libvirt_public.syms                            |   2 +
>   src/qemu/qemu.conf                                 |   2 +-
>   src/qemu/qemu_capabilities.c                       |  90 +++++++++++-
>   src/qemu/qemu_capabilities.h                       |   6 +
>   src/qemu/qemu_capspriv.h                           |   4 +
>   src/qemu/qemu_cgroup.c                             |   2 +-
>   src/qemu/qemu_command.c                            |  41 ++++++
>   src/qemu/qemu_driver.c                             | 151 +++++++++++++++++++++
>   src/qemu/qemu_monitor.c                            |  18 +++
>   src/qemu/qemu_monitor.h                            |   6 +
>   src/qemu/qemu_monitor_json.c                       | 121 +++++++++++++++++
>   src/qemu/qemu_monitor_json.h                       |   5 +
>   src/qemu/qemu_process.c                            |  62 +++++++++
>   src/qemu/test_libvirtd_qemu.aug.in                 |   1 +
>   src/remote/remote_daemon_dispatch.c                |  91 +++++++++++++
>   src/remote/remote_driver.c                         |  80 +++++++++++
>   src/remote/remote_protocol.x                       |  39 +++++-
>   src/remote_protocol-structs                        |  23 ++++
>   tests/genericxml2xmlindata/launch-security-sev.xml |  24 ++++
>   tests/genericxml2xmltest.c                         |   2 +
>   .../caps_2.12.0.x86_64.replies                     |  10 ++
>   tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml  |   3 +-
>   tests/qemuxml2argvdata/launch-security-sev.args    |  29 ++++
>   tests/qemuxml2argvdata/launch-security-sev.xml     |  37 +++++
>   tests/qemuxml2argvtest.c                           |   4 +
>   40 files changed, 1420 insertions(+), 6 deletions(-)
>   create mode 100644 tests/genericxml2xmlindata/launch-security-sev.xml
>   create mode 100644 tests/qemuxml2argvdata/launch-security-sev.args
>   create mode 100644 tests/qemuxml2argvdata/launch-security-sev.xml
> 

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v9 00/11] x86: Secure Encrypted Virtualization (AMD)
Posted by Erik Skultety, 1 week ago
On Fri, Jun 08, 2018 at 10:14:35AM -0500, Brijesh Singh wrote:
>
> Re: Jano's below comment
>
> (Also, some of the patches have double "<< >>" around your e-mail,
> how did that happen?)
>
> I am not sure what I am doing that is causing the double "<< >>" around my
> email address in some patches. I tried fixing it after I saw Jano note but
> it somehow happens again...I have no explanation on what is going on.
> Whoever commits the series, can you please remove one of the quote from the
> my email address, Or I can try fixing it and resend the series. Please let
> me know. thanks

For the whole series (I'll make the tiny change in patch 5):
Reviewed-by: Erik Skultety <eskultet@redhat.com>

I'll also tweak the double angle brackets, at first I thought you were adding
the SoB manually and this was a typo, but it clearly isn't the case, it would
be pointless to bikeshed about that, so as I said, I'll take care of that
before merging.

Also, now that this is done, would take also take care of extending the other
language bindings for the new APIs, or shall I do that?

Thanks,
Erik

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v9 00/11] x86: Secure Encrypted Virtualization (AMD)
Posted by Brijesh Singh, 1 week ago
Hi Erik,


On 06/11/2018 09:10 AM, Erik Skultety wrote:
> On Fri, Jun 08, 2018 at 10:14:35AM -0500, Brijesh Singh wrote:
>>
>> Re: Jano's below comment
>>
>> (Also, some of the patches have double "<< >>" around your e-mail,
>> how did that happen?)
>>
>> I am not sure what I am doing that is causing the double "<< >>" around my
>> email address in some patches. I tried fixing it after I saw Jano note but
>> it somehow happens again...I have no explanation on what is going on.
>> Whoever commits the series, can you please remove one of the quote from the
>> my email address, Or I can try fixing it and resend the series. Please let
>> me know. thanks
> 
> For the whole series (I'll make the tiny change in patch 5):
> Reviewed-by: Erik Skultety <eskultet@redhat.com>
> 
> I'll also tweak the double angle brackets, at first I thought you were adding
> the SoB manually and this was a typo, but it clearly isn't the case, it would
> be pointless to bikeshed about that, so as I said, I'll take care of that
> before merging.
> 
> Also, now that this is done, would take also take care of extending the other
> language bindings for the new APIs, or shall I do that?
> 


Thanks for all your help in reviews. Any help on language bindings for 
the new APIs are appreciated. I think I may able to do python but will 
certainly need help with others (I am not very familiar with other 
languages).

-Brijesh

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v9 00/11] x86: Secure Encrypted Virtualization (AMD)
Posted by Daniel P. Berrangé, 1 week ago
On Mon, Jun 11, 2018 at 11:17:02AM -0500, Brijesh Singh wrote:
> Hi Erik,
> 
> 
> On 06/11/2018 09:10 AM, Erik Skultety wrote:
> > On Fri, Jun 08, 2018 at 10:14:35AM -0500, Brijesh Singh wrote:
> > > 
> > > Re: Jano's below comment
> > > 
> > > (Also, some of the patches have double "<< >>" around your e-mail,
> > > how did that happen?)
> > > 
> > > I am not sure what I am doing that is causing the double "<< >>" around my
> > > email address in some patches. I tried fixing it after I saw Jano note but
> > > it somehow happens again...I have no explanation on what is going on.
> > > Whoever commits the series, can you please remove one of the quote from the
> > > my email address, Or I can try fixing it and resend the series. Please let
> > > me know. thanks
> > 
> > For the whole series (I'll make the tiny change in patch 5):
> > Reviewed-by: Erik Skultety <eskultet@redhat.com>
> > 
> > I'll also tweak the double angle brackets, at first I thought you were adding
> > the SoB manually and this was a typo, but it clearly isn't the case, it would
> > be pointless to bikeshed about that, so as I said, I'll take care of that
> > before merging.
> > 
> > Also, now that this is done, would take also take care of extending the other
> > language bindings for the new APIs, or shall I do that?
> 
> 
> Thanks for all your help in reviews. Any help on language bindings for the
> new APIs are appreciated. I think I may able to do python but will certainly
> need help with others (I am not very familiar with other languages).

Thanks for all your hard work in developing this feature for libvirt and
patience with the many rounds of the review process.

I will take care of the Go & Perl bindings if no one beats me to it.


Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v9 00/11] x86: Secure Encrypted Virtualization (AMD)
Posted by Erik Skultety, 1 week ago
On Tue, Jun 12, 2018 at 11:07:51AM +0100, Daniel P. Berrangé wrote:
> On Mon, Jun 11, 2018 at 11:17:02AM -0500, Brijesh Singh wrote:
> > Hi Erik,
> >
> >
> > On 06/11/2018 09:10 AM, Erik Skultety wrote:
> > > On Fri, Jun 08, 2018 at 10:14:35AM -0500, Brijesh Singh wrote:
> > > >
> > > > Re: Jano's below comment
> > > >
> > > > (Also, some of the patches have double "<< >>" around your e-mail,
> > > > how did that happen?)
> > > >
> > > > I am not sure what I am doing that is causing the double "<< >>" around my
> > > > email address in some patches. I tried fixing it after I saw Jano note but
> > > > it somehow happens again...I have no explanation on what is going on.
> > > > Whoever commits the series, can you please remove one of the quote from the
> > > > my email address, Or I can try fixing it and resend the series. Please let
> > > > me know. thanks
> > >
> > > For the whole series (I'll make the tiny change in patch 5):
> > > Reviewed-by: Erik Skultety <eskultet@redhat.com>
> > >
> > > I'll also tweak the double angle brackets, at first I thought you were adding
> > > the SoB manually and this was a typo, but it clearly isn't the case, it would
> > > be pointless to bikeshed about that, so as I said, I'll take care of that
> > > before merging.
> > >
> > > Also, now that this is done, would take also take care of extending the other
> > > language bindings for the new APIs, or shall I do that?
> >
> >
> > Thanks for all your help in reviews. Any help on language bindings for the
> > new APIs are appreciated. I think I may able to do python but will certainly
> > need help with others (I am not very familiar with other languages).
>
> Thanks for all your hard work in developing this feature for libvirt and
> patience with the many rounds of the review process.
>
> I will take care of the Go & Perl bindings if no one beats me to it.

I'm working on the python ones at the moment, thanks Daniel for taking care of
Go & Perl.

Erik

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v9 01/11] qemu: provide support to query the SEV capability
Posted by Brijesh Singh, 2 weeks ago
QEMU version >= 2.12 provides support for launching an encrypted VMs on
AMD x86 platform using Secure Encrypted Virtualization (SEV) feature.
This patch adds support to query the SEV capability from the qemu.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
---
 src/conf/domain_capabilities.c                     | 12 ++++
 src/conf/domain_capabilities.h                     | 12 ++++
 src/libvirt_private.syms                           |  1 +
 src/qemu/qemu_capabilities.c                       | 37 ++++++++++
 src/qemu/qemu_capabilities.h                       |  4 +-
 src/qemu/qemu_capspriv.h                           |  4 ++
 src/qemu/qemu_monitor.c                            | 10 +++
 src/qemu/qemu_monitor.h                            |  3 +
 src/qemu/qemu_monitor_json.c                       | 79 ++++++++++++++++++++++
 src/qemu/qemu_monitor_json.h                       |  3 +
 .../caps_2.12.0.x86_64.replies                     | 10 +++
 tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml  |  3 +-
 12 files changed, 176 insertions(+), 2 deletions(-)

diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index c20358e..3589777 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -67,6 +67,18 @@ virDomainCapsStringValuesFree(virDomainCapsStringValuesPtr values)
 }
 
 
+void
+virSEVCapabilitiesFree(virSEVCapability *cap)
+{
+    if (!cap)
+        return;
+
+    VIR_FREE(cap->pdh);
+    VIR_FREE(cap->cert_chain);
+    VIR_FREE(cap);
+}
+
+
 static void
 virDomainCapsDispose(void *obj)
 {
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index b0eb4aa..56c1903 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -137,6 +137,15 @@ struct _virDomainCapsCPU {
     virDomainCapsCPUModelsPtr custom;
 };
 
+typedef struct _virSEVCapability virSEVCapability;
+typedef virSEVCapability *virSEVCapabilityPtr;
+struct _virSEVCapability {
+    char *pdh;
+    char *cert_chain;
+    unsigned int cbitpos;
+    unsigned int reduced_phys_bits;
+};
+
 struct _virDomainCaps {
     virObjectLockable parent;
 
@@ -202,4 +211,7 @@ int virDomainCapsEnumSet(virDomainCapsEnumPtr capsEnum,
 void virDomainCapsEnumClear(virDomainCapsEnumPtr capsEnum);
 
 char * virDomainCapsFormat(virDomainCapsPtr const caps);
+
+void
+virSEVCapabilitiesFree(virSEVCapability *capabilities);
 #endif /* __DOMAIN_CAPABILITIES_H__ */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 2245101..ea24f28 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -185,6 +185,7 @@ virDomainCapsEnumClear;
 virDomainCapsEnumSet;
 virDomainCapsFormat;
 virDomainCapsNew;
+virSEVCapabilitiesFree;
 
 
 # conf/domain_conf.h
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index a673709..8b3ffe1 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -497,6 +497,9 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
               "tpm-emulator",
               "mch",
               "mch.extended-tseg-mbytes",
+
+              /* 310 */
+              "sev-guest",
     );
 
 
@@ -563,6 +566,8 @@ struct _virQEMUCaps {
     size_t ngicCapabilities;
     virGICCapability *gicCapabilities;
 
+    virSEVCapability *sevCapabilities;
+
     virQEMUCapsHostCPUData kvmCPU;
     virQEMUCapsHostCPUData tcgCPU;
 };
@@ -1135,6 +1140,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
     { "vmgenid", QEMU_CAPS_DEVICE_VMGENID },
     { "vhost-vsock-device", QEMU_CAPS_DEVICE_VHOST_VSOCK },
     { "mch", QEMU_CAPS_DEVICE_MCH },
+    { "sev-guest", QEMU_CAPS_SEV_GUEST },
 };
 
 static struct virQEMUCapsStringFlags virQEMUCapsDevicePropsVirtioBalloon[] = {
@@ -2078,6 +2084,16 @@ virQEMUCapsSetGICCapabilities(virQEMUCapsPtr qemuCaps,
 }
 
 
+void
+virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
+                              virSEVCapability *capabilities)
+{
+    virSEVCapabilitiesFree(qemuCaps->sevCapabilities);
+
+    qemuCaps->sevCapabilities = capabilities;
+}
+
+
 static int
 virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
                             qemuMonitorPtr mon)
@@ -2665,6 +2681,21 @@ virQEMUCapsProbeQMPGICCapabilities(virQEMUCapsPtr qemuCaps,
 }
 
 
+static int
+virQEMUCapsProbeQMPSEVCapabilities(virQEMUCapsPtr qemuCaps,
+                                   qemuMonitorPtr mon)
+{
+    virSEVCapability *caps = NULL;
+
+    if (qemuMonitorGetSEVCapabilities(mon, &caps) < 0)
+        return -1;
+
+    virQEMUCapsSetSEVCapabilities(qemuCaps, caps);
+
+    return 0;
+}
+
+
 bool
 virQEMUCapsCPUFilterFeatures(const char *name,
                              void *opaque)
@@ -4064,6 +4095,12 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
             virQEMUCapsClear(qemuCaps, QEMU_CAPS_DEVICE_VFIO_CCW);
     }
 
+    /* Probe for SEV capabilities */
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
+        if (virQEMUCapsProbeQMPSEVCapabilities(qemuCaps, mon) < 0)
+            virQEMUCapsClear(qemuCaps, QEMU_CAPS_SEV_GUEST);
+    }
+
     ret = 0;
  cleanup:
     return ret;
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 884b406..f80da91 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -482,6 +482,9 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
     QEMU_CAPS_DEVICE_MCH, /* Northbridge in q35 machine types */
     QEMU_CAPS_MCH_EXTENDED_TSEG_MBYTES, /* -global mch.extended-tseg-mbytes */
 
+    /* 310 */
+    QEMU_CAPS_SEV_GUEST, /* -object sev-guest,... */
+
     QEMU_CAPS_LAST /* this must always be the last item */
 } virQEMUCapsFlags;
 
@@ -615,5 +618,4 @@ bool virQEMUCapsGuestIsNative(virArch host,
 
 bool virQEMUCapsCPUFilterFeatures(const char *name,
                                   void *opaque);
-
 #endif /* __QEMU_CAPABILITIES_H__*/
diff --git a/src/qemu/qemu_capspriv.h b/src/qemu/qemu_capspriv.h
index 4b7a04a..cb5e0dd 100644
--- a/src/qemu/qemu_capspriv.h
+++ b/src/qemu/qemu_capspriv.h
@@ -90,6 +90,10 @@ virQEMUCapsSetGICCapabilities(virQEMUCapsPtr qemuCaps,
                               virGICCapability *capabilities,
                               size_t ncapabilities);
 
+void
+virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
+                              virSEVCapability *capabilities);
+
 int
 virQEMUCapsProbeQMPCPUDefinitions(virQEMUCapsPtr qemuCaps,
                                   qemuMonitorPtr mon,
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 215135a..fd6bce9 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -3850,6 +3850,16 @@ qemuMonitorGetGICCapabilities(qemuMonitorPtr mon,
 
 
 int
+qemuMonitorGetSEVCapabilities(qemuMonitorPtr mon,
+                              virSEVCapability **capabilities)
+{
+    QEMU_CHECK_MONITOR(mon);
+
+    return qemuMonitorJSONGetSEVCapabilities(mon, capabilities);
+}
+
+
+int
 qemuMonitorNBDServerStart(qemuMonitorPtr mon,
                           const char *host,
                           unsigned int port,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 4384372..75d5d98 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -711,6 +711,9 @@ int qemuMonitorSetMigrationCapabilities(qemuMonitorPtr mon,
 int qemuMonitorGetGICCapabilities(qemuMonitorPtr mon,
                                   virGICCapability **capabilities);
 
+int qemuMonitorGetSEVCapabilities(qemuMonitorPtr mon,
+                                  virSEVCapability **capabilities);
+
 typedef enum {
   QEMU_MONITOR_MIGRATE_BACKGROUND       = 1 << 0,
   QEMU_MONITOR_MIGRATE_NON_SHARED_DISK  = 1 << 1, /* migration with non-shared storage with full disk copy */
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index e8a46d2..ba0da9a 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -6401,6 +6401,85 @@ qemuMonitorJSONGetGICCapabilities(qemuMonitorPtr mon,
     return ret;
 }
 
+
+int
+qemuMonitorJSONGetSEVCapabilities(qemuMonitorPtr mon,
+                                  virSEVCapability **capabilities)
+{
+    int ret = -1;
+    virJSONValuePtr cmd;
+    virJSONValuePtr reply = NULL;
+    virJSONValuePtr caps;
+    virSEVCapability *capability = NULL;
+    const char *pdh = NULL, *cert_chain = NULL;
+    unsigned int cbitpos, reduced_phys_bits;
+
+    *capabilities = NULL;
+
+    if (!(cmd = qemuMonitorJSONMakeCommand("query-sev-capabilities",
+                                           NULL)))
+        return -1;
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        goto cleanup;
+
+
+    if (qemuMonitorJSONCheckError(cmd, reply) < 0)
+        goto cleanup;
+
+    caps = virJSONValueObjectGetObject(reply, "return");
+
+    if (virJSONValueObjectGetNumberUint(caps, "cbitpos", &cbitpos) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("query-sev-capabilities reply was missing"
+                         " 'cbitpos' field"));
+        goto cleanup;
+    }
+
+    if (virJSONValueObjectGetNumberUint(caps, "reduced-phys-bits",
+                                       &reduced_phys_bits) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("query-sev-capabilities reply was missing"
+                         " 'reduced-phys-bits' field"));
+        goto cleanup;
+    }
+
+    if (!(pdh = virJSONValueObjectGetString(caps, "pdh"))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("query-sev-capabilities reply was missing"
+                         " 'pdh' field"));
+        goto cleanup;
+    }
+
+    if (!(cert_chain = virJSONValueObjectGetString(caps, "cert-chain"))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("query-sev-capabilities reply was missing"
+                         " 'cert-chain' field"));
+        goto cleanup;
+    }
+
+    if (VIR_ALLOC(capability) < 0)
+        goto cleanup;
+
+    if (VIR_STRDUP(capability->pdh, pdh) < 0)
+        goto cleanup;
+
+    if (VIR_STRDUP(capability->cert_chain, cert_chain) < 0)
+        goto cleanup;
+
+    capability->cbitpos = cbitpos;
+    capability->reduced_phys_bits = reduced_phys_bits;
+    VIR_STEAL_PTR(*capabilities, capability);
+    ret = 0;
+
+ cleanup:
+    virSEVCapabilitiesFree(capability);
+    virJSONValueFree(cmd);
+    virJSONValueFree(reply);
+
+    return ret;
+}
+
 static virJSONValuePtr
 qemuMonitorJSONBuildInetSocketAddress(const char *host,
                                       const char *port)
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 2ae0faa..4c10574 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -152,6 +152,9 @@ int qemuMonitorJSONSetMigrationCapabilities(qemuMonitorPtr mon,
 int qemuMonitorJSONGetGICCapabilities(qemuMonitorPtr mon,
                                       virGICCapability **capabilities);
 
+int qemuMonitorJSONGetSEVCapabilities(qemuMonitorPtr mon,
+                                      virSEVCapability **capabilities);
+
 int qemuMonitorJSONMigrate(qemuMonitorPtr mon,
                            unsigned int flags,
                            const char *uri);
diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies
index 78e1b45..ddee9b9 100644
--- a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies
+++ b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies
@@ -19039,6 +19039,16 @@
 }
 
 {
+  "return" : {
+   "reduced-phys-bits": 1,
+   "cbitpos": 47,
+   "cert-chain": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA",
+   "pdh": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA"
+  },
+  "id": "libvirt-52"
+}
+
+{
   "return": {
   },
   "id": "libvirt-1"
diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
index 2afd7ad..0c38826 100644
--- a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
@@ -210,9 +210,10 @@
   <flag name='tpm-emulator'/>
   <flag name='mch'/>
   <flag name='mch.extended-tseg-mbytes'/>
+  <flag name='sev-guest'/>
   <version>2011090</version>
   <kvmVersion>0</kvmVersion>
-  <microcodeVersion>391586</microcodeVersion>
+  <microcodeVersion>391832</microcodeVersion>
   <package>v2.12.0-rc0</package>
   <arch>x86_64</arch>
   <hostCPU type='kvm' model='base' migratability='yes'>
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v9 02/11] conf: expose SEV feature in domain capabilities
Posted by Brijesh Singh, 2 weeks ago
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>
---
 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 e0814cb..6be553a 100644
--- a/docs/formatdomaincaps.html.in
+++ b/docs/formatdomaincaps.html.in
@@ -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>
diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng
index 5ceabb0..1d0a2e1 100644
--- a/docs/schemas/domaincaps.rng
+++ b/docs/schemas/domaincaps.rng
@@ -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'>
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index 3589777..ec469bf 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, "<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");
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index 56c1903..755de13 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 8b3ffe1..1803ed9 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;
 }
 
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v9 03/11] libvirt: Introduce virNodeGetSEVInfo public API
Posted by Brijesh Singh, 2 weeks ago
The API can be used by application to retrieve the Platform Diffie-Hellman
Key and Platform Certificate chain.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
---
 include/libvirt/libvirt-host.h | 42 ++++++++++++++++++++++++++++++++++++
 src/driver-hypervisor.h        |  6 ++++++
 src/libvirt-host.c             | 49 ++++++++++++++++++++++++++++++++++++++++++
 src/libvirt_public.syms        |  1 +
 4 files changed, 98 insertions(+)

diff --git a/include/libvirt/libvirt-host.h b/include/libvirt/libvirt-host.h
index 84f4858..a04d669 100644
--- a/include/libvirt/libvirt-host.h
+++ b/include/libvirt/libvirt-host.h
@@ -432,6 +432,48 @@ typedef virNodeCPUStats *virNodeCPUStatsPtr;
 
 typedef virNodeMemoryStats *virNodeMemoryStatsPtr;
 
+
+/**
+ *
+ * SEV Parameters
+ */
+
+/**
+ * VIR_NODE_SEV_PDH:
+ *
+ * Macro represents the Platform Diffie-Hellman key, as VIR_TYPED_PARAMS_STRING.
+ */
+# define VIR_NODE_SEV_PDH "pdh"
+
+/**
+ * VIR_NODE_SEV_CERT_CHAIN:
+ *
+ * Macro represents the platform certificate chain that includes the platform
+ * endorsement key (PEK), owner certificate authority (OCD) and chip
+ * endorsement key (CEK), as VIR_TYPED_PARAMS_STRING.
+ */
+# define VIR_NODE_SEV_CERT_CHAIN "cert-chain"
+
+/**
+ * VIR_NODE_SEV_CBITPOS:
+ *
+ * Macro represents the CBit Position used by hypervisor when SEV is enabled.
+ */
+# define VIR_NODE_SEV_CBITPOS "cbitpos"
+
+/**
+ * VIR_NODE_SEV_REDUCED_PHYS_BITS:
+ *
+ * Macro represents the number of bits we lose in physical address space
+ * when SEV is enabled in the guest.
+ */
+# define VIR_NODE_SEV_REDUCED_PHYS_BITS "reduced-phys-bits"
+
+int virNodeGetSEVInfo (virConnectPtr conn,
+                       virTypedParameterPtr *params,
+                       int *nparams,
+                       unsigned int flags);
+
 /**
  * virConnectFlags
  *
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index aa99cbb..c50d2a0 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1309,6 +1309,11 @@ typedef int
                                   unsigned int action,
                                   unsigned int flags);
 
+typedef int
+(*virDrvNodeGetSEVInfo)(virConnectPtr conn,
+                        virTypedParameterPtr *params,
+                        int *nparams,
+                        unsigned int flags);
 
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;
@@ -1558,6 +1563,7 @@ struct _virHypervisorDriver {
     virDrvDomainSetLifecycleAction domainSetLifecycleAction;
     virDrvConnectCompareHypervisorCPU connectCompareHypervisorCPU;
     virDrvConnectBaselineHypervisorCPU connectBaselineHypervisorCPU;
+    virDrvNodeGetSEVInfo nodeGetSEVInfo;
 };
 
 
diff --git a/src/libvirt-host.c b/src/libvirt-host.c
index 3aaf558..e20d6ee 100644
--- a/src/libvirt-host.c
+++ b/src/libvirt-host.c
@@ -1639,3 +1639,52 @@ virNodeAllocPages(virConnectPtr conn,
     virDispatchError(conn);
     return -1;
 }
+
+
+/*
+ * virNodeGetSEVInfo:
+ * @conn: pointer to the hypervisor connection
+ * @params: where to store  SEV information
+ * @nparams: pointer to number of SEV parameters returned in @params
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * If hypervisor supports AMD's SEV feature, then @params will contain various
+ * platform specific information like PDH and certificate chain. Caller is
+ * responsible for freeing @params.
+ *
+ * Returns 0 in case of success, and -1 in case of failure.
+ */
+int
+virNodeGetSEVInfo(virConnectPtr conn,
+                  virTypedParameterPtr *params,
+                  int *nparams,
+                  unsigned int flags)
+{
+    VIR_DEBUG("conn=%p, params=%p, nparams=%p, flags=0x%x",
+              conn, params, nparams, flags);
+
+    virResetLastError();
+
+    virCheckConnectReturn(conn, -1);
+    virCheckNonNullArgGoto(nparams, error);
+    virCheckNonNegativeArgGoto(*nparams, error);
+    virCheckReadOnlyGoto(conn->flags, error);
+
+    if (VIR_DRV_SUPPORTS_FEATURE(conn->driver, conn,
+                                 VIR_DRV_FEATURE_TYPED_PARAM_STRING))
+        flags |= VIR_TYPED_PARAM_STRING_OKAY;
+
+    if (conn->driver->nodeGetSEVInfo) {
+        int ret;
+        ret = conn->driver->nodeGetSEVInfo(conn, params, nparams, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+
+ error:
+    virDispatchError(conn);
+    return -1;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 4f54b84..524d5fd 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -796,6 +796,7 @@ LIBVIRT_4.5.0 {
     global:
         virGetLastErrorCode;
         virGetLastErrorDomain;
+        virNodeGetSEVInfo;
 } LIBVIRT_4.4.0;
 
 # .... define new API here using predicted next version number ....
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v9 04/11] remote: implement the remote protocol for virNodeGetSEVInfo()
Posted by Brijesh Singh, 2 weeks ago
Add remote support for virNodeGetSEVInfo().

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
---
 src/remote/remote_daemon_dispatch.c | 44 +++++++++++++++++++++++++++++++++++++
 src/remote/remote_driver.c          | 40 +++++++++++++++++++++++++++++++++
 src/remote/remote_protocol.x        | 22 ++++++++++++++++++-
 src/remote_protocol-structs         | 12 ++++++++++
 4 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c
index 81d0445..959367f 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -5001,6 +5001,50 @@ remoteDispatchDomainGetDiskErrors(virNetServerPtr server ATTRIBUTE_UNUSED,
 
 
 static int
+remoteDispatchNodeGetSevInfo(virNetServerPtr server ATTRIBUTE_UNUSED,
+                             virNetServerClientPtr client ATTRIBUTE_UNUSED,
+                             virNetMessagePtr msg ATTRIBUTE_UNUSED,
+                             virNetMessageErrorPtr rerr,
+                             remote_node_get_sev_info_args *args,
+                             remote_node_get_sev_info_ret *ret)
+{
+    virTypedParameterPtr params = NULL;
+    int nparams = 0;
+    int rv = -1;
+    struct daemonClientPrivate *priv =
+        virNetServerClientGetPrivateData(client);
+
+    if (!priv->conn) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+        goto cleanup;
+    }
+
+    if (virNodeGetSEVInfo(priv->conn, &params, &nparams, args->flags) < 0)
+        goto cleanup;
+
+    if (nparams > REMOTE_NODE_SEV_INFO_MAX) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nparams too large"));
+        goto cleanup;
+    }
+
+
+    if (virTypedParamsSerialize(params, nparams,
+                                (virTypedParameterRemotePtr *) &ret->params.params_val,
+                                &ret->params.params_len,
+                                args->flags) < 0)
+        goto cleanup;
+
+    rv = 0;
+
+ cleanup:
+    if (rv < 0)
+        virNetMessageSaveError(rerr);
+    virTypedParamsFree(params, nparams);
+    return rv;
+}
+
+
+static int
 remoteDispatchNodeGetMemoryParameters(virNetServerPtr server ATTRIBUTE_UNUSED,
                                       virNetServerClientPtr client ATTRIBUTE_UNUSED,
                                       virNetMessagePtr msg ATTRIBUTE_UNUSED,
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index c22993c..8ac7264 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -6775,6 +6775,45 @@ remoteNodeGetMemoryParameters(virConnectPtr conn,
     return rv;
 }
 
+
+static int
+remoteNodeGetSEVInfo(virConnectPtr conn,
+                     virTypedParameterPtr *params,
+                     int *nparams,
+                     unsigned int flags)
+{
+    int rv = -1;
+    remote_node_get_sev_info_args args;
+    remote_node_get_sev_info_ret ret;
+    struct private_data *priv = conn->privateData;
+
+    remoteDriverLock(priv);
+
+    args.flags = flags;
+
+    memset(&ret, 0, sizeof(ret));
+    if (call(conn, priv, 0, REMOTE_PROC_NODE_GET_SEV_INFO,
+             (xdrproc_t) xdr_remote_node_get_sev_info_args, (char *) &args,
+             (xdrproc_t) xdr_remote_node_get_sev_info_ret, (char *) &ret) == -1)
+        goto done;
+
+    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.params.params_val,
+                                  ret.params.params_len,
+                                  REMOTE_NODE_SEV_INFO_MAX,
+                                  params,
+                                  nparams) < 0)
+        goto cleanup;
+
+    rv = 0;
+
+ cleanup:
+    xdr_free((xdrproc_t) xdr_remote_node_get_sev_info_ret, (char *) &ret);
+ done:
+    remoteDriverUnlock(priv);
+    return rv;
+}
+
+
 static int
 remoteNodeGetCPUMap(virConnectPtr conn,
                     unsigned char **cpumap,
@@ -8451,6 +8490,7 @@ static virHypervisorDriver hypervisor_driver = {
     .domainSetLifecycleAction = remoteDomainSetLifecycleAction, /* 3.9.0 */
     .connectCompareHypervisorCPU = remoteConnectCompareHypervisorCPU, /* 4.4.0 */
     .connectBaselineHypervisorCPU = remoteConnectBaselineHypervisorCPU, /* 4.4.0 */
+    .nodeGetSEVInfo = remoteNodeGetSEVInfo, /* 4.5.0 */
 };
 
 static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index a0ab7e9..ec72afa 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -253,6 +253,9 @@ const REMOTE_DOMAIN_IP_ADDR_MAX = 2048;
 /* Upper limit on number of guest vcpu information entries */
 const REMOTE_DOMAIN_GUEST_VCPU_PARAMS_MAX = 64;
 
+/* Upper limit on number of SEV parameters */
+const REMOTE_NODE_SEV_INFO_MAX = 64;
+
 /* UUID.  VIR_UUID_BUFLEN definition comes from libvirt.h */
 typedef opaque remote_uuid[VIR_UUID_BUFLEN];
 
@@ -3480,6 +3483,17 @@ struct remote_connect_baseline_hypervisor_cpu_ret {
     remote_nonnull_string cpu;
 };
 
+struct remote_node_get_sev_info_args {
+    int nparams;
+    unsigned int flags;
+};
+
+struct remote_node_get_sev_info_ret {
+    remote_typed_param params<REMOTE_NODE_SEV_INFO_MAX>;
+    int nparams;
+};
+
+
 /*----- Protocol. -----*/
 
 /* Define the program number, protocol version and procedure numbers here. */
@@ -6187,5 +6201,11 @@ enum remote_procedure {
      * @generate: both
      * @acl: connect:write
      */
-    REMOTE_PROC_CONNECT_BASELINE_HYPERVISOR_CPU = 394
+    REMOTE_PROC_CONNECT_BASELINE_HYPERVISOR_CPU = 394,
+
+    /**
+     * @generate: none
+     * @acl: connect:read
+     */
+    REMOTE_PROC_NODE_GET_SEV_INFO = 395
 };
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 0c4cfc6..dfc3624 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -2907,6 +2907,17 @@ struct remote_connect_baseline_hypervisor_cpu_args {
 struct remote_connect_baseline_hypervisor_cpu_ret {
         remote_nonnull_string      cpu;
 };
+struct remote_node_get_sev_info_args {
+        int                        nparams;
+        u_int                      flags;
+};
+struct remote_node_get_sev_info_ret {
+        struct {
+                u_int              params_len;
+                remote_typed_param * params_val;
+        } params;
+        int                        nparams;
+};
 enum remote_procedure {
         REMOTE_PROC_CONNECT_OPEN = 1,
         REMOTE_PROC_CONNECT_CLOSE = 2,
@@ -3302,4 +3313,5 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_DETACH_DEVICE_ALIAS = 392,
         REMOTE_PROC_CONNECT_COMPARE_HYPERVISOR_CPU = 393,
         REMOTE_PROC_CONNECT_BASELINE_HYPERVISOR_CPU = 394,
+        REMOTE_PROC_NODE_GET_SEV_INFO = 395,
 };
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v9 05/11] qemu: Implement the driver backend for virNodeGetSEVInfo()
Posted by Brijesh Singh, 2 weeks ago
Signed-off-by: Brijesh Singh <<brijesh.singh@amd.com>>
---
 src/qemu/qemu_capabilities.c |  7 ++++
 src/qemu/qemu_capabilities.h |  4 +++
 src/qemu/qemu_driver.c       | 82 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 93 insertions(+)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 1803ed9..7a245a5 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -2094,6 +2094,13 @@ virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
 }
 
 
+virSEVCapabilityPtr
+virQEMUCapsGetSEVCapabilities(virQEMUCapsPtr qemuCaps)
+{
+    return qemuCaps->sevCapabilities;
+}
+
+
 static int
 virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
                             qemuMonitorPtr mon)
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index f80da91..3519a19 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -618,4 +618,8 @@ bool virQEMUCapsGuestIsNative(virArch host,
 
 bool virQEMUCapsCPUFilterFeatures(const char *name,
                                   void *opaque);
+
+virSEVCapabilityPtr
+virQEMUCapsGetSEVCapabilities(virQEMUCapsPtr qemuCaps);
+
 #endif /* __QEMU_CAPABILITIES_H__*/
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 2876987..264c47d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -21424,6 +21424,87 @@ qemuDomainSetLifecycleAction(virDomainPtr dom,
 }
 
 
+static int
+qemuGetSEVInfoToParams(virQEMUCapsPtr qemuCaps,
+                       virTypedParameterPtr *params,
+                       int *nparams,
+                       unsigned int flags)
+{
+    int maxpar = 0;
+    int n = 0;
+    virSEVCapabilityPtr sev = virQEMUCapsGetSEVCapabilities(qemuCaps);
+    virTypedParameterPtr sevParams = NULL;
+
+    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+    if (virTypedParamsAddString(&sevParams, &n, &maxpar,
+                    VIR_NODE_SEV_PDH, sev->pdh) < 0)
+        return -1;
+
+    if (virTypedParamsAddString(&sevParams, &n, &maxpar,
+                    VIR_NODE_SEV_CERT_CHAIN, sev->cert_chain) < 0)
+        goto cleanup;
+
+    if (virTypedParamsAddUInt(&sevParams, &n, &maxpar,
+                    VIR_NODE_SEV_CBITPOS, sev->cbitpos) < 0)
+        goto cleanup;
+
+    if (virTypedParamsAddUInt(&sevParams, &n, &maxpar,
+                    VIR_NODE_SEV_REDUCED_PHYS_BITS,
+                    sev->reduced_phys_bits) < 0)
+        goto cleanup;
+
+    VIR_STEAL_PTR(*params, sevParams);
+    *nparams = n;
+    return 0;
+
+ cleanup:
+    virTypedParamsFree(sevParams, n);
+    return -1;
+}
+
+
+static int
+qemuNodeGetSEVInfo(virConnectPtr conn,
+                   virTypedParameterPtr *params,
+                   int *nparams,
+                   unsigned int flags)
+{
+    virQEMUDriverPtr driver = conn->privateData;
+    virCapsPtr caps = NULL;
+    virQEMUCapsPtr qemucaps = NULL;
+    int ret = -1;
+
+    if (virNodeGetSevInfoEnsureACL(conn) < 0)
+        return ret;
+
+    if (!(caps = virQEMUDriverGetCapabilities(driver, true)))
+        return ret;
+
+    qemucaps = virQEMUCapsCacheLookupByArch(driver->qemuCapsCache,
+                                            virArchFromHost());
+    if (!qemucaps)
+        goto cleanup;
+
+    if (!virQEMUCapsGet(qemucaps, QEMU_CAPS_SEV_GUEST)) {
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                       _("QEMU does not support SEV guest"));
+        goto cleanup;
+    }
+
+    if (qemuGetSEVInfoToParams(qemucaps, params, nparams, flags) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    virObjectUnref(qemucaps);
+    virObjectUnref(caps);
+
+    return ret;
+}
+
+
 static virHypervisorDriver qemuHypervisorDriver = {
     .name = QEMU_DRIVER_NAME,
     .connectURIProbe = qemuConnectURIProbe,
@@ -21647,6 +21728,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
     .domainSetLifecycleAction = qemuDomainSetLifecycleAction, /* 3.9.0 */
     .connectCompareHypervisorCPU = qemuConnectCompareHypervisorCPU, /* 4.4.0 */
     .connectBaselineHypervisorCPU = qemuConnectBaselineHypervisorCPU, /* 4.4.0 */
+    .nodeGetSEVInfo = qemuNodeGetSEVInfo, /* 4.5.0 */
 };
 
 
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v9 05/11] qemu: Implement the driver backend for virNodeGetSEVInfo()
Posted by Erik Skultety, 1 week ago
On Fri, Jun 08, 2018 at 09:40:55AM -0500, Brijesh Singh wrote:
> Signed-off-by: Brijesh Singh <<brijesh.singh@amd.com>>
> ---
>  src/qemu/qemu_capabilities.c |  7 ++++
>  src/qemu/qemu_capabilities.h |  4 +++
>  src/qemu/qemu_driver.c       | 82 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 93 insertions(+)
>

...

> +
> +static int
> +qemuNodeGetSEVInfo(virConnectPtr conn,
> +                   virTypedParameterPtr *params,
> +                   int *nparams,
> +                   unsigned int flags)
> +{
> +    virQEMUDriverPtr driver = conn->privateData;
> +    virCapsPtr caps = NULL;
> +    virQEMUCapsPtr qemucaps = NULL;
> +    int ret = -1;
> +
> +    if (virNodeGetSevInfoEnsureACL(conn) < 0)
> +        return ret;
> +
> +    if (!(caps = virQEMUDriverGetCapabilities(driver, true)))

you don't need ^this, I'll remove it before merging...

> +        return ret;
> +
> +    qemucaps = virQEMUCapsCacheLookupByArch(driver->qemuCapsCache,
> +                                            virArchFromHost());
> +    if (!qemucaps)
> +        goto cleanup;
> +
> +    if (!virQEMUCapsGet(qemucaps, QEMU_CAPS_SEV_GUEST)) {
> +        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
> +                       _("QEMU does not support SEV guest"));
> +        goto cleanup;
> +    }
> +
> +    if (qemuGetSEVInfoToParams(qemucaps, params, nparams, flags) < 0)
> +        goto cleanup;
> +
> +    ret = 0;
> +
> + cleanup:
> +    virObjectUnref(qemucaps);
> +    virObjectUnref(caps);

...neither ^this single unref (and the variable itself for that matter)...

Erik

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v9 06/11] conf: introduce launch-security element in domain
Posted by Brijesh Singh, 2 weeks ago
The launch-security element can be used to define the security
model to use when launching a domain. Currently we support 'sev'.

When 'sev' is used, the VM will be launched with AMD SEV feature enabled.
SEV feature supports running encrypted VM under the control of KVM.
Encrypted VMs have their pages (code and data) secured such that only the
guest itself has access to the unencrypted version. Each encrypted VM is
associated with a unique encryption key; if its data is accessed to a
different entity using a different key the encrypted guests data will be
incorrectly decrypted, leading to unintelligible data.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
---
 docs/formatdomain.html.in                          | 115 ++++++++++++++++++
 docs/schemas/domaincommon.rng                      |  37 ++++++
 src/conf/domain_conf.c                             | 133 +++++++++++++++++++++
 src/conf/domain_conf.h                             |  27 +++++
 tests/genericxml2xmlindata/launch-security-sev.xml |  24 ++++
 tests/genericxml2xmltest.c                         |   2 +
 6 files changed, 338 insertions(+)
 create mode 100644 tests/genericxml2xmlindata/launch-security-sev.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 6912762..77845fe 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -8458,6 +8458,121 @@ qemu-kvm -net nic,model=? /dev/null
 
     <p>Note: DEA/TDEA is synonymous with DES/TDES.</p>
 
+    <h3><a id="sev">Secure Encrypted Virtualization (SEV)</a></h3>
+
+    <p>
+       The contents of the <code>&lt;launch-security type='sev'&gt;</code> element
+       is used to provide the guest owners input used for creating an encrypted
+       VM using the AMD SEV feature.
+
+       SEV is an extension to the AMD-V architecture which supports running
+       encrypted virtual machine (VMs) under the control of KVM. Encrypted
+       VMs have their pages (code and data) secured such that only the guest
+       itself has access to the unencrypted version. Each encrypted VM is
+       associated with a unique encryption key; if its data is accessed to a
+       different entity using a different key the encrypted guests data will
+       be incorrectly decrypted, leading to unintelligible data.
+
+       For more information see various input parameters and its format see the SEV API spec
+       <a href="https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf"> https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf </a>
+       <span class="since">Since 4.4.0</span>
+       </p>
+    <pre>
+&lt;domain&gt;
+  ...
+  &lt;launch-security type='sev'&gt;
+    &lt;policy&gt; 0x0001 &lt;/policy&gt;
+    &lt;cbitpos&gt; 47 &lt;/cbitpos&gt;
+    &lt;reduced-phys-bits&gt; 1 &lt;/reduced-phys-bits&gt;
+    &lt;session&gt; AAACCCDD=FFFCCCDSDS &lt;/session&gt;
+    &lt;dh-cert&gt; RBBBSDDD=FDDCCCDDDG &lt;/dh&gt;
+  &lt;/sev&gt;
+  ...
+&lt;/domain&gt;
+</pre>
+
+    <dl>
+      <dt><code>cbitpos</code></dt>
+      <dd>The required <code>cbitpos</code> element provides the C-bit (aka encryption bit)
+      location in guest page table entry. The value of <code>cbitpos</code> is
+      hypervisor dependent and can be obtained through the <code>sev</code> element
+      from the domain capabilities.
+      </dd>
+      <dt><code>reduced-phys-bits</code></dt>
+      <dd>The required <code>reduced-phys-bits</code> element provides the physical
+      address bit reducation. Similar to <code>cbitpos</code> the value of <code>
+      reduced-phys-bit</code> is hypervisor dependent and can be obtained
+      through the <code>sev</code> element from the domain capabilities.
+      </dd>
+      <dt><code>policy</code></dt>
+      <dd>The required <code>policy</code> element provides the guest policy
+      which must be maintained by the SEV 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 4 unsigned byte with the fields shown in Table:
+
+      <table class="top_table">
+        <tr>
+          <th> Bit(s) </th>
+          <th> Description </th>
+        </tr>
+        <tr>
+          <td> 0 </td>
+          <td> Debugging of the guest is disallowed when set </td>
+        </tr>
+        <tr>
+          <td> 1 </td>
+          <td> Sharing keys with other guests is disallowed when set </td>
+        </tr>
+        <tr>
+          <td> 2 </td>
+          <td> SEV-ES is required when set</td>
+        </tr>
+        <tr>
+          <td> 3 </td>
+          <td> Sending the guest to another platform is disallowed when set</td>
+        </tr>
+        <tr>
+          <td> 4 </td>
+          <td> The guest must not be transmitted to another platform that is
+               not in the domain when set. </td>
+        </tr>
+        <tr>
+          <td> 5 </td>
+          <td> The guest must not be transmitted to another platform that is
+               not SEV capable when set. </td>
+        </tr>
+        <tr>
+          <td> 6:15 </td>
+          <td> reserved </td>
+        </tr>
+        <tr>
+          <td> 16:32 </td>
+          <td> The guest must not be transmitted to another platform with a
+               lower firmware version. </td>
+        </tr>
+      </table>
+
+      </dd>
+      <dt><code>dh-cert</code></dt>
+      <dd>The optional <code>dh-cert</code> element provides the guest owners
+      base64 encoded Diffie-Hellman (DH) key. The key is used to negotiate a
+      master secret key between the SEV firmware and guest owner. This master
+      secret key is then used to establish a trusted channel between SEV
+      firmware and guest owner.
+      </dd>
+      <dt><code>session</code></dt>
+      <dd>The optional <code>session</code> element provides the guest owners
+      base64 encoded session blob defined in the SEV API spec.
+
+      See SEV spec LAUNCH_START section for the session blob format.
+      </dd>
+    </dl>
+
     <h2><a id="examples">Example configs</a></h2>
 
     <p>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 550fb10..1d06a5e 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -77,6 +77,9 @@
         <optional>
           <ref name='keywrap'/>
         </optional>
+        <optional>
+          <ref name='launch-security'/>
+        </optional>
       </interleave>
     </element>
   </define>
@@ -436,6 +439,40 @@
     </element>
   </define>
 
+  <define name="launch-security">
+    <element name="launch-security">
+      <attribute name="type">
+        <value>sev</value>
+      </attribute>
+      <interleave>
+        <element name="cbitpos">
+          <data type='unsignedInt'/>
+        </element>
+        <element name="reduced-phys-bits">
+          <data type='unsignedInt'/>
+        </element>
+        <element name="policy">
+          <ref name='hexuint'/>
+        </element>
+        <optional>
+          <element name="handle">
+            <ref name='unsignedInt'/>
+          </element>
+        </optional>
+        <optional>
+          <element name="dh-cert">
+            <data type="string"/>
+          </element>
+        </optional>
+        <optional>
+          <element name="session">
+            <data type="string"/>
+          </element>
+        </optional>
+      </interleave>
+    </element>
+  </define>
+
   <!--
       Enable or disable perf events for the domain. For each
       of the events the following rules apply:
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index ab93bb7..c4a609c 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -944,6 +944,10 @@ VIR_ENUM_IMPL(virDomainShmemModel, VIR_DOMAIN_SHMEM_MODEL_LAST,
               "ivshmem-plain",
               "ivshmem-doorbell")
 
+VIR_ENUM_IMPL(virDomainLaunchSecurity, VIR_DOMAIN_LAUNCH_SECURITY_LAST,
+              "",
+              "sev")
+
 static virClassPtr virDomainObjClass;
 static virClassPtr virDomainXMLOptionClass;
 static void virDomainObjDispose(void *obj);
@@ -2957,6 +2961,19 @@ virDomainCachetuneDefFree(virDomainCachetuneDefPtr cachetune)
 }
 
 
+static void
+virDomainSEVDefFree(virDomainSevDefPtr def)
+{
+    if (!def)
+        return;
+
+    VIR_FREE(def->dh_cert);
+    VIR_FREE(def->session);
+
+    VIR_FREE(def);
+}
+
+
 void virDomainDefFree(virDomainDefPtr def)
 {
     size_t i;
@@ -3139,6 +3156,8 @@ void virDomainDefFree(virDomainDefPtr def)
     if (def->namespaceData && def->ns.free)
         (def->ns.free)(def->namespaceData);
 
+    virDomainSEVDefFree(def->sev);
+
     xmlFreeNode(def->metadata);
 
     VIR_FREE(def);
@@ -15826,6 +15845,85 @@ virDomainMemoryTargetDefParseXML(xmlNodePtr node,
 }
 
 
+static virDomainSevDefPtr
+virDomainSEVDefParseXML(xmlNodePtr sevNode,
+                        xmlXPathContextPtr ctxt)
+{
+    char *tmp = NULL;
+    char *type = NULL;
+    xmlNodePtr save = ctxt->node;
+    virDomainSevDefPtr def;
+    unsigned long policy;
+
+    ctxt->node = sevNode;
+
+    if (VIR_ALLOC(def) < 0)
+        return NULL;
+
+    if (!(type = virXMLPropString(sevNode, "type"))) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("missing launch-security type"));
+        goto error;
+    }
+
+    def->sectype = virDomainLaunchSecurityTypeFromString(type);
+    switch ((virDomainLaunchSecurity) def->sectype) {
+    case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
+        break;
+    case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
+    case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
+    default:
+        virReportError(VIR_ERR_XML_ERROR,
+                       _("unsupported launch-security type '%s'"),
+                       type);
+        goto error;
+    }
+
+    if (virXPathUInt("string(./cbitpos)", ctxt, &def->cbitpos) < 0) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("failed to get launch-security cbitpos"));
+        goto error;
+    }
+
+    if (virXPathUInt("string(./reduced-phys-bits)", ctxt,
+                     &def->reduced_phys_bits) < 0) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("failed to get launch-security reduced-phys-bits"));
+        goto error;
+    }
+
+    if (virXPathULongHex("string(./policy)", ctxt, &policy) < 0) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("failed to get launch-security policy"));
+        goto error;
+    }
+
+    def->policy = policy;
+
+    if ((tmp = virXPathString("string(./dh-cert)", ctxt))) {
+        if (VIR_STRDUP(def->dh_cert, tmp) < 0)
+            goto error;
+
+        VIR_FREE(tmp);
+    }
+
+    if ((tmp = virXPathString("string(./session)", ctxt))) {
+        if (VIR_STRDUP(def->session, tmp) < 0)
+            goto error;
+
+        VIR_FREE(tmp);
+    }
+
+    ctxt->node = save;
+    return def;
+
+ error:
+    VIR_FREE(tmp);
+    virDomainSEVDefFree(def);
+    ctxt->node = save;
+    return NULL;
+}
+
 static virDomainMemoryDefPtr
 virDomainMemoryDefParseXML(virDomainXMLOptionPtr xmlopt,
                            xmlNodePtr memdevNode,
@@ -20631,6 +20729,13 @@ virDomainDefParseXML(xmlDocPtr xml,
     ctxt->node = node;
     VIR_FREE(nodes);
 
+    /* Check for SEV feature */
+    if ((node = virXPathNode("./launch-security", ctxt)) != NULL) {
+        def->sev = virDomainSEVDefParseXML(node, ctxt);
+        if (!def->sev)
+            goto error;
+    }
+
     /* analysis of memory devices */
     if ((n = virXPathNodeSet("./devices/memory", ctxt, &nodes)) < 0)
         goto error;
@@ -26642,6 +26747,32 @@ virDomainKeyWrapDefFormat(virBufferPtr buf, virDomainKeyWrapDefPtr keywrap)
     virBufferAddLit(buf, "</keywrap>\n");
 }
 
+
+static void
+virDomainSEVDefFormat(virBufferPtr buf, virDomainSevDefPtr sev)
+{
+    if (!sev)
+        return;
+
+    virBufferAsprintf(buf, "<launch-security type='%s'>\n",
+                      virDomainLaunchSecurityTypeToString(sev->sectype));
+    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);
+    virBufferAsprintf(buf, "<policy>0x%04x</policy>\n", sev->policy);
+    if (sev->dh_cert)
+        virBufferEscapeString(buf, "<dh-cert>%s</dh-cert>\n", sev->dh_cert);
+
+    if (sev->session)
+        virBufferEscapeString(buf, "<session>%s</session>\n", sev->session);
+
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</launch-security>\n");
+}
+
+
 static void
 virDomainPerfDefFormat(virBufferPtr buf, virDomainPerfDefPtr perf)
 {
@@ -27905,6 +28036,8 @@ virDomainDefFormatInternal(virDomainDefPtr def,
     if (def->keywrap)
         virDomainKeyWrapDefFormat(buf, def->keywrap);
 
+    virDomainSEVDefFormat(buf, def->sev);
+
     virBufferAdjustIndent(buf, -2);
     virBufferAddLit(buf, "</domain>\n");
 
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index a41cdce..fe7a6bb 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -142,6 +142,9 @@ typedef virDomainPanicDef *virDomainPanicDefPtr;
 typedef struct _virDomainMemoryDef virDomainMemoryDef;
 typedef virDomainMemoryDef *virDomainMemoryDefPtr;
 
+typedef struct _virDomainSevDef virDomainSevDef;
+typedef virDomainSevDef *virDomainSevDefPtr;
+
 /* forward declarations virDomainChrSourceDef, required by
  * virDomainNetDef
  */
@@ -2318,6 +2321,26 @@ struct _virDomainKeyWrapDef {
 };
 
 typedef enum {
+    VIR_DOMAIN_LAUNCH_SECURITY_NONE,
+    VIR_DOMAIN_LAUNCH_SECURITY_SEV,
+
+    VIR_DOMAIN_LAUNCH_SECURITY_LAST,
+} virDomainLaunchSecurity;
+
+typedef struct _virDomainSevDef virDomainSevDef;
+typedef virDomainSevDef *virDomainSevDefPtr;
+
+struct _virDomainSevDef {
+    int sectype; /* enum virDomainLaunchSecurity */
+    char *dh_cert;
+    char *session;
+    unsigned int policy;
+    unsigned int cbitpos;
+    unsigned int reduced_phys_bits;
+};
+
+
+typedef enum {
     VIR_DOMAIN_IOMMU_MODEL_INTEL,
 
     VIR_DOMAIN_IOMMU_MODEL_LAST
@@ -2508,6 +2531,9 @@ struct _virDomainDef {
 
     virDomainKeyWrapDefPtr keywrap;
 
+    /* SEV-specific domain */
+    virDomainSevDefPtr sev;
+
     /* Application-specific custom metadata */
     xmlNodePtr metadata;
 
@@ -3418,6 +3444,7 @@ VIR_ENUM_DECL(virDomainMemoryAllocation)
 VIR_ENUM_DECL(virDomainIOMMUModel)
 VIR_ENUM_DECL(virDomainVsockModel)
 VIR_ENUM_DECL(virDomainShmemModel)
+VIR_ENUM_DECL(virDomainLaunchSecurity)
 /* from libvirt.h */
 VIR_ENUM_DECL(virDomainState)
 VIR_ENUM_DECL(virDomainNostateReason)
diff --git a/tests/genericxml2xmlindata/launch-security-sev.xml b/tests/genericxml2xmlindata/launch-security-sev.xml
new file mode 100644
index 0000000..fb64e1e
--- /dev/null
+++ b/tests/genericxml2xmlindata/launch-security-sev.xml
@@ -0,0 +1,24 @@
+<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-1.0'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+  </devices>
+  <launch-security type='sev'>
+    <cbitpos>47</cbitpos>
+    <reduced-phys-bits>1</reduced-phys-bits>
+    <policy>0x0001</policy>
+    <dh-cert>AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA</dh-cert>
+    <session>IHAVENOIDEABUTJUSTPROVIDINGASTRING</session>
+  </launch-security>
+</domain>
diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c
index daad6e0..7a4fc1e 100644
--- a/tests/genericxml2xmltest.c
+++ b/tests/genericxml2xmltest.c
@@ -143,6 +143,8 @@ mymain(void)
 
     DO_TEST("tseg");
 
+    DO_TEST("launch-security-sev");
+
     virObjectUnref(caps);
     virObjectUnref(xmlopt);
 
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v9 07/11] qemu/cgroup: add /dev/sev in shared devices list
Posted by Brijesh Singh, 2 weeks ago
QEMU uses /dev/sev device while creating the SEV guest, lets add /dev/sev
in the list of devices allowed to be accessed by the QEMU.

Signed-off-by: Brijesh Singh <<brijesh.singh@amd.com>>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
---
 docs/drvqemu.html.in               | 3 ++-
 src/qemu/qemu.conf                 | 2 +-
 src/qemu/qemu_cgroup.c             | 2 +-
 src/qemu/test_libvirtd_qemu.aug.in | 1 +
 4 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/docs/drvqemu.html.in b/docs/drvqemu.html.in
index cbd159d..13adb5c 100644
--- a/docs/drvqemu.html.in
+++ b/docs/drvqemu.html.in
@@ -396,7 +396,8 @@ chmod o+x /path/to/directory
 /dev/null, /dev/full, /dev/zero,
 /dev/random, /dev/urandom,
 /dev/ptmx, /dev/kvm, /dev/kqemu,
-/dev/rtc, /dev/hpet, /dev/net/tun
+/dev/rtc, /dev/hpet, /dev/net/tun,
+/dev/sev
 </pre>
 
     <p>
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index 76afe88..cd57b3c 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -485,7 +485,7 @@
 #    "/dev/null", "/dev/full", "/dev/zero",
 #    "/dev/random", "/dev/urandom",
 #    "/dev/ptmx", "/dev/kvm", "/dev/kqemu",
-#    "/dev/rtc","/dev/hpet"
+#    "/dev/rtc","/dev/hpet", "/dev/sev"
 #]
 #
 # RDMA migration requires the following extra files to be added to the list:
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 12b3f3b..43c5ae8 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -48,7 +48,7 @@ const char *const defaultDeviceACL[] = {
     "/dev/null", "/dev/full", "/dev/zero",
     "/dev/random", "/dev/urandom",
     "/dev/ptmx", "/dev/kvm", "/dev/kqemu",
-    "/dev/rtc", "/dev/hpet",
+    "/dev/rtc", "/dev/hpet", "/dev/sev",
     NULL,
 };
 #define DEVICE_PTY_MAJOR 136
diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in
index 61690ee..f1e8806 100644
--- a/src/qemu/test_libvirtd_qemu.aug.in
+++ b/src/qemu/test_libvirtd_qemu.aug.in
@@ -62,6 +62,7 @@ module Test_libvirtd_qemu =
     { "8" = "/dev/kqemu" }
     { "9" = "/dev/rtc" }
     { "10" = "/dev/hpet" }
+    { "11" = "/dev/sev" }
 }
 { "save_image_format" = "raw" }
 { "dump_image_format" = "raw" }
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v9 08/11] qemu: add support to launch SEV guest
Posted by Brijesh Singh, 2 weeks ago
QEMU >= 2.12 provides 'sev-guest' object which is used to launch encrypted
VMs on AMD platform using SEV feature. The various inputs required to
launch SEV guest is provided through the <launch-security> tag. A typical
SEV guest launch command line looks like this:

# $QEMU ...\
  -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=5 ...\
  -machine memory-encryption=sev0 \

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
---
 src/qemu/qemu_command.c                         | 41 ++++++++++++++++
 src/qemu/qemu_process.c                         | 62 +++++++++++++++++++++++++
 tests/qemuxml2argvdata/launch-security-sev.args | 29 ++++++++++++
 tests/qemuxml2argvdata/launch-security-sev.xml  | 37 +++++++++++++++
 tests/qemuxml2argvtest.c                        |  4 ++
 5 files changed, 173 insertions(+)
 create mode 100644 tests/qemuxml2argvdata/launch-security-sev.args
 create mode 100644 tests/qemuxml2argvdata/launch-security-sev.xml

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index bd54d17..6a95344 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7287,6 +7287,9 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
         virQEMUCapsGet(qemuCaps, QEMU_CAPS_LOADPARM))
         qemuAppendLoadparmMachineParm(&buf, def);
 
+    if (def->sev)
+        virBufferAddLit(&buf, ",memory-encryption=sev0");
+
     virCommandAddArgBuffer(cmd, &buf);
 
     ret = 0;
@@ -9687,6 +9690,41 @@ qemuBuildTPMCommandLine(virCommandPtr cmd,
     return 0;
 }
 
+static int
+qemuBuildSevCommandLine(virDomainObjPtr vm, virCommandPtr cmd,
+                        virDomainSevDefPtr sev)
+{
+    virBuffer obj = VIR_BUFFER_INITIALIZER;
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    char *path = NULL;
+
+    if (!sev)
+        return 0;
+
+    VIR_DEBUG("policy=0x%x cbitpos=%d reduced_phys_bits=%d",
+              sev->policy, sev->cbitpos, sev->reduced_phys_bits);
+
+    virBufferAsprintf(&obj, "sev-guest,id=sev0,cbitpos=%d", sev->cbitpos);
+    virBufferAsprintf(&obj, ",reduced-phys-bits=%d", sev->reduced_phys_bits);
+    virBufferAsprintf(&obj, ",policy=0x%x", sev->policy);
+
+    if (sev->dh_cert) {
+        if (virAsprintf(&path, "%s/dh_cert.base64", priv->libDir) < 0)
+            return -1;
+        virBufferAsprintf(&obj, ",dh-cert-file=%s", path);
+        VIR_FREE(path);
+    }
+
+    if (sev->session) {
+        if (virAsprintf(&path, "%s/session.base64", priv->libDir) < 0)
+            return -1;
+        virBufferAsprintf(&obj, ",session-file=%s", path);
+        VIR_FREE(path);
+    }
+
+    virCommandAddArgList(cmd, "-object", virBufferContentAndReset(&obj), NULL);
+    return 0;
+}
 
 static int
 qemuBuildVMCoreInfoCommandLine(virCommandPtr cmd,
@@ -10283,6 +10321,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
     if (qemuBuildVMCoreInfoCommandLine(cmd, def, qemuCaps) < 0)
         goto error;
 
+    if (qemuBuildSevCommandLine(vm, cmd, def->sev) < 0)
+        goto error;
+
     if (snapshot)
         virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL);
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 1606f4c..480bc8c 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5826,6 +5826,65 @@ qemuProcessPrepareDomain(virQEMUDriverPtr driver,
 
 
 static int
+qemuBuildSevCreateFile(const char *configDir,
+                       const char *name,
+                       const char *data)
+{
+    char *configFile;
+
+    if (!(configFile = virFileBuildPath(configDir, name, ".base64")))
+        return -1;
+
+    if (virFileRewriteStr(configFile, S_IRUSR | S_IWUSR, data) < 0) {
+        virReportSystemError(errno, _("failed to write data to config '%s'"),
+                             configFile);
+        goto error;
+    }
+
+    VIR_FREE(configFile);
+    return 0;
+
+ error:
+    VIR_FREE(configFile);
+    return -1;
+}
+
+
+static int
+qemuProcessPrepareSevGuestInput(virDomainObjPtr vm)
+{
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    virDomainDefPtr def = vm->def;
+    virQEMUCapsPtr qemuCaps = priv->qemuCaps;
+    virDomainSevDefPtr sev = def->sev;
+
+    if (!sev)
+        return 0;
+
+    VIR_DEBUG("Prepare SEV guest");
+
+    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Domain %s asked for 'sev' launch but this "
+                          "QEMU does not support SEV feature"), vm->def->name);
+        return -1;
+    }
+
+    if (sev->dh_cert) {
+        if (qemuBuildSevCreateFile(priv->libDir, "dh_cert", sev->dh_cert) < 0)
+            return -1;
+    }
+
+    if (sev->session) {
+        if (qemuBuildSevCreateFile(priv->libDir, "session", sev->session) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
+
+static int
 qemuProcessPrepareHostStorage(virQEMUDriverPtr driver,
                               virDomainObjPtr vm,
                               unsigned int flags)
@@ -5987,6 +6046,9 @@ qemuProcessPrepareHost(virQEMUDriverPtr driver,
     if (qemuExtDevicesPrepareHost(driver, vm->def) < 0)
         goto cleanup;
 
+    if (qemuProcessPrepareSevGuestInput(vm) < 0)
+        goto cleanup;
+
     ret = 0;
  cleanup:
     virObjectUnref(cfg);
diff --git a/tests/qemuxml2argvdata/launch-security-sev.args b/tests/qemuxml2argvdata/launch-security-sev.args
new file mode 100644
index 0000000..db0be1a
--- /dev/null
+++ b/tests/qemuxml2argvdata/launch-security-sev.args
@@ -0,0 +1,29 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name QEMUGuest1 \
+-S \
+-machine pc-1.0,accel=kvm,usb=off,dump-guest-core=off,memory-encryption=sev0 \
+-m 214 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot c \
+-usb \
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1,policy=0x1,\
+dh-cert-file=/tmp/lib/domain--1-QEMUGuest1/dh_cert.base64,\
+session-file=/tmp/lib/domain--1-QEMUGuest1/session.base64
diff --git a/tests/qemuxml2argvdata/launch-security-sev.xml b/tests/qemuxml2argvdata/launch-security-sev.xml
new file mode 100644
index 0000000..5ae83f6
--- /dev/null
+++ b/tests/qemuxml2argvdata/launch-security-sev.xml
@@ -0,0 +1,37 @@
+<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-1.0'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <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'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='none'/>
+  </devices>
+  <launch-security type='sev'>
+    <cbitpos>47</cbitpos>
+    <reduced-phys-bits>1</reduced-phys-bits>
+    <policy>0x0001</policy>
+    <dh-cert>AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA</dh-cert>
+    <session>IHAVENOIDEABUTJUSTPROVIDINGASTRING</session>
+  </launch-security>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index c81caec..f630185 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -2897,6 +2897,10 @@ mymain(void)
     DO_TEST_CAPS_LATEST("vhost-vsock");
     DO_TEST_CAPS_LATEST("vhost-vsock-auto");
 
+    DO_TEST("launch-security-sev",
+            QEMU_CAPS_KVM,
+            QEMU_CAPS_SEV_GUEST);
+
     if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
         virFileDeleteTree(fakerootdir);
 
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v9 09/11] libvirt: Introduce virDomainGetLaunchSecurityInfo public API
Posted by Brijesh Singh, 2 weeks ago
The API can be used outside the libvirt to get the launch security
information. When SEV is enabled, the API can be used to get the
measurement of the launch process.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
---
 include/libvirt/libvirt-domain.h | 17 ++++++++++++++
 src/driver-hypervisor.h          |  8 +++++++
 src/libvirt-domain.c             | 48 ++++++++++++++++++++++++++++++++++++++++
 src/libvirt_public.syms          |  1 +
 4 files changed, 74 insertions(+)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index da773b7..3ef7c24 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -4767,4 +4767,21 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
                                 unsigned int action,
                                 unsigned int flags);
 
+/**
+ * Launch Security API
+ */
+
+/**
+ * VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT:
+ *
+ * Macro represents the launch measurement of the SEV guest,
+ * as VIR_TYPED_PARAM_STRING.
+ */
+# define VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT "sev-measurement"
+
+int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
+                                   virTypedParameterPtr *params,
+                                   int *nparams,
+                                   unsigned int flags);
+
 #endif /* __VIR_LIBVIRT_DOMAIN_H__ */
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index c50d2a0..eef31eb 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1315,6 +1315,13 @@ typedef int
                         int *nparams,
                         unsigned int flags);
 
+typedef int
+(*virDrvDomainGetLaunchSecurityInfo)(virDomainPtr domain,
+                                        virTypedParameterPtr *params,
+                                        int *nparams,
+                                        unsigned int flags);
+
+
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;
 
@@ -1564,6 +1571,7 @@ struct _virHypervisorDriver {
     virDrvConnectCompareHypervisorCPU connectCompareHypervisorCPU;
     virDrvConnectBaselineHypervisorCPU connectBaselineHypervisorCPU;
     virDrvNodeGetSEVInfo nodeGetSEVInfo;
+    virDrvDomainGetLaunchSecurityInfo domainGetLaunchSecurityInfo;
 };
 
 
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index d44b553..dcfc7d4 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -12154,3 +12154,51 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
     virDispatchError(domain->conn);
     return -1;
 }
+
+/**
+ * virDomainGetLaunchSecurityInfo:
+ * @domain: a domain object
+ * @params: where to store security info
+ * @nparams: number of items in @params
+ * @flags: currently used, set to 0.
+ *
+ * Get the launch security info. In case of the SEV guest, this will
+ * return the launch measurement.
+ *
+ * Returns -1 in case of failure, 0 in case of success.
+ */
+int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
+                                   virTypedParameterPtr *params,
+                                   int *nparams,
+                                   unsigned int flags)
+{
+    virConnectPtr conn = domain->conn;
+
+    VIR_DOMAIN_DEBUG(domain, "params=%p, nparams=%p flags=0x%x",
+                     params, nparams, flags);
+
+    virResetLastError();
+
+    virCheckDomainReturn(domain, -1);
+    virCheckNonNullArgGoto(params, error);
+    virCheckNonNullArgGoto(nparams, error);
+    virCheckReadOnlyGoto(conn->flags, error);
+
+    if (VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn,
+                                 VIR_DRV_FEATURE_TYPED_PARAM_STRING))
+        flags |= VIR_TYPED_PARAM_STRING_OKAY;
+
+    if (conn->driver->domainGetLaunchSecurityInfo) {
+        int ret;
+        ret = conn->driver->domainGetLaunchSecurityInfo(domain, params,
+                                                        nparams, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+    virReportUnsupportedError();
+
+ error:
+    virDispatchError(domain->conn);
+    return -1;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 524d5fd..3bf3c3f 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -797,6 +797,7 @@ LIBVIRT_4.5.0 {
         virGetLastErrorCode;
         virGetLastErrorDomain;
         virNodeGetSEVInfo;
+        virDomainGetLaunchSecurityInfo;
 } LIBVIRT_4.4.0;
 
 # .... define new API here using predicted next version number ....
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v9 10/11] remote: implement the remote protocol for launch security
Posted by Brijesh Singh, 2 weeks ago
Add remote support for launch security info.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
---
 src/remote/remote_daemon_dispatch.c | 47 +++++++++++++++++++++++++++++++++++++
 src/remote/remote_driver.c          | 40 +++++++++++++++++++++++++++++++
 src/remote/remote_protocol.x        | 19 ++++++++++++++-
 src/remote_protocol-structs         | 11 +++++++++
 4 files changed, 116 insertions(+), 1 deletion(-)

diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c
index 959367f..f1a5ba2 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -3110,6 +3110,53 @@ remoteDispatchNodeGetMemoryStats(virNetServerPtr server ATTRIBUTE_UNUSED,
 }
 
 static int
+remoteDispatchDomainGetLaunchSecurityInfo(virNetServerPtr server ATTRIBUTE_UNUSED,
+                                          virNetServerClientPtr client ATTRIBUTE_UNUSED,
+                                          virNetMessagePtr msg ATTRIBUTE_UNUSED,
+                                          virNetMessageErrorPtr rerr,
+                                          remote_domain_get_launch_security_info_args *args,
+                                          remote_domain_get_launch_security_info_ret *ret)
+{
+    virDomainPtr dom = NULL;
+    virTypedParameterPtr params = NULL;
+    int nparams = 0;
+    int rv = -1;
+    struct daemonClientPrivate *priv =
+        virNetServerClientGetPrivateData(client);
+
+    if (!priv->conn) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+        goto cleanup;
+    }
+
+    if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+        goto cleanup;
+
+    if (virDomainGetLaunchSecurityInfo(dom, &params, &nparams, args->flags) < 0)
+        goto cleanup;
+
+    if (nparams > REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nparams too large"));
+        goto cleanup;
+    }
+
+    if (virTypedParamsSerialize(params, nparams,
+                                (virTypedParameterRemotePtr *) &ret->params.params_val,
+                                &ret->params.params_len,
+                                args->flags) < 0)
+        goto cleanup;
+
+    rv = 0;
+
+ cleanup:
+    if (rv < 0)
+        virNetMessageSaveError(rerr);
+    virTypedParamsFree(params, nparams);
+    virObjectUnref(dom);
+    return rv;
+}
+
+static int
 remoteDispatchDomainGetPerfEvents(virNetServerPtr server ATTRIBUTE_UNUSED,
                                   virNetServerClientPtr client ATTRIBUTE_UNUSED,
                                   virNetMessagePtr msg ATTRIBUTE_UNUSED,
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 8ac7264..995d440 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -1966,6 +1966,45 @@ remoteDomainGetNumaParameters(virDomainPtr domain,
 }
 
 static int
+remoteDomainGetLaunchSecurityInfo(virDomainPtr domain,
+                                  virTypedParameterPtr *params,
+                                  int *nparams,
+                                  unsigned int flags)
+{
+    int rv = -1;
+    remote_domain_get_launch_security_info_args args;
+    remote_domain_get_launch_security_info_ret ret;
+    struct private_data *priv = domain->conn->privateData;
+
+    remoteDriverLock(priv);
+
+    make_nonnull_domain(&args.dom, domain);
+    args.flags = flags;
+
+    memset(&ret, 0, sizeof(ret));
+    if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_LAUNCH_SECURITY_INFO,
+             (xdrproc_t) xdr_remote_domain_get_launch_security_info_args, (char *) &args,
+             (xdrproc_t) xdr_remote_domain_get_launch_security_info_ret, (char *) &ret) == -1)
+        goto done;
+
+    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.params.params_val,
+                                  ret.params.params_len,
+                                  REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX,
+                                  params,
+                                  nparams) < 0)
+        goto cleanup;
+
+    rv = 0;
+
+ cleanup:
+    xdr_free((xdrproc_t) xdr_remote_domain_get_launch_security_info_ret,
+             (char *) &ret);
+ done:
+    remoteDriverUnlock(priv);
+    return rv;
+}
+
+static int
 remoteDomainGetPerfEvents(virDomainPtr domain,
                           virTypedParameterPtr *params,
                           int *nparams,
@@ -8491,6 +8530,7 @@ static virHypervisorDriver hypervisor_driver = {
     .connectCompareHypervisorCPU = remoteConnectCompareHypervisorCPU, /* 4.4.0 */
     .connectBaselineHypervisorCPU = remoteConnectBaselineHypervisorCPU, /* 4.4.0 */
     .nodeGetSEVInfo = remoteNodeGetSEVInfo, /* 4.5.0 */
+    .domainGetLaunchSecurityInfo = remoteDomainGetLaunchSecurityInfo /* 4.5.0 */
 };
 
 static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index ec72afa..162cf5e 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -256,6 +256,9 @@ const REMOTE_DOMAIN_GUEST_VCPU_PARAMS_MAX = 64;
 /* Upper limit on number of SEV parameters */
 const REMOTE_NODE_SEV_INFO_MAX = 64;
 
+/* Upper limit on number of launch security information entries */
+const REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX = 64;
+
 /* UUID.  VIR_UUID_BUFLEN definition comes from libvirt.h */
 typedef opaque remote_uuid[VIR_UUID_BUFLEN];
 
@@ -3493,6 +3496,14 @@ struct remote_node_get_sev_info_ret {
     int nparams;
 };
 
+struct remote_domain_get_launch_security_info_args {
+    remote_nonnull_domain dom;
+    unsigned int flags;
+};
+
+struct remote_domain_get_launch_security_info_ret {
+    remote_typed_param params<REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX>;
+};
 
 /*----- Protocol. -----*/
 
@@ -6207,5 +6218,11 @@ enum remote_procedure {
      * @generate: none
      * @acl: connect:read
      */
-    REMOTE_PROC_NODE_GET_SEV_INFO = 395
+    REMOTE_PROC_NODE_GET_SEV_INFO = 395,
+
+    /**
+     * @generate: none
+     * @acl: domain:read
+     */
+    REMOTE_PROC_DOMAIN_GET_LAUNCH_SECURITY_INFO = 396
 };
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index dfc3624..0c75ad2 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -2918,6 +2918,16 @@ struct remote_node_get_sev_info_ret {
         } params;
         int                        nparams;
 };
+struct remote_domain_get_launch_security_info_args {
+        remote_nonnull_domain      dom;
+        u_int                      flags;
+};
+struct remote_domain_get_launch_security_info_ret {
+        struct {
+                u_int              params_len;
+                remote_typed_param * params_val;
+        } params;
+};
 enum remote_procedure {
         REMOTE_PROC_CONNECT_OPEN = 1,
         REMOTE_PROC_CONNECT_CLOSE = 2,
@@ -3314,4 +3324,5 @@ enum remote_procedure {
         REMOTE_PROC_CONNECT_COMPARE_HYPERVISOR_CPU = 393,
         REMOTE_PROC_CONNECT_BASELINE_HYPERVISOR_CPU = 394,
         REMOTE_PROC_NODE_GET_SEV_INFO = 395,
+        REMOTE_PROC_DOMAIN_GET_LAUNCH_SECURITY_INFO = 396,
 };
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v9 11/11] qemu: Implement the driver backend for virDomainGetLaunchSecurityInfo
Posted by Brijesh Singh, 2 weeks ago
This patch implements the internal driver API for launch event into
qemu driver. When SEV is enabled, execute 'query-sev-launch-measurement'
to get the measurement of memory encrypted through launch sequence.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
---
 src/qemu/qemu_driver.c       | 69 ++++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor.c      |  8 +++++
 src/qemu/qemu_monitor.h      |  3 ++
 src/qemu/qemu_monitor_json.c | 42 +++++++++++++++++++++++++++
 src/qemu/qemu_monitor_json.h |  2 ++
 5 files changed, 124 insertions(+)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 264c47d..3f1eb8a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -21505,6 +21505,74 @@ qemuNodeGetSEVInfo(virConnectPtr conn,
 }
 
 
+static int
+qemuDomainGetSEVMeasurement(virQEMUDriverPtr driver,
+                            virDomainObjPtr vm,
+                            virTypedParameterPtr *params,
+                            int *nparams,
+                            unsigned int flags)
+{
+    int ret = -1;
+    char *tmp;
+    int maxpar = 0;
+
+    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
+        return -1;
+
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
+        goto endjob;
+
+    tmp = qemuMonitorGetSEVMeasurement(QEMU_DOMAIN_PRIVATE(vm)->mon);
+    if (tmp == NULL)
+        goto endjob;
+
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        goto endjob;
+
+    if (virTypedParamsAddString(params, nparams, &maxpar,
+                                VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT,
+                                tmp) < 0)
+        goto endjob;
+
+    VIR_FREE(tmp);
+    ret = 0;
+
+ endjob:
+    qemuDomainObjEndJob(driver, vm);
+    return ret;
+}
+
+
+static int
+qemuDomainGetLaunchSecurityInfo(virDomainPtr domain,
+                                virTypedParameterPtr *params,
+                                int *nparams,
+                                unsigned int flags)
+{
+    virQEMUDriverPtr driver = domain->conn->privateData;
+    virDomainObjPtr vm;
+    int ret = -1;
+
+    if (!(vm = qemuDomObjFromDomain(domain)))
+        goto cleanup;
+
+    if (virDomainGetLaunchSecurityInfoEnsureACL(domain->conn, vm->def) < 0)
+        goto cleanup;
+
+    if (vm->def->sev) {
+        if (qemuDomainGetSEVMeasurement(driver, vm, params, nparams, flags) < 0)
+            goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    virDomainObjEndAPI(&vm);
+    return ret;
+}
+
 static virHypervisorDriver qemuHypervisorDriver = {
     .name = QEMU_DRIVER_NAME,
     .connectURIProbe = qemuConnectURIProbe,
@@ -21729,6 +21797,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
     .connectCompareHypervisorCPU = qemuConnectCompareHypervisorCPU, /* 4.4.0 */
     .connectBaselineHypervisorCPU = qemuConnectBaselineHypervisorCPU, /* 4.4.0 */
     .nodeGetSEVInfo = qemuNodeGetSEVInfo, /* 4.5.0 */
+    .domainGetLaunchSecurityInfo = qemuDomainGetLaunchSecurityInfo, /* 4.5.0 */
 };
 
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index fd6bce9..6e0cdca 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4297,3 +4297,11 @@ qemuMonitorBlockdevDel(qemuMonitorPtr mon,
 
     return qemuMonitorJSONBlockdevDel(mon, nodename);
 }
+
+char *
+qemuMonitorGetSEVMeasurement(qemuMonitorPtr mon)
+{
+    QEMU_CHECK_MONITOR_NULL(mon);
+
+    return qemuMonitorJSONGetSEVMeasurement(mon);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 75d5d98..7432997 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1142,4 +1142,7 @@ int qemuMonitorBlockdevAdd(qemuMonitorPtr mon,
 int qemuMonitorBlockdevDel(qemuMonitorPtr mon,
                            const char *nodename);
 
+char *
+qemuMonitorGetSEVMeasurement(qemuMonitorPtr mon);
+
 #endif /* QEMU_MONITOR_H */
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index ba0da9a..c5480a2 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -7994,3 +7994,45 @@ qemuMonitorJSONBlockdevDel(qemuMonitorPtr mon,
     virJSONValueFree(reply);
     return ret;
 }
+
+/**
+ * The function is used to retrieve the measurement of a SEV guest.
+ * The measurement is signature of the memory contents that was encrypted
+ * through the SEV launch flow.
+ *
+ * A example JSON output:
+ *
+ * { "execute" : "query-sev-launch-measure" }
+ * { "return" : { "data" : "4l8LXeNlSPUDlXPJG5966/8%YZ" } }
+ */
+char *
+qemuMonitorJSONGetSEVMeasurement(qemuMonitorPtr mon)
+{
+    const char *tmp;
+    char *measurement = NULL;
+    virJSONValuePtr cmd;
+    virJSONValuePtr reply = NULL;
+    virJSONValuePtr data;
+
+    if (!(cmd = qemuMonitorJSONMakeCommand("query-sev-launch-measure", NULL)))
+         return NULL;
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        goto cleanup;
+
+    if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
+        goto cleanup;
+
+    data = virJSONValueObjectGetObject(reply, "return");
+
+    if (!(tmp = virJSONValueObjectGetString(data, "data")))
+        goto cleanup;
+
+    if (VIR_STRDUP(measurement, tmp) < 0)
+        goto cleanup;
+
+ cleanup:
+    virJSONValueFree(cmd);
+    virJSONValueFree(reply);
+    return measurement;
+}
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 4c10574..6bc0dd3 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -343,6 +343,8 @@ int qemuMonitorJSONGetBlockIoThrottle(qemuMonitorPtr mon,
 
 int qemuMonitorJSONSystemWakeup(qemuMonitorPtr mon);
 
+char *qemuMonitorJSONGetSEVMeasurement(qemuMonitorPtr mon);
+
 int qemuMonitorJSONGetVersion(qemuMonitorPtr mon,
                               int *major,
                               int *minor,
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list