[PATCH v1 0/8] Introducing TPM Proxy device support

Hello, This series implements a new device type for Libvirt called "TPM Proxy". This device acts as a proxy for TPM requisitions that the guest can make for an existing TPM Resource Manager in the host. The TPM Resource Manager multiplexes TPM access to multiple processes, allowing more than one process (guest) to use the host TPM at the same time. A guest using a TPM Proxy device does not have access to all possible TPM features. In that case the guest will need to assign a vTPM device (tpm-spapr for PPC64). There is no restrictions of using both a vTPM and a TPM Proxy device at the same time, but only one TPM Proxy is allowed per guest. At this moment, this device exists only for QEMU pSeries guests. A "model" field was added device to allow more models to be added when/if other architectures implements it. Daniel Henrique Barboza (8): docs: documentation and schema for the new TPM Proxy device qemu: Extend QEMU capabilities with 'spapr-tpm-proxy' conf, qemu: adding VIR_DOMAIN_DEVICE_TPMPROXY device domain_conf.c: XML parsing for VIR_DOMAIN_DEVICE_TPMPROXY tests: add test for domain XML with TPM Proxy device model qemu: build command line for the TPM Proxy device tests/qemuxml2argvtest.c: add TPM Proxy command line test docs/news.xml: update for the new TPM Proxy device docs/formatdomain.html.in | 42 +++++ docs/news.xml | 14 ++ docs/schemas/domaincommon.rng | 18 ++ src/conf/domain_capabilities.c | 1 + src/conf/domain_conf.c | 160 ++++++++++++++++++ src/conf/domain_conf.h | 18 ++ src/conf/virconftypes.h | 3 + src/libvirt_private.syms | 2 + src/qemu/qemu_alias.c | 16 ++ src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 21 +++ src/qemu/qemu_domain.c | 14 ++ src/qemu/qemu_domain_address.c | 2 + src/qemu/qemu_driver.c | 5 + src/qemu/qemu_hotplug.c | 3 + src/qemu/qemu_validate.c | 37 ++++ .../qemucapabilitiesdata/caps_4.2.0.ppc64.xml | 1 + .../qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + tests/qemuxml2argvdata/ppc64-tpmproxy.args | 28 +++ tests/qemuxml2argvdata/ppc64-tpmproxy.xml | 31 ++++ tests/qemuxml2argvtest.c | 4 + tests/qemuxml2xmloutdata/ppc64-tpmproxy.xml | 37 ++++ tests/qemuxml2xmltest.c | 4 + 24 files changed, 465 insertions(+) create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy.args create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy.xml create mode 100644 tests/qemuxml2xmloutdata/ppc64-tpmproxy.xml -- 2.26.2

QEMU 4.1.0 introduced a new device type called TPM Proxy, currently implemented by PPC64 guests via a new virtual device called 'spapr-tpm-proxy' (see QEMU 0fb6bd073230 for more info). The TPM Proxy device interacts with a TPM Resource Manager, a host device capable of multiplexing the host TPM with multiple processes. This allows multiple guests to access some TPM features at the same time. Note that this mode of operation does not provide full TPM features to be available for the guest - for that case the guest still needs to assign a vTPM device (tpm-spapr for PPC64 guests). Although redundant, there is currently no technical limitation for a guest to assign both a vTPM and a TPM Proxy at the same time. This patch adds documentation and schema for the new TPM Proxy device. An example of a TPM Proxy device connected to a TPM Resource Manager '/dev/tpmrm0' will look like this: <tpmproxy model='spapr-tpm-proxy'> <device path='/dev/tpmrm0'/> </tpmproxy> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- docs/formatdomain.html.in | 42 +++++++++++++++++++++++++++++++++++ docs/schemas/domaincommon.rng | 18 +++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 23eb029234..650e2a8c6e 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -8849,6 +8849,48 @@ qemu-kvm -net nic,model=? /dev/null </dd> </dl> + <h4><a id="elementsTpmProxy">TPM Proxy device</a></h4> + + <p> + The TPM Proxy device allows a QEMU guest to interact with an + existing TPM Resource Manager in the host. A TPM Resource Manager + enables a TPM device to be securely multiplexed across several + guests. Only one TPM Proxy device is allowed per guest. + </p> + <p> + A guest using the TPM Proxy device does not have access to all the + features a TPM device provides. This means that a guest can have both + a TPM Proxy and a TPM device assigned at the same time. + </p> + <p> + The TPM Proxy device is currently available only for pSeries guests. + <span class="since">since 6.4.0</span> + </p> + <p> + Example: usage of the TPM Proxy device + </p> +<pre> +... +<devices> + <tpmproxy model='spapr-tpm-proxy'> + <device path='/dev/tpmrm0'/> + </tpmproxy> +</devices> +... +</pre> + + <dl> + <dt><code>model</code></dt> + <dd> + <p> + The <code>model</code> attribute specifies what device + model QEMU provides to the guest. If no model name is provided, + <code>spapr-tpm-proxy</code> will automatically be chosen for + PPC64 architectures. + </p> + </dd> + </dl> + <h4><a id="elementsNVRAM">NVRAM device</a></h4> <p> nvram device is always added to pSeries guest on PPC64, and its address diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 9d60b090f3..44bbd92244 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4676,6 +4676,23 @@ </optional> </define> + <define name="tpmproxy"> + <element name="tpmproxy"> + <optional> + <attribute name="model"> + <choice> + <value>spapr-tpm-proxy</value> + </choice> + </attribute> + </optional> + <element name="device"> + <attribute name="path"> + <ref name="filePath"/> + </attribute> + </element> + </element> + </define> + <define name="vsock"> <element name="vsock"> <optional> @@ -5279,6 +5296,7 @@ <ref name="tpm"/> <ref name="shmem"/> <ref name="memorydev"/> + <ref name="tpmproxy"/> </choice> </zeroOrMore> <optional> -- 2.26.2

On 5/8/20 8:06 AM, Daniel Henrique Barboza wrote:
QEMU 4.1.0 introduced a new device type called TPM Proxy, currently implemented by PPC64 guests via a new virtual device called 'spapr-tpm-proxy' (see QEMU 0fb6bd073230 for more info).
The TPM Proxy device interacts with a TPM Resource Manager, a host device capable of multiplexing the host TPM with multiple processes. This allows multiple guests to access some TPM features at the same time. Note that this mode of operation does not provide full TPM features to be available for the guest - for that case the guest still needs to assign a vTPM device (tpm-spapr for PPC64 guests). Although redundant, there is currently no technical limitation for a guest to assign both a vTPM and a TPM Proxy at the same time.
This patch adds documentation and schema for the new TPM Proxy device. An example of a TPM Proxy device connected to a TPM Resource Manager '/dev/tpmrm0' will look like this:
<tpmproxy model='spapr-tpm-proxy'> <device path='/dev/tpmrm0'/> </tpmproxy>
We already have: <backend type='passthrough'> <device path='/dev/tpm0'/> </backend> Now what is the difference between this tpm-proxy device using /dev/tpmrm0 and having the existing passthrough device use /dev/tpmrm0? Is there any useful filtering going on by the tpm-proxy device? If not, why not use passthrough with /dev/tpmrm0? Stefan

On Fri, May 08, 2020 at 04:30:09PM -0400, Stefan Berger wrote:
On 5/8/20 8:06 AM, Daniel Henrique Barboza wrote:
QEMU 4.1.0 introduced a new device type called TPM Proxy, currently implemented by PPC64 guests via a new virtual device called 'spapr-tpm-proxy' (see QEMU 0fb6bd073230 for more info).
The TPM Proxy device interacts with a TPM Resource Manager, a host device capable of multiplexing the host TPM with multiple processes. This allows multiple guests to access some TPM features at the same time. Note that this mode of operation does not provide full TPM features to be available for the guest - for that case the guest still needs to assign a vTPM device (tpm-spapr for PPC64 guests). Although redundant, there is currently no technical limitation for a guest to assign both a vTPM and a TPM Proxy at the same time.
This patch adds documentation and schema for the new TPM Proxy device. An example of a TPM Proxy device connected to a TPM Resource Manager '/dev/tpmrm0' will look like this:
<tpmproxy model='spapr-tpm-proxy'> <device path='/dev/tpmrm0'/> </tpmproxy>
We already have:
<backend type='passthrough'> <device path='/dev/tpm0'/> </backend>
Now what is the difference between this tpm-proxy device using /dev/tpmrm0 and having the existing passthrough device use /dev/tpmrm0? Is there any useful filtering going on by the tpm-proxy device? If not, why not use passthrough with /dev/tpmrm0?
It's a different guest side interface, the H_TPM_COMM hypercall instead of the other PAPR TPM interface. To which "why?" is a very good question, but it's there now, so there's not much we can do about it. -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson

On Mon, May 11, 2020 at 11:22:57AM +1000, David Gibson wrote:
On Fri, May 08, 2020 at 04:30:09PM -0400, Stefan Berger wrote:
On 5/8/20 8:06 AM, Daniel Henrique Barboza wrote:
QEMU 4.1.0 introduced a new device type called TPM Proxy, currently implemented by PPC64 guests via a new virtual device called 'spapr-tpm-proxy' (see QEMU 0fb6bd073230 for more info).
The TPM Proxy device interacts with a TPM Resource Manager, a host device capable of multiplexing the host TPM with multiple processes. This allows multiple guests to access some TPM features at the same time. Note that this mode of operation does not provide full TPM features to be available for the guest - for that case the guest still needs to assign a vTPM device (tpm-spapr for PPC64 guests). Although redundant, there is currently no technical limitation for a guest to assign both a vTPM and a TPM Proxy at the same time.
This patch adds documentation and schema for the new TPM Proxy device. An example of a TPM Proxy device connected to a TPM Resource Manager '/dev/tpmrm0' will look like this:
<tpmproxy model='spapr-tpm-proxy'> <device path='/dev/tpmrm0'/> </tpmproxy>
We already have:
<backend type='passthrough'> <device path='/dev/tpm0'/> </backend>
Now what is the difference between this tpm-proxy device using /dev/tpmrm0 and having the existing passthrough device use /dev/tpmrm0? Is there any useful filtering going on by the tpm-proxy device? If not, why not use passthrough with /dev/tpmrm0?
It's a different guest side interface, the H_TPM_COMM hypercall instead of the other PAPR TPM interface. To which "why?" is a very good question, but it's there now, so there's not much we can do about it.
That's ok. Even though its a different guest interface, it is still conceptually a TPM device at a high level, so we should be reusing the existing <tpm> device type. At most we should add a new backend type 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 :|

On 5/11/20 6:57 AM, Daniel P. Berrangé wrote:
On Mon, May 11, 2020 at 11:22:57AM +1000, David Gibson wrote: [...]
It's a different guest side interface, the H_TPM_COMM hypercall instead of the other PAPR TPM interface. To which "why?" is a very good question, but it's there now, so there's not much we can do about it.
That's ok. Even though its a different guest interface, it is still conceptually a TPM device at a high level, so we should be reusing the existing <tpm> device type. At most we should add a new backend type
I think adding a new backend type is sensible. Re-using the passthrough type and making the differentiation with 'model', for a device that doesn't operate exactly as a regular vTPM but can coexist with other vTPM devices, will make for a lot of IFs in the code. DHB
Regards, Daniel

On Mon, May 11, 2020 at 08:26:53AM -0300, Daniel Henrique Barboza wrote:
On 5/11/20 6:57 AM, Daniel P. Berrangé wrote:
On Mon, May 11, 2020 at 11:22:57AM +1000, David Gibson wrote: [...]
It's a different guest side interface, the H_TPM_COMM hypercall instead of the other PAPR TPM interface. To which "why?" is a very good question, but it's there now, so there's not much we can do about it.
That's ok. Even though its a different guest interface, it is still conceptually a TPM device at a high level, so we should be reusing the existing <tpm> device type. At most we should add a new backend type
I think adding a new backend type is sensible. Re-using the passthrough type and making the differentiation with 'model', for a device that doesn't operate exactly as a regular vTPM but can coexist with other vTPM devices, will make for a lot of IFs in the code.
Currently libvirt only allows a single <tpm>, but we can trivially lift that restriction to allow multiple if desired too. 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 :|

On 5/11/20 8:28 AM, Daniel P. Berrangé wrote:
On Mon, May 11, 2020 at 08:26:53AM -0300, Daniel Henrique Barboza wrote:
On 5/11/20 6:57 AM, Daniel P. Berrangé wrote:
On Mon, May 11, 2020 at 11:22:57AM +1000, David Gibson wrote: [...]
It's a different guest side interface, the H_TPM_COMM hypercall instead of the other PAPR TPM interface. To which "why?" is a very good question, but it's there now, so there's not much we can do about it.
That's ok. Even though its a different guest interface, it is still conceptually a TPM device at a high level, so we should be reusing the existing <tpm> device type. At most we should add a new backend type
I think adding a new backend type is sensible. Re-using the passthrough type and making the differentiation with 'model', for a device that doesn't operate exactly as a regular vTPM but can coexist with other vTPM devices, will make for a lot of IFs in the code.
Currently libvirt only allows a single <tpm>, but we can trivially lift that restriction to allow multiple if desired too.
I don't believe it'll be necessary. Since it's only this TPM Proxy device that can coexist with other TPMs, my idea is to do what I did here in this series, but instead of creating a new device type I'll re-use the existing TPM device in a 'tpmproxy' pointer in the domain for this case. I'll still thinking about whether a new backend type is warranted or not. For this PPC64 case alone it'll be simpler to just add a new 'model' called 'spapr-tpm'-proxy' for the existing TPM passthrough type. Creating a new backend type makes it easier to add other TPM Proxy devices when other archs implement it though. Thanks, DHB
Regards, Daniel

On 5/11/20 8:50 AM, Daniel Henrique Barboza wrote:
On 5/11/20 8:28 AM, Daniel P. Berrangé wrote:
On Mon, May 11, 2020 at 08:26:53AM -0300, Daniel Henrique Barboza wrote:
On 5/11/20 6:57 AM, Daniel P. Berrangé wrote:
On Mon, May 11, 2020 at 11:22:57AM +1000, David Gibson wrote: [...]
[...]
Currently libvirt only allows a single <tpm>, but we can trivially lift that restriction to allow multiple if desired too.
I don't believe it'll be necessary. Since it's only this TPM Proxy device that can coexist with other TPMs, my idea is to do what I did here in this series, but instead of creating a new device type I'll re-use the existing TPM device in a 'tpmproxy' pointer in the domain for this case.
I'll still thinking about whether a new backend type is warranted or not. For this PPC64 case alone it'll be simpler to just add a new 'model' called 'spapr-tpm'-proxy' for the existing TPM passthrough type. Creating a new backend type makes it easier to add other TPM Proxy devices when other archs implement it though.
Update: I tried it out the new "backend" approach and didn't enjoy the results. It ended up replicating a large amount of existing cgroup/dac/selinux code that handles the existing "passthrough" backend and, all said and done, it didn't alleviate that much the parsing/format XML logic comparing to the alternative. I chose then to go to the simpler route - adding a new 'passthrough' model called 'spapr-tpm-proxy'. This will not scale well if/when more TPM proxies devices are added in the future, but we can cross that bridge when we come to it. DHB
Thanks,
DHB
Regards, Daniel

On Tue, May 12, 2020 at 01:29:43PM -0300, Daniel Henrique Barboza wrote:
On 5/11/20 8:50 AM, Daniel Henrique Barboza wrote:
On 5/11/20 8:28 AM, Daniel P. Berrangé wrote:
On Mon, May 11, 2020 at 08:26:53AM -0300, Daniel Henrique Barboza wrote:
On 5/11/20 6:57 AM, Daniel P. Berrangé wrote:
On Mon, May 11, 2020 at 11:22:57AM +1000, David Gibson wrote: [...]
[...]
Currently libvirt only allows a single <tpm>, but we can trivially lift that restriction to allow multiple if desired too.
I don't believe it'll be necessary. Since it's only this TPM Proxy device that can coexist with other TPMs, my idea is to do what I did here in this series, but instead of creating a new device type I'll re-use the existing TPM device in a 'tpmproxy' pointer in the domain for this case.
I'll still thinking about whether a new backend type is warranted or not. For this PPC64 case alone it'll be simpler to just add a new 'model' called 'spapr-tpm'-proxy' for the existing TPM passthrough type. Creating a new backend type makes it easier to add other TPM Proxy devices when other archs implement it though.
Update: I tried it out the new "backend" approach and didn't enjoy the results. It ended up replicating a large amount of existing cgroup/dac/selinux code that handles the existing "passthrough" backend and, all said and done, it didn't alleviate that much the parsing/format XML logic comparing to the alternative.
I chose then to go to the simpler route - adding a new 'passthrough' model called 'spapr-tpm-proxy'. This will not scale well if/when more TPM proxies devices are added in the future, but we can cross that bridge when we come to it.
TBH, I think that's unlikely to happen. The TPM proxy exists because of the design of POWER's secure VM model, and because it was easy to add an hcall to PAPR for this, without thinking how it would integrate with other TPM devices or PAPR's existing / concurrently designed vTPM interface. I don't think there's any general reason you'd want a device like this, distinct from just a vTPM. -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson

On Wed, May 13, 2020 at 10:06:23AM +1000, David Gibson wrote:
On Tue, May 12, 2020 at 01:29:43PM -0300, Daniel Henrique Barboza wrote:
On 5/11/20 8:50 AM, Daniel Henrique Barboza wrote:
On 5/11/20 8:28 AM, Daniel P. Berrangé wrote:
On Mon, May 11, 2020 at 08:26:53AM -0300, Daniel Henrique Barboza wrote:
On 5/11/20 6:57 AM, Daniel P. Berrangé wrote:
On Mon, May 11, 2020 at 11:22:57AM +1000, David Gibson wrote: [...]
[...]
Currently libvirt only allows a single <tpm>, but we can trivially lift that restriction to allow multiple if desired too.
I don't believe it'll be necessary. Since it's only this TPM Proxy device that can coexist with other TPMs, my idea is to do what I did here in this series, but instead of creating a new device type I'll re-use the existing TPM device in a 'tpmproxy' pointer in the domain for this case.
I'll still thinking about whether a new backend type is warranted or not. For this PPC64 case alone it'll be simpler to just add a new 'model' called 'spapr-tpm'-proxy' for the existing TPM passthrough type. Creating a new backend type makes it easier to add other TPM Proxy devices when other archs implement it though.
Update: I tried it out the new "backend" approach and didn't enjoy the results. It ended up replicating a large amount of existing cgroup/dac/selinux code that handles the existing "passthrough" backend and, all said and done, it didn't alleviate that much the parsing/format XML logic comparing to the alternative.
I chose then to go to the simpler route - adding a new 'passthrough' model called 'spapr-tpm-proxy'. This will not scale well if/when more TPM proxies devices are added in the future, but we can cross that bridge when we come to it.
TBH, I think that's unlikely to happen. The TPM proxy exists because of the design of POWER's secure VM model, and because it was easy to add an hcall to PAPR for this, without thinking how it would integrate with other TPM devices or PAPR's existing / concurrently designed vTPM interface. I don't think there's any general reason you'd want a device like this, distinct from just a vTPM.
Indeed, arguably, this would be better modelled by just some sort of machine or firmware feature flag, rather than a "device" as such. -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson

On 5/11/20 7:28 AM, Daniel P. Berrangé wrote:
On Mon, May 11, 2020 at 08:26:53AM -0300, Daniel Henrique Barboza wrote:
On 5/11/20 6:57 AM, Daniel P. Berrangé wrote:
It's a different guest side interface, the H_TPM_COMM hypercall instead of the other PAPR TPM interface. To which "why?" is a very good question, but it's there now, so there's not much we can do about it. That's ok. Even though its a different guest interface, it is still conceptually a TPM device at a high level, so we should be reusing
On Mon, May 11, 2020 at 11:22:57AM +1000, David Gibson wrote: [...] the existing <tpm> device type. At most we should add a new backend type I think adding a new backend type is sensible. Re-using the passthrough type and making the differentiation with 'model', for a device that doesn't operate exactly as a regular vTPM but can coexist with other vTPM devices, will make for a lot of IFs in the code.
Currently libvirt only allows a single <tpm>, but we can trivially lift that restriction to allow multiple if desired too.
QEMU won't accept multiple TIS or CRB devices, though.
Regards, Daniel

On Tue, May 12, 2020 at 11:21:52AM -0400, Stefan Berger wrote:
On 5/11/20 7:28 AM, Daniel P. Berrangé wrote:
On Mon, May 11, 2020 at 08:26:53AM -0300, Daniel Henrique Barboza wrote:
On 5/11/20 6:57 AM, Daniel P. Berrangé wrote:
It's a different guest side interface, the H_TPM_COMM hypercall instead of the other PAPR TPM interface. To which "why?" is a very good question, but it's there now, so there's not much we can do about it. That's ok. Even though its a different guest interface, it is still conceptually a TPM device at a high level, so we should be reusing
On Mon, May 11, 2020 at 11:22:57AM +1000, David Gibson wrote: [...] the existing <tpm> device type. At most we should add a new backend type I think adding a new backend type is sensible. Re-using the passthrough type and making the differentiation with 'model', for a device that doesn't operate exactly as a regular vTPM but can coexist with other vTPM devices, will make for a lot of IFs in the code.
Currently libvirt only allows a single <tpm>, but we can trivially lift that restriction to allow multiple if desired too.
QEMU won't accept multiple TIS or CRB devices, though.
The commit message says you can do 2 at a time: "Although redundant, there is currently no technical limitation for a guest to assign both a vTPM and a TPM Proxy at the same time." is that text not accurate ? 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 :|

On 5/12/20 12:53 PM, Daniel P. Berrangé wrote:
On Tue, May 12, 2020 at 11:21:52AM -0400, Stefan Berger wrote:
On 5/11/20 7:28 AM, Daniel P. Berrangé wrote:
On Mon, May 11, 2020 at 08:26:53AM -0300, Daniel Henrique Barboza wrote:
On 5/11/20 6:57 AM, Daniel P. Berrangé wrote:
It's a different guest side interface, the H_TPM_COMM hypercall instead of the other PAPR TPM interface. To which "why?" is a very good question, but it's there now, so there's not much we can do about it. That's ok. Even though its a different guest interface, it is still conceptually a TPM device at a high level, so we should be reusing
On Mon, May 11, 2020 at 11:22:57AM +1000, David Gibson wrote: [...] the existing <tpm> device type. At most we should add a new backend type I think adding a new backend type is sensible. Re-using the passthrough type and making the differentiation with 'model', for a device that doesn't operate exactly as a regular vTPM but can coexist with other vTPM devices, will make for a lot of IFs in the code.
Currently libvirt only allows a single <tpm>, but we can trivially lift that restriction to allow multiple if desired too.
QEMU won't accept multiple TIS or CRB devices, though.
The commit message says you can do 2 at a time:
"Although redundant, there is currently no technical limitation for a guest to assign both a vTPM and a TPM Proxy at the same time."
is that text not accurate ?
It is. A TPM Proxy is not considered a TIS or CRB, so it's ok to mix it up with another TPM device. The allowed combinations are: - single vTPM device - single TPM Proxy device - a single vTPM + single TPM Proxy devices Not allowed: - 2 or more vTPM devices - 2 or more TPM Proxy devices DHB
Regards, Daniel

On Tue, May 12, 2020 at 01:21:40PM -0300, Daniel Henrique Barboza wrote:
On 5/12/20 12:53 PM, Daniel P. Berrangé wrote:
On Tue, May 12, 2020 at 11:21:52AM -0400, Stefan Berger wrote:
On 5/11/20 7:28 AM, Daniel P. Berrangé wrote:
On Mon, May 11, 2020 at 08:26:53AM -0300, Daniel Henrique Barboza wrote:
On 5/11/20 6:57 AM, Daniel P. Berrangé wrote:
On Mon, May 11, 2020 at 11:22:57AM +1000, David Gibson wrote: [...] > It's a different guest side interface, the H_TPM_COMM hypercall > instead of the other PAPR TPM interface. To which "why?" is a very > good question, but it's there now, so there's not much we can do about > it. That's ok. Even though its a different guest interface, it is still conceptually a TPM device at a high level, so we should be reusing the existing <tpm> device type. At most we should add a new backend type I think adding a new backend type is sensible. Re-using the passthrough type and making the differentiation with 'model', for a device that doesn't operate exactly as a regular vTPM but can coexist with other vTPM devices, will make for a lot of IFs in the code.
Currently libvirt only allows a single <tpm>, but we can trivially lift that restriction to allow multiple if desired too.
QEMU won't accept multiple TIS or CRB devices, though.
The commit message says you can do 2 at a time:
"Although redundant, there is currently no technical limitation for a guest to assign both a vTPM and a TPM Proxy at the same time."
is that text not accurate ?
It is. A TPM Proxy is not considered a TIS or CRB, so it's ok to mix it up with another TPM device. The allowed combinations are:
- single vTPM device - single TPM Proxy device - a single vTPM + single TPM Proxy devices
So we do need multiple <tpm> support in the XML for this last case then. 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 :|

On 5/12/20 1:44 PM, Daniel P. Berrangé wrote:
On Tue, May 12, 2020 at 01:21:40PM -0300, Daniel Henrique Barboza wrote:
On 5/12/20 12:53 PM, Daniel P. Berrangé wrote:
On Tue, May 12, 2020 at 11:21:52AM -0400, Stefan Berger wrote:
On 5/11/20 7:28 AM, Daniel P. Berrangé wrote:
On Mon, May 11, 2020 at 08:26:53AM -0300, Daniel Henrique Barboza wrote:
On 5/11/20 6:57 AM, Daniel P. Berrangé wrote: > On Mon, May 11, 2020 at 11:22:57AM +1000, David Gibson wrote: [...] >> It's a different guest side interface, the H_TPM_COMM hypercall >> instead of the other PAPR TPM interface. To which "why?" is a very >> good question, but it's there now, so there's not much we can do about >> it. > That's ok. Even though its a different guest interface, it is still > conceptually a TPM device at a high level, so we should be reusing > the existing <tpm> device type. At most we should add a new backend > type I think adding a new backend type is sensible. Re-using the passthrough type and making the differentiation with 'model', for a device that doesn't operate exactly as a regular vTPM but can coexist with other vTPM devices, will make for a lot of IFs in the code.
Currently libvirt only allows a single <tpm>, but we can trivially lift that restriction to allow multiple if desired too.
QEMU won't accept multiple TIS or CRB devices, though.
The commit message says you can do 2 at a time:
"Although redundant, there is currently no technical limitation for a guest to assign both a vTPM and a TPM Proxy at the same time."
is that text not accurate ?
It is. A TPM Proxy is not considered a TIS or CRB, so it's ok to mix it up with another TPM device. The allowed combinations are:
- single vTPM device - single TPM Proxy device - a single vTPM + single TPM Proxy devices
So we do need multiple <tpm> support in the XML for this last case then.
Indeed we do. Working on it ATM. The plan is for this kind of XML format to be valid: <tpm model='tpm-tis'> <backend type='passthrough'> <device path='/dev/tpm0'/> </backend> </tpm> <tpm model='spapr-tpm-proxy'> <backend type='passthrough'> <device path='/dev/tpmrm0'/> </backend> </tpm> A TPM Proxy allows a second TPM device to be added, as long as it's not a second TPM Proxy device. Thanks, DHB
Regards, Daniel

On Tue, May 12, 2020 at 01:51:33PM -0300, Daniel Henrique Barboza wrote:
On 5/12/20 1:44 PM, Daniel P. Berrangé wrote:
On Tue, May 12, 2020 at 01:21:40PM -0300, Daniel Henrique Barboza wrote:
On 5/12/20 12:53 PM, Daniel P. Berrangé wrote:
On Tue, May 12, 2020 at 11:21:52AM -0400, Stefan Berger wrote:
On 5/11/20 7:28 AM, Daniel P. Berrangé wrote:
On Mon, May 11, 2020 at 08:26:53AM -0300, Daniel Henrique Barboza wrote: > > On 5/11/20 6:57 AM, Daniel P. Berrangé wrote: > > On Mon, May 11, 2020 at 11:22:57AM +1000, David Gibson wrote: > [...] > > > It's a different guest side interface, the H_TPM_COMM hypercall > > > instead of the other PAPR TPM interface. To which "why?" is a very > > > good question, but it's there now, so there's not much we can do about > > > it. > > That's ok. Even though its a different guest interface, it is still > > conceptually a TPM device at a high level, so we should be reusing > > the existing <tpm> device type. At most we should add a new backend > > type > I think adding a new backend type is sensible. Re-using the passthrough type > and making the differentiation with 'model', for a device that doesn't > operate exactly as a regular vTPM but can coexist with other vTPM devices, > will make for a lot of IFs in the code. Currently libvirt only allows a single <tpm>, but we can trivially lift that restriction to allow multiple if desired too.
QEMU won't accept multiple TIS or CRB devices, though.
The commit message says you can do 2 at a time:
"Although redundant, there is currently no technical limitation for a guest to assign both a vTPM and a TPM Proxy at the same time."
is that text not accurate ?
It is. A TPM Proxy is not considered a TIS or CRB, so it's ok to mix it up with another TPM device. The allowed combinations are:
- single vTPM device - single TPM Proxy device - a single vTPM + single TPM Proxy devices
So we do need multiple <tpm> support in the XML for this last case then.
Indeed we do. Working on it ATM. The plan is for this kind of XML format to be valid:
<tpm model='tpm-tis'> <backend type='passthrough'> <device path='/dev/tpm0'/> </backend> </tpm> <tpm model='spapr-tpm-proxy'> <backend type='passthrough'> <device path='/dev/tpmrm0'/> </backend> </tpm>
Right, that sounds ok. 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 :|

On 5/8/20 8:06 AM, Daniel Henrique Barboza wrote:
QEMU 4.1.0 introduced a new device type called TPM Proxy, currently implemented by PPC64 guests via a new virtual device called 'spapr-tpm-proxy' (see QEMU 0fb6bd073230 for more info).
The TPM Proxy device interacts with a TPM Resource Manager, a host device capable of multiplexing the host TPM with multiple processes. This allows multiple guests to access some TPM features at the same time. Note that this mode of operation does not provide full TPM features to be available for the guest - for that case the guest still needs to assign a vTPM device (tpm-spapr for PPC64 guests). Although redundant, there is currently no technical limitation for a guest to assign both a vTPM and a TPM Proxy at the same time.
This patch adds documentation and schema for the new TPM Proxy device. An example of a TPM Proxy device connected to a TPM Resource Manager '/dev/tpmrm0' will look like this:
<tpmproxy model='spapr-tpm-proxy'> <device path='/dev/tpmrm0'/> </tpmproxy>
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- docs/formatdomain.html.in | 42 +++++++++++++++++++++++++++++++++++ docs/schemas/domaincommon.rng | 18 +++++++++++++++ 2 files changed, 60 insertions(+)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 23eb029234..650e2a8c6e 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -8849,6 +8849,48 @@ qemu-kvm -net nic,model=? /dev/null </dd> </dl>
+ <h4><a id="elementsTpmProxy">TPM Proxy device</a></h4> + + <p> + The TPM Proxy device allows a QEMU guest to interact with an + existing TPM Resource Manager in the host. A TPM Resource Manager + enables a TPM device to be securely multiplexed across several + guests. Only one TPM Proxy device is allowed per guest.
I think you should mention SVMs here and that this is what this extension is used for or are there other uses than secure VMs?
+ </p> + <p> + A guest using the TPM Proxy device does not have access to all the + features a TPM device provides. This means that a guest can have both + a TPM Proxy and a TPM device assigned at the same time.
And this TPM Proxy device only enables the H_COMM_TPM hypercall rather than talking to /dev/tpm(rm)0 inside the SVM. I think this should be clarified because otherwise people might confuse it with the passthrough device that does expose /dev/tpm0 inside the VM for example.
+ </p> + <p> + The TPM Proxy device is currently available only for pSeries guests. + <span class="since">since 6.4.0</span> + </p> + <p> + Example: usage of the TPM Proxy device + </p> +<pre> +... +<devices> + <tpmproxy model='spapr-tpm-proxy'> + <device path='/dev/tpmrm0'/> + </tpmproxy> +</devices> +... +</pre> + + <dl> + <dt><code>model</code></dt> + <dd> + <p> + The <code>model</code> attribute specifies what device + model QEMU provides to the guest. If no model name is provided, + <code>spapr-tpm-proxy</code> will automatically be chosen for + PPC64 architectures. + </p> + </dd> + </dl> + <h4><a id="elementsNVRAM">NVRAM device</a></h4> <p> nvram device is always added to pSeries guest on PPC64, and its address diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 9d60b090f3..44bbd92244 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4676,6 +4676,23 @@ </optional> </define>
+ <define name="tpmproxy"> + <element name="tpmproxy"> + <optional> + <attribute name="model"> + <choice> + <value>spapr-tpm-proxy</value> + </choice> + </attribute> + </optional> + <element name="device"> + <attribute name="path"> + <ref name="filePath"/> + </attribute> + </element> + </element> + </define> + <define name="vsock"> <element name="vsock"> <optional> @@ -5279,6 +5296,7 @@ <ref name="tpm"/> <ref name="shmem"/> <ref name="memorydev"/> + <ref name="tpmproxy"/> </choice> </zeroOrMore> <optional>

On Fri, May 08, 2020 at 06:43:20PM -0400, Stefan Berger wrote:
On 5/8/20 8:06 AM, Daniel Henrique Barboza wrote:
QEMU 4.1.0 introduced a new device type called TPM Proxy, currently implemented by PPC64 guests via a new virtual device called 'spapr-tpm-proxy' (see QEMU 0fb6bd073230 for more info).
The TPM Proxy device interacts with a TPM Resource Manager, a host device capable of multiplexing the host TPM with multiple processes. This allows multiple guests to access some TPM features at the same time. Note that this mode of operation does not provide full TPM features to be available for the guest - for that case the guest still needs to assign a vTPM device (tpm-spapr for PPC64 guests). Although redundant, there is currently no technical limitation for a guest to assign both a vTPM and a TPM Proxy at the same time.
This patch adds documentation and schema for the new TPM Proxy device. An example of a TPM Proxy device connected to a TPM Resource Manager '/dev/tpmrm0' will look like this:
<tpmproxy model='spapr-tpm-proxy'> <device path='/dev/tpmrm0'/> </tpmproxy>
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- docs/formatdomain.html.in | 42 +++++++++++++++++++++++++++++++++++ docs/schemas/domaincommon.rng | 18 +++++++++++++++ 2 files changed, 60 insertions(+)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 23eb029234..650e2a8c6e 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -8849,6 +8849,48 @@ qemu-kvm -net nic,model=? /dev/null </dd> </dl> + <h4><a id="elementsTpmProxy">TPM Proxy device</a></h4> + + <p> + The TPM Proxy device allows a QEMU guest to interact with an + existing TPM Resource Manager in the host. A TPM Resource Manager + enables a TPM device to be securely multiplexed across several + guests. Only one TPM Proxy device is allowed per guest.
I think you should mention SVMs here and that this is what this extension is used for or are there other uses than secure VMs?
Yes, I think talking about PEF secure VMs is a good idea. This could theoretically be used for other things, but secure VMs is the only actual user I know of.
+ </p> + <p> + A guest using the TPM Proxy device does not have access to all the + features a TPM device provides. This means that a guest can have both + a TPM Proxy and a TPM device assigned at the same time.
And this TPM Proxy device only enables the H_COMM_TPM hypercall rather than talking to /dev/tpm(rm)0 inside the SVM. I think this should be clarified because otherwise people might confuse it with the passthrough device that does expose /dev/tpm0 inside the VM for example.
+ </p> + <p> + The TPM Proxy device is currently available only for pSeries guests. + <span class="since">since 6.4.0</span> + </p> + <p> + Example: usage of the TPM Proxy device + </p> +<pre> +... +<devices> + <tpmproxy model='spapr-tpm-proxy'> + <device path='/dev/tpmrm0'/> + </tpmproxy> +</devices> +... +</pre> + + <dl> + <dt><code>model</code></dt> + <dd> + <p> + The <code>model</code> attribute specifies what device + model QEMU provides to the guest. If no model name is provided, + <code>spapr-tpm-proxy</code> will automatically be chosen for + PPC64 architectures. + </p> + </dd> + </dl> + <h4><a id="elementsNVRAM">NVRAM device</a></h4> <p> nvram device is always added to pSeries guest on PPC64, and its address diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 9d60b090f3..44bbd92244 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4676,6 +4676,23 @@ </optional> </define> + <define name="tpmproxy"> + <element name="tpmproxy"> + <optional> + <attribute name="model"> + <choice> + <value>spapr-tpm-proxy</value> + </choice> + </attribute> + </optional> + <element name="device"> + <attribute name="path"> + <ref name="filePath"/> + </attribute> + </element> + </element> + </define> + <define name="vsock"> <element name="vsock"> <optional> @@ -5279,6 +5296,7 @@ <ref name="tpm"/> <ref name="shmem"/> <ref name="memorydev"/> + <ref name="tpmproxy"/> </choice> </zeroOrMore> <optional>
-- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson

Expose the TPM Proxy support for PPC64 guests by creating a new cap called QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY. Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + 4 files changed, 5 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 2c6e36685e..dcc1886954 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -580,6 +580,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "machine.pseries.cap-sbbc", "machine.pseries.cap-ibs", "tcg", + "spapr-tpm-proxy", ); @@ -1301,6 +1302,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "tpm-spapr", QEMU_CAPS_DEVICE_TPM_SPAPR }, { "vhost-user-fs-device", QEMU_CAPS_DEVICE_VHOST_USER_FS }, { "tcg-accel", QEMU_CAPS_TCG }, + { "spapr-tpm-proxy", QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY }, }; static struct virQEMUCapsStringFlags virQEMUCapsDevicePropsVirtioBalloon[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index cdeaf09cce..92aca0470b 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -561,6 +561,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_MACHINE_PSERIES_CAP_SBBC, /* -machine pseries.cap-sbbc */ QEMU_CAPS_MACHINE_PSERIES_CAP_IBS, /* -machine pseries.cap-ibs */ QEMU_CAPS_TCG, /* QEMU does support TCG */ + QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY, /* -device spapr-tpm-proxy */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml index 796ed0a2bc..75301833e6 100644 --- a/tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml @@ -184,6 +184,7 @@ <flag name='machine.pseries.cap-sbbc'/> <flag name='machine.pseries.cap-ibs'/> <flag name='tcg'/> + <flag name='spapr-tpm-proxy'/> <version>4001050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>42900242</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml index a5f0bb538b..08cf607cbf 100644 --- a/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml @@ -199,6 +199,7 @@ <flag name='machine.pseries.cap-sbbc'/> <flag name='machine.pseries.cap-ibs'/> <flag name='tcg'/> + <flag name='spapr-tpm-proxy'/> <version>5000000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>42900241</microcodeVersion> -- 2.26.2

On 5/8/20 8:06 AM, Daniel Henrique Barboza wrote:
Expose the TPM Proxy support for PPC64 guests by creating a new cap called QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY.
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + 4 files changed, 5 insertions(+)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 2c6e36685e..dcc1886954 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -580,6 +580,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "machine.pseries.cap-sbbc", "machine.pseries.cap-ibs", "tcg", + "spapr-tpm-proxy",
To me a proxy is something different and enablement of a ultracall/hypercall type of thing. Call it spapr-tpm-hcall?
);
@@ -1301,6 +1302,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "tpm-spapr", QEMU_CAPS_DEVICE_TPM_SPAPR }, { "vhost-user-fs-device", QEMU_CAPS_DEVICE_VHOST_USER_FS }, { "tcg-accel", QEMU_CAPS_TCG }, + { "spapr-tpm-proxy", QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY }, };
static struct virQEMUCapsStringFlags virQEMUCapsDevicePropsVirtioBalloon[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index cdeaf09cce..92aca0470b 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -561,6 +561,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_MACHINE_PSERIES_CAP_SBBC, /* -machine pseries.cap-sbbc */ QEMU_CAPS_MACHINE_PSERIES_CAP_IBS, /* -machine pseries.cap-ibs */ QEMU_CAPS_TCG, /* QEMU does support TCG */ + QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY, /* -device spapr-tpm-proxy */
QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml index 796ed0a2bc..75301833e6 100644 --- a/tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml @@ -184,6 +184,7 @@ <flag name='machine.pseries.cap-sbbc'/> <flag name='machine.pseries.cap-ibs'/> <flag name='tcg'/> + <flag name='spapr-tpm-proxy'/> <version>4001050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>42900242</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml index a5f0bb538b..08cf607cbf 100644 --- a/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml @@ -199,6 +199,7 @@ <flag name='machine.pseries.cap-sbbc'/> <flag name='machine.pseries.cap-ibs'/> <flag name='tcg'/> + <flag name='spapr-tpm-proxy'/> <version>5000000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>42900241</microcodeVersion>

On Fri, May 08, 2020 at 06:48:24PM -0400, Stefan Berger wrote:
On 5/8/20 8:06 AM, Daniel Henrique Barboza wrote:
Expose the TPM Proxy support for PPC64 guests by creating a new cap called QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY.
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + 4 files changed, 5 insertions(+)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 2c6e36685e..dcc1886954 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -580,6 +580,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "machine.pseries.cap-sbbc", "machine.pseries.cap-ibs", "tcg", + "spapr-tpm-proxy",
To me a proxy is something different and enablement of a ultracall/hypercall type of thing. Call it spapr-tpm-hcall?
The "spapr-tpm-proxy" name is already exposed at the qemu level. And while, I can agree that's maybe not a great name, I think it's probably even more confusing to add another name fro it at the libvirt level.
); @@ -1301,6 +1302,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "tpm-spapr", QEMU_CAPS_DEVICE_TPM_SPAPR }, { "vhost-user-fs-device", QEMU_CAPS_DEVICE_VHOST_USER_FS }, { "tcg-accel", QEMU_CAPS_TCG }, + { "spapr-tpm-proxy", QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY }, }; static struct virQEMUCapsStringFlags virQEMUCapsDevicePropsVirtioBalloon[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index cdeaf09cce..92aca0470b 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -561,6 +561,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_MACHINE_PSERIES_CAP_SBBC, /* -machine pseries.cap-sbbc */ QEMU_CAPS_MACHINE_PSERIES_CAP_IBS, /* -machine pseries.cap-ibs */ QEMU_CAPS_TCG, /* QEMU does support TCG */ + QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY, /* -device spapr-tpm-proxy */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml index 796ed0a2bc..75301833e6 100644 --- a/tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml @@ -184,6 +184,7 @@ <flag name='machine.pseries.cap-sbbc'/> <flag name='machine.pseries.cap-ibs'/> <flag name='tcg'/> + <flag name='spapr-tpm-proxy'/> <version>4001050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>42900242</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml index a5f0bb538b..08cf607cbf 100644 --- a/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml @@ -199,6 +199,7 @@ <flag name='machine.pseries.cap-sbbc'/> <flag name='machine.pseries.cap-ibs'/> <flag name='tcg'/> + <flag name='spapr-tpm-proxy'/> <version>5000000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>42900241</microcodeVersion>
-- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson

This new device will be used to represent a single instance of a TPM Proxy for the domain. XML functions to parse and format the device from the XML definition will be added in the next patch. Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- src/conf/domain_capabilities.c | 1 + src/conf/domain_conf.c | 68 ++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 18 +++++++++ src/conf/virconftypes.h | 3 ++ src/qemu/qemu_command.c | 1 + src/qemu/qemu_domain.c | 14 +++++++ src/qemu/qemu_domain_address.c | 2 + src/qemu/qemu_driver.c | 5 +++ src/qemu/qemu_hotplug.c | 3 ++ src/qemu/qemu_validate.c | 37 ++++++++++++++++++ 10 files changed, 152 insertions(+) diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index 921d795630..485fa9a22d 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -703,6 +703,7 @@ virDomainCapsDeviceDefValidate(const virDomainCaps *caps, case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_TPMPROXY: case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_LAST: break; diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 83748354b0..4c731b9f36 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -323,6 +323,7 @@ VIR_ENUM_IMPL(virDomainDevice, "memory", "iommu", "vsock", + "tpmproxy", ); VIR_ENUM_IMPL(virDomainDiskDevice, @@ -1180,6 +1181,12 @@ VIR_ENUM_IMPL(virDomainTPMVersion, "2.0", ); +VIR_ENUM_IMPL(virDomainTPMProxyModel, + VIR_DOMAIN_TPMPROXY_MODEL_LAST, + "default", + "spapr-tpm-proxy", +); + VIR_ENUM_IMPL(virDomainIOMMUModel, VIR_DOMAIN_IOMMU_MODEL_LAST, "intel", @@ -3061,6 +3068,17 @@ void virDomainTPMDefFree(virDomainTPMDefPtr def) VIR_FREE(def); } +void virDomainTPMProxyDefFree(virDomainTPMProxyDefPtr def) +{ + if (!def) + return; + + VIR_FREE(def->path); + virDomainDeviceInfoClear(&def->info); + VIR_FREE(def); + +} + void virDomainHostdevDefFree(virDomainHostdevDefPtr def) { if (!def) @@ -3187,6 +3205,9 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def) case VIR_DOMAIN_DEVICE_TPM: virDomainTPMDefFree(def->data.tpm); break; + case VIR_DOMAIN_DEVICE_TPMPROXY: + virDomainTPMProxyDefFree(def->data.tpmproxy); + break; case VIR_DOMAIN_DEVICE_PANIC: virDomainPanicDefFree(def->data.panic); break; @@ -3480,6 +3501,7 @@ void virDomainDefFree(virDomainDefPtr def) VIR_FREE(def->mems); virDomainTPMDefFree(def->tpm); + virDomainTPMProxyDefFree(def->tpmproxy); for (i = 0; i < def->npanics; i++) virDomainPanicDefFree(def->panics[i]); @@ -4038,6 +4060,8 @@ virDomainDeviceGetInfo(virDomainDeviceDefPtr device) return &device->data.memory->info; case VIR_DOMAIN_DEVICE_VSOCK: return &device->data.vsock->info; + case VIR_DOMAIN_DEVICE_TPMPROXY: + return &device->data.tpmproxy->info; /* The following devices do not contain virDomainDeviceInfo */ case VIR_DOMAIN_DEVICE_LEASE: @@ -4137,6 +4161,9 @@ virDomainDeviceSetData(virDomainDeviceDefPtr device, case VIR_DOMAIN_DEVICE_LEASE: device->data.lease = devicedata; break; + case VIR_DOMAIN_DEVICE_TPMPROXY: + device->data.tpmproxy = devicedata; + break; case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_LAST: break; @@ -4318,6 +4345,12 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def, if ((rc = cb(def, &device, &def->tpm->info, opaque)) != 0) return rc; } + if (def->tpmproxy) { + device.type = VIR_DOMAIN_DEVICE_TPMPROXY; + device.data.tpmproxy = def->tpmproxy; + if ((rc = cb(def, &device, &def->tpmproxy->info, opaque)) != 0) + return rc; + } device.type = VIR_DOMAIN_DEVICE_PANIC; for (i = 0; i < def->npanics; i++) { device.data.panic = def->panics[i]; @@ -4403,6 +4436,7 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def, case VIR_DOMAIN_DEVICE_MEMORY: case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_VSOCK: + case VIR_DOMAIN_DEVICE_TPMPROXY: break; } #endif @@ -5395,6 +5429,7 @@ virDomainDeviceDefPostParseCommon(virDomainDeviceDefPtr dev, case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_MEMORY: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_TPMPROXY: ret = 0; break; @@ -6795,6 +6830,7 @@ virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev, case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_TPMPROXY: case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_LAST: break; @@ -17039,6 +17075,7 @@ virDomainDeviceDefParse(const char *xmlStr, flags))) return NULL; break; + case VIR_DOMAIN_DEVICE_TPMPROXY: case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_LAST: break; @@ -23743,6 +23780,25 @@ virDomainTPMDefCheckABIStability(virDomainTPMDefPtr src, } +static bool +virDomainTPMProxyDefCheckABIStability(virDomainTPMProxyDefPtr src, + virDomainTPMProxyDefPtr dst) +{ + if (src->model != dst->model) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Target TPM Proxy device model doesn't match source")); + return false; + } + + if (STRNEQ_NULLABLE(src->path, dst->path)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Target TPM Proxy device path doesn't match source")); + return false; + } + + return virDomainDeviceInfoCheckABIStability(&src->info, &dst->info); +} + static bool virDomainMemtuneCheckABIStability(const virDomainDef *src, const virDomainDef *dst, @@ -24355,6 +24411,16 @@ virDomainDefCheckABIStabilityFlags(virDomainDefPtr src, goto error; } + if (src->tpmproxy && dst->tpmproxy) { + if (!virDomainTPMProxyDefCheckABIStability(src->tpmproxy, dst->tpmproxy)) + goto error; + } else if (src->tpmproxy || dst->tpmproxy) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Either both target and source domains or none of " + "them must have TPM Proxy device present")); + goto error; + } + if (src->nmems != dst->nmems) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target domain memory device count %zu " @@ -24427,6 +24493,7 @@ virDomainDefCheckABIStabilityFlags(virDomainDefPtr src, case VIR_DOMAIN_DEVICE_MEMORY: case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_VSOCK: + case VIR_DOMAIN_DEVICE_TPMPROXY: break; } #endif @@ -30977,6 +31044,7 @@ virDomainDeviceDefCopy(virDomainDeviceDefPtr src, case VIR_DOMAIN_DEVICE_MEMBALLOON: case VIR_DOMAIN_DEVICE_NVRAM: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_TPMPROXY: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_INTERNAL_ERROR, _("Copying definition of '%d' type " diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 4afd8f04bc..d9b6bc5a22 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -85,6 +85,7 @@ typedef enum { VIR_DOMAIN_DEVICE_MEMORY, VIR_DOMAIN_DEVICE_IOMMU, VIR_DOMAIN_DEVICE_VSOCK, + VIR_DOMAIN_DEVICE_TPMPROXY, VIR_DOMAIN_DEVICE_LAST } virDomainDeviceType; @@ -116,6 +117,7 @@ struct _virDomainDeviceDef { virDomainMemoryDefPtr memory; virDomainIOMMUDefPtr iommu; virDomainVsockDefPtr vsock; + virDomainTPMProxyDefPtr tpmproxy; } data; }; @@ -1330,6 +1332,19 @@ struct _virDomainTPMDef { } data; }; +typedef enum { + VIR_DOMAIN_TPMPROXY_MODEL_DEFAULT, + VIR_DOMAIN_TPMPROXY_MODEL_SPAPR, + + VIR_DOMAIN_TPMPROXY_MODEL_LAST +} virDomainTPMProxyModel; + +struct _virDomainTPMProxyDef { + virDomainDeviceInfo info; + int model; /* virDomainTPMProxyModel */ + char *path; +}; + typedef enum { VIR_DOMAIN_INPUT_TYPE_MOUSE, VIR_DOMAIN_INPUT_TYPE_TABLET, @@ -2625,6 +2640,7 @@ struct _virDomainDef { virDomainMemballoonDefPtr memballoon; virDomainNVRAMDefPtr nvram; virDomainTPMDefPtr tpm; + virDomainTPMProxyDefPtr tpmproxy; virCPUDefPtr cpu; virSysinfoDefPtr sysinfo; virDomainRedirFilterDefPtr redirfilter; @@ -3023,6 +3039,7 @@ virDomainDeviceInfoPtr virDomainDeviceGetInfo(virDomainDeviceDefPtr device); void virDomainDeviceSetData(virDomainDeviceDefPtr device, void *devicedata); void virDomainTPMDefFree(virDomainTPMDefPtr def); +void virDomainTPMProxyDefFree(virDomainTPMProxyDefPtr def); typedef int (*virDomainDeviceInfoCallback)(virDomainDefPtr def, virDomainDeviceDefPtr dev, @@ -3594,6 +3611,7 @@ VIR_ENUM_DECL(virDomainRNGBackend); VIR_ENUM_DECL(virDomainTPMModel); VIR_ENUM_DECL(virDomainTPMBackend); VIR_ENUM_DECL(virDomainTPMVersion); +VIR_ENUM_DECL(virDomainTPMProxyModel); VIR_ENUM_DECL(virDomainMemoryModel); VIR_ENUM_DECL(virDomainMemoryBackingModel); VIR_ENUM_DECL(virDomainMemorySource); diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h index 1c62cde251..5c4a149f24 100644 --- a/src/conf/virconftypes.h +++ b/src/conf/virconftypes.h @@ -312,6 +312,9 @@ typedef virDomainSoundDef *virDomainSoundDefPtr; typedef struct _virDomainTPMDef virDomainTPMDef; typedef virDomainTPMDef *virDomainTPMDefPtr; +typedef struct _virDomainTPMProxyDef virDomainTPMProxyDef; +typedef virDomainTPMProxyDef *virDomainTPMProxyDefPtr; + typedef struct _virDomainThreadSchedParam virDomainThreadSchedParam; typedef virDomainThreadSchedParam *virDomainThreadSchedParamPtr; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 269bdbaf56..9065164b1d 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -537,6 +537,7 @@ qemuBuildVirtioDevStr(virBufferPtr buf, case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_MEMORY: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_TPMPROXY: case VIR_DOMAIN_DEVICE_LAST: default: return 0; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 9c629c31a3..3e86797093 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5923,6 +5923,16 @@ qemuDomainTPMDefPostParse(virDomainTPMDefPtr tpm, } +static int +qemuDomainTPMProxyDefPostParse(virDomainTPMProxyDefPtr tpmproxy) +{ + if (tpmproxy->model == VIR_DOMAIN_TPMPROXY_MODEL_DEFAULT) + tpmproxy->model = VIR_DOMAIN_TPMPROXY_MODEL_SPAPR; + + return 0; +} + + static int qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, const virDomainDef *def, @@ -5980,6 +5990,10 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, ret = qemuDomainTPMDefPostParse(dev->data.tpm, def->os.arch); break; + case VIR_DOMAIN_DEVICE_TPMPROXY: + ret = qemuDomainTPMProxyDefPostParse(dev->data.tpmproxy); + break; + case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_FS: case VIR_DOMAIN_DEVICE_INPUT: diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 07431343ed..566516f8b5 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -528,6 +528,7 @@ qemuDomainDeviceSupportZPCI(virDomainDeviceDefPtr device) case VIR_DOMAIN_DEVICE_MEMORY: case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_VSOCK: + case VIR_DOMAIN_DEVICE_TPMPROXY: break; case VIR_DOMAIN_DEVICE_NONE: @@ -1031,6 +1032,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev, case VIR_DOMAIN_DEVICE_HUB: case VIR_DOMAIN_DEVICE_REDIRDEV: case VIR_DOMAIN_DEVICE_SMARTCARD: + case VIR_DOMAIN_DEVICE_TPMPROXY: /* These devices don't even have a DeviceInfo */ case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_GRAPHICS: diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 1c7c87128d..57575b705f 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7956,6 +7956,7 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_TPMPROXY: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("live attach of device '%s' is not supported"), @@ -8090,6 +8091,7 @@ qemuDomainUpdateDeviceLive(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_VSOCK: + case VIR_DOMAIN_DEVICE_TPMPROXY: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("live update of device '%s' is not supported"), @@ -8311,6 +8313,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef, case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_TPMPROXY: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("persistent attach of device '%s' is not supported"), @@ -8513,6 +8516,7 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef, case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_TPMPROXY: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("persistent detach of device '%s' is not supported"), @@ -8620,6 +8624,7 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef, case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_VSOCK: + case VIR_DOMAIN_DEVICE_TPMPROXY: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("persistent update of device '%s' is not supported"), diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 60d0729f1e..aba80c87d3 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -4980,6 +4980,7 @@ qemuDomainRemoveAuditDevice(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_TPMPROXY: case VIR_DOMAIN_DEVICE_LAST: /* libvirt doesn't yet support detaching these devices */ break; @@ -5078,6 +5079,7 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver, case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_TPMPROXY: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("don't know how to remove a %s device"), @@ -5849,6 +5851,7 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_TPMPROXY: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("live detach of device '%s' is not supported"), diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 9debac6b30..733850416a 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -3326,6 +3326,38 @@ qemuValidateDomainDeviceDefTPM(virDomainTPMDef *tpm, } +static int +qemuValidateDomainDeviceDefTPMProxy(virDomainTPMProxyDef *tpmproxy, + const virDomainDef *def, + virQEMUCapsPtr qemuCaps) +{ + if (!ARCH_IS_PPC64(def->os.arch)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("TPM Proxy device is only supported " + "for PPC64 guests")); + return -1; + } + + switch ((virDomainTPMProxyModel)tpmproxy->model) { + case VIR_DOMAIN_TPMPROXY_MODEL_DEFAULT: + case VIR_DOMAIN_TPMPROXY_MODEL_SPAPR: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("TPM Proxy is not supported " + "with this QEMU binary")); + return -1; + } + break; + case VIR_DOMAIN_TPMPROXY_MODEL_LAST: + default: + virReportEnumRangeError(virDomainTPMProxyModel, + tpmproxy->model); + return -1; + } + + return 0; +} + static int qemuValidateDomainDeviceDefInput(const virDomainInputDef *input, const virDomainDef *def, @@ -3722,6 +3754,11 @@ qemuValidateDomainDeviceDef(const virDomainDeviceDef *dev, ret = qemuValidateDomainDeviceDefMemory(dev->data.memory, qemuCaps); break; + case VIR_DOMAIN_DEVICE_TPMPROXY: + ret = qemuValidateDomainDeviceDefTPMProxy(dev->data.tpmproxy, + def, qemuCaps); + break; + case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_SHMEM: case VIR_DOMAIN_DEVICE_PANIC: -- 2.26.2

Add virDomainTPMProxyDefParseXML() and virDomainTPMProxyDefFormat() to handle the creating of the TPM Proxy device via its XML description. Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- src/conf/domain_conf.c | 94 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 4c731b9f36..4f43dcddee 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -13779,6 +13779,50 @@ virDomainTPMDefParseXML(virDomainXMLOptionPtr xmlopt, return NULL; } +static virDomainTPMProxyDefPtr +virDomainTPMProxyDefParseXML(virDomainXMLOptionPtr xmlopt, + xmlNodePtr node, + xmlXPathContextPtr ctxt, + unsigned int flags) +{ + virDomainTPMProxyDefPtr def; + VIR_XPATH_NODE_AUTORESTORE(ctxt); + g_autofree char *path = NULL; + g_autofree char *model = NULL; + + if (VIR_ALLOC(def) < 0) + return NULL; + + def->model = VIR_DOMAIN_TPMPROXY_MODEL_DEFAULT; + + model = virXMLPropString(node, "model"); + if (model != NULL && + (def->model = virDomainTPMProxyModelTypeFromString(model)) < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unknown TPM Proxy frontend model '%s'"), model); + goto error; + } + + ctxt->node = node; + + path = virXPathString("string(./device/@path)", ctxt); + if (!path) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing TPM Proxy device path")); + goto error; + } + def->path = g_steal_pointer(&path); + + if (virDomainDeviceInfoParseXML(xmlopt, node, &def->info, flags) < 0) + goto error; + + return def; + + error: + virDomainTPMProxyDefFree(def); + return NULL; +} + static virDomainPanicDefPtr virDomainPanicDefParseXML(virDomainXMLOptionPtr xmlopt, xmlNodePtr node, @@ -17076,6 +17120,10 @@ virDomainDeviceDefParse(const char *xmlStr, return NULL; break; case VIR_DOMAIN_DEVICE_TPMPROXY: + if (!(dev->data.tpmproxy = virDomainTPMProxyDefParseXML(xmlopt, node, + ctxt, flags))) + return NULL; + break; case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_LAST: break; @@ -22024,6 +22072,23 @@ virDomainDefParseXML(xmlDocPtr xml, } VIR_FREE(nodes); + /* Parse TPM Proxy device */ + if ((n = virXPathNodeSet("./devices/tpmproxy", ctxt, &nodes)) < 0) + goto error; + + if (n > 1) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("only a single TPM Proxy device is supported")); + goto error; + } + + if (n > 0) { + if (!(def->tpmproxy = virDomainTPMProxyDefParseXML(xmlopt, nodes[0], + ctxt, flags))) + goto error; + } + VIR_FREE(nodes); + if ((n = virXPathNodeSet("./devices/nvram", ctxt, &nodes)) < 0) goto error; @@ -27166,6 +27231,26 @@ virDomainTPMDefFormat(virBufferPtr buf, } +static int +virDomainTPMProxyDefFormat(virBufferPtr buf, + virDomainTPMProxyDefPtr def, + unsigned int flags) +{ + virBufferAsprintf(buf, "<tpmproxy model='%s'>\n", + virDomainTPMProxyModelTypeToString(def->model)); + virBufferAdjustIndent(buf, 2); + virBufferEscapeString(buf, "<device path='%s'/>\n", def->path); + + if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) + return -1; + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</tpmproxy>\n"); + + return 0; +} + + static int virDomainSoundDefFormat(virBufferPtr buf, virDomainSoundDefPtr def, @@ -29853,6 +29938,11 @@ virDomainDefFormatInternalSetRootName(virDomainDefPtr def, goto error; } + if (def->tpmproxy) { + if (virDomainTPMProxyDefFormat(buf, def->tpmproxy, flags) < 0) + goto error; + } + for (n = 0; n < def->ngraphics; n++) { if (virDomainGraphicsDefFormat(buf, def->graphics[n], flags) < 0) goto error; @@ -31038,13 +31128,15 @@ virDomainDeviceDefCopy(virDomainDeviceDefPtr src, case VIR_DOMAIN_DEVICE_VSOCK: rc = virDomainVsockDefFormat(&buf, src->data.vsock); break; + case VIR_DOMAIN_DEVICE_TPMPROXY: + rc = virDomainTPMProxyDefFormat(&buf, src->data.tpmproxy, flags); + break; case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_SMARTCARD: case VIR_DOMAIN_DEVICE_MEMBALLOON: case VIR_DOMAIN_DEVICE_NVRAM: case VIR_DOMAIN_DEVICE_IOMMU: - case VIR_DOMAIN_DEVICE_TPMPROXY: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_INTERNAL_ERROR, _("Copying definition of '%d' type " -- 2.26.2

Update qemuxml2xmltest.c to add tests to validate the XML parsing of the new TPM Proxy device type. Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- tests/qemuxml2argvdata/ppc64-tpmproxy.xml | 31 +++++++++++++++++ tests/qemuxml2xmloutdata/ppc64-tpmproxy.xml | 37 +++++++++++++++++++++ tests/qemuxml2xmltest.c | 4 +++ 3 files changed, 72 insertions(+) create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy.xml create mode 100644 tests/qemuxml2xmloutdata/ppc64-tpmproxy.xml diff --git a/tests/qemuxml2argvdata/ppc64-tpmproxy.xml b/tests/qemuxml2argvdata/ppc64-tpmproxy.xml new file mode 100644 index 0000000000..fef82bd5c7 --- /dev/null +++ b/tests/qemuxml2argvdata/ppc64-tpmproxy.xml @@ -0,0 +1,31 @@ +<domain type='qemu'> + <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='ppc64' machine='pseries'>hvm</type> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <tpmproxy> + <device path='/dev/tpmrm0'/> + </tpmproxy> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/ppc64-tpmproxy.xml b/tests/qemuxml2xmloutdata/ppc64-tpmproxy.xml new file mode 100644 index 0000000000..9ad1da9434 --- /dev/null +++ b/tests/qemuxml2xmloutdata/ppc64-tpmproxy.xml @@ -0,0 +1,37 @@ +<domain type='qemu'> + <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='ppc64' machine='pseries'>hvm</type> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <controller type='usb' index='0' model='pci-ohci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> + <tpmproxy model='spapr-tpm-proxy'> + <device path='/dev/tpmrm0'/> + </tpmproxy> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 86f3d2c1f3..c9745ae337 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -610,6 +610,10 @@ mymain(void) DO_TEST("controller-usb-order", QEMU_CAPS_PIIX_DISABLE_S3, QEMU_CAPS_PIIX_DISABLE_S4); + DO_TEST("ppc64-tpmproxy", + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_PCI_OHCI, + QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY); DO_TEST_FULL("seclabel-dynamic-baselabel", WHEN_INACTIVE, ARG_QEMU_CAPS, NONE); -- 2.26.2

This patch wraps it up all the wiring done in previous patches, enabling a PPC64 guest to launch a guest using a TPM Proxy device. Note that device validation is already being done in qemu_validate.c, qemuValidateDomainDeviceDefTPMProxy(), on domain define time. We don't need to verify QEMU capabilities for this device again in qemu_command.c Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- src/libvirt_private.syms | 2 ++ src/qemu/qemu_alias.c | 16 ++++++++++++++++ src/qemu/qemu_command.c | 20 ++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 935ef7303b..b242c6164e 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -636,6 +636,8 @@ virDomainTPMBackendTypeToString; virDomainTPMDefFree; virDomainTPMModelTypeFromString; virDomainTPMModelTypeToString; +virDomainTPMProxyModelTypeFromString; +virDomainTPMProxyModelTypeToString; virDomainUSBDeviceDefForeach; virDomainVideoDefaultRAM; virDomainVideoDefClear; diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index b0ea62af39..b21d5bb514 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -413,6 +413,18 @@ qemuAssignDeviceTPMAlias(virDomainTPMDefPtr tpm, } +static int +qemuAssignDeviceTPMProxyAlias(virDomainTPMProxyDefPtr tpmproxy, + int idx) +{ + if (tpmproxy->info.alias) + return 0; + + tpmproxy->info.alias = g_strdup_printf("tpmproxy%d", idx); + return 0; +} + + int qemuAssignDeviceRedirdevAlias(virDomainDefPtr def, virDomainRedirdevDefPtr redirdev, @@ -673,6 +685,10 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps) if (qemuAssignDeviceTPMAlias(def->tpm, 0) < 0) return -1; } + if (def->tpmproxy) { + if (qemuAssignDeviceTPMProxyAlias(def->tpmproxy, 0) < 0) + return -1; + } for (i = 0; i < def->nmems; i++) { if (qemuAssignDeviceMemoryAlias(NULL, def->mems[i], false) < 0) return -1; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 9065164b1d..40a8505d24 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -9318,6 +9318,23 @@ qemuBuildTPMCommandLine(virCommandPtr cmd, return 0; } +static int +qemuBuildTPMProxyCommandLine(virCommandPtr cmd, + const virDomainDef *def) +{ + const virDomainTPMProxyDef *tpmproxy = def->tpmproxy; + + if (!tpmproxy) + return 0; + + virCommandAddArg(cmd, "-device"); + virCommandAddArgFormat(cmd, "%s,id=%s,host-path=%s", + virDomainTPMProxyModelTypeToString(tpmproxy->model), + tpmproxy->info.alias, tpmproxy->path); + + return 0; +} + static int qemuBuildSEVCommandLine(virDomainObjPtr vm, virCommandPtr cmd, virDomainSEVDefPtr sev) @@ -9999,6 +10016,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, if (qemuBuildTPMCommandLine(cmd, def, qemuCaps) < 0) return NULL; + if (qemuBuildTPMProxyCommandLine(cmd, def) < 0) + return NULL; + if (qemuBuildInputCommandLine(cmd, def, qemuCaps) < 0) return NULL; -- 2.26.2

Add a new test to assert the QEMU command line being built for the TPM Proxy device. Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- tests/qemuxml2argvdata/ppc64-tpmproxy.args | 28 ++++++++++++++++++++++ tests/qemuxml2argvtest.c | 4 ++++ 2 files changed, 32 insertions(+) create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy.args diff --git a/tests/qemuxml2argvdata/ppc64-tpmproxy.args b/tests/qemuxml2argvdata/ppc64-tpmproxy.args new file mode 100644 index 0000000000..a296a962ce --- /dev/null +++ b/tests/qemuxml2argvdata/ppc64-tpmproxy.args @@ -0,0 +1,28 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name QEMUGuest1 \ +-S \ +-machine pseries,accel=tcg,usb=off,dump-guest-core=off \ +-m 256 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-device pci-ohci,id=usb,bus=pci.0,addr=0x1 \ +-device spapr-tpm-proxy,id=tpmproxy0,host-path=/dev/tpmrm0 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6 diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 04febd1b0c..1a9b197907 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -2967,6 +2967,10 @@ mymain(void) QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, QEMU_CAPS_NEC_USB_XHCI, QEMU_CAPS_DEVICE_QEMU_XHCI); + DO_TEST("ppc64-tpmproxy", + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_PCI_OHCI, + QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY); DO_TEST("aarch64-usb-controller-qemu-xhci", QEMU_CAPS_OBJECT_GPEX, -- 2.26.2

Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- docs/news.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/news.xml b/docs/news.xml index 4cef804aac..21ee98c45b 100644 --- a/docs/news.xml +++ b/docs/news.xml @@ -44,6 +44,20 @@ <libvirt> <release version="v6.4.0" date="unreleased"> <section title="New features"> + <change> + <summary> + qemu: add TPM Proxy device support + </summary> + <description> + libvirt can now create guests using a new device type called + "TPM Proxy". This new device type connects with a TPM Resource + Manager in the host, which allows multiple processes to access + TPM features concurrently. Only one TPM Proxy is allowed per + guest. A guest using a TPM Proxy device can instantiate a vTPM + device at the same time. This device is supported only for pSeries + guests via the 'spapr-tpm-proxy' virtual device. + </description> + </change> </section> <section title="Improvements"> </section> -- 2.26.2

On 5/8/20 8:06 AM, Daniel Henrique Barboza wrote:
Hello,
This series implements a new device type for Libvirt called "TPM Proxy". This device acts as a proxy for TPM requisitions that the guest can make for an existing TPM Resource Manager in the host. The TPM Resource Manager multiplexes TPM access to multiple processes, allowing more than one process (guest) to use the host TPM at the same time.
A guest using a TPM Proxy device does not have access to all possible TPM features. In that case the guest will need to
'... does not have access to all possible TPM features': Is this device filtering? Since I never used this device, I am wondering what does this mean? What is the usage model of this device and in what case do you intend to use it? Do you give any guest now access to the host HW TPM and its PCRs and let the guest extend them? That's not something you would want, at least not for untrusted guests... keeping the device busy creating keys or loading it up with keys is another possible issue.
assign a vTPM device (tpm-spapr for PPC64). There is no restrictions of using both a vTPM and a TPM Proxy device at the same time, but only one TPM Proxy is allowed per guest.
At this moment, this device exists only for QEMU pSeries guests. A "model" field was added device to allow more models to be added when/if other architectures implements it.
Daniel Henrique Barboza (8): docs: documentation and schema for the new TPM Proxy device qemu: Extend QEMU capabilities with 'spapr-tpm-proxy' conf, qemu: adding VIR_DOMAIN_DEVICE_TPMPROXY device domain_conf.c: XML parsing for VIR_DOMAIN_DEVICE_TPMPROXY tests: add test for domain XML with TPM Proxy device model qemu: build command line for the TPM Proxy device tests/qemuxml2argvtest.c: add TPM Proxy command line test docs/news.xml: update for the new TPM Proxy device
docs/formatdomain.html.in | 42 +++++ docs/news.xml | 14 ++ docs/schemas/domaincommon.rng | 18 ++ src/conf/domain_capabilities.c | 1 + src/conf/domain_conf.c | 160 ++++++++++++++++++ src/conf/domain_conf.h | 18 ++ src/conf/virconftypes.h | 3 + src/libvirt_private.syms | 2 + src/qemu/qemu_alias.c | 16 ++ src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 21 +++ src/qemu/qemu_domain.c | 14 ++ src/qemu/qemu_domain_address.c | 2 + src/qemu/qemu_driver.c | 5 + src/qemu/qemu_hotplug.c | 3 + src/qemu/qemu_validate.c | 37 ++++ .../qemucapabilitiesdata/caps_4.2.0.ppc64.xml | 1 + .../qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + tests/qemuxml2argvdata/ppc64-tpmproxy.args | 28 +++ tests/qemuxml2argvdata/ppc64-tpmproxy.xml | 31 ++++ tests/qemuxml2argvtest.c | 4 + tests/qemuxml2xmloutdata/ppc64-tpmproxy.xml | 37 ++++ tests/qemuxml2xmltest.c | 4 + 24 files changed, 465 insertions(+) create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy.args create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy.xml create mode 100644 tests/qemuxml2xmloutdata/ppc64-tpmproxy.xml

(CCing Mike Roth since he implemented the QEMU support for this device) On 5/8/20 5:18 PM, Stefan Berger wrote:
On 5/8/20 8:06 AM, Daniel Henrique Barboza wrote:
Hello,
This series implements a new device type for Libvirt called "TPM Proxy". This device acts as a proxy for TPM requisitions that the guest can make for an existing TPM Resource Manager in the host. The TPM Resource Manager multiplexes TPM access to multiple processes, allowing more than one process (guest) to use the host TPM at the same time.
A guest using a TPM Proxy device does not have access to all possible TPM features. In that case the guest will need to
'... does not have access to all possible TPM features': Is this device filtering? Since I never used this device, I am wondering what does this mean? What is the usage model of this device and in what case do you intend to use it?
Do you give any guest now access to the host HW TPM and its PCRs and let the guest extend them? That's not something you would want, at least not for untrusted guests... keeping the device busy creating keys or loading it up with keys is another possible issue.
This device is part of the machinery the guest need to orchestrate with the PPC64 Ultravisor the transition to the Secure VM (SVM) mode. Inside QEMU, the 'host-path' provided in this device will be used with the following hypercall: - H_TPM_COMM (0xef10) For TPM_COMM_OP_EXECUTE operation: Send a request to a TPM and receive a response, opening a new TPM session if one has not already been opened. For TPM_COMM_OP_CLOSE_SESSION operation: Close the existing TPM session, if any. This was extracted from docs/specs/ppc-spapr-uv-hcalls.txt in QEMU tree. This document also has a use case notes for this specific hypercall and how it interacts with the TPM Resource Manager: ---- Use-case/notes: SVM filesystems are encrypted using a symmetric key. This key is then wrapped/encrypted using the public key of a trusted system which has the private key stored in the system's TPM. An Ultravisor will use this hcall to unwrap/unseal the symmetric key using the system's TPM device or a TPM Resource Manager associated with the device. The Ultravisor sets up a separate session key with the TPM in advance during host system boot. All sensitive in and out values will be encrypted using the session key. Though the hypervisor will see the 'in' and 'out' buffers in raw form, any sensitive contents will generally be encrypted using this session key. ---- I am not aware of any other use case for this device, aside from helping enable SVM mode for PPC64 guests in coordination with an Ultravisor. Hope this clarifies a bit what role the TPM Proxy/spapr-tpm-proxy plays out. All this said, I made the decision to not treat it as a new type of the regular vTPM device in Libvirt, given that there is no restriction of a guest using both devices at the same time and the TPM Proxy plays a different role than vTPM. If we decide that allowing both devices is a bad idea then we can limit the guest to use either one or the other. In that case, we can discuss whether it makes sense to change the logic in this series to make spapr-tpm-proxy another TPM passthrough model like tpm-spapr, instead of creating a new device type. Thanks, DHB
assign a vTPM device (tpm-spapr for PPC64). There is no restrictions of using both a vTPM and a TPM Proxy device at the same time, but only one TPM Proxy is allowed per guest.
At this moment, this device exists only for QEMU pSeries guests. A "model" field was added device to allow more models to be added when/if other architectures implements it.
Daniel Henrique Barboza (8): docs: documentation and schema for the new TPM Proxy device qemu: Extend QEMU capabilities with 'spapr-tpm-proxy' conf, qemu: adding VIR_DOMAIN_DEVICE_TPMPROXY device domain_conf.c: XML parsing for VIR_DOMAIN_DEVICE_TPMPROXY tests: add test for domain XML with TPM Proxy device model qemu: build command line for the TPM Proxy device tests/qemuxml2argvtest.c: add TPM Proxy command line test docs/news.xml: update for the new TPM Proxy device
docs/formatdomain.html.in | 42 +++++ docs/news.xml | 14 ++ docs/schemas/domaincommon.rng | 18 ++ src/conf/domain_capabilities.c | 1 + src/conf/domain_conf.c | 160 ++++++++++++++++++ src/conf/domain_conf.h | 18 ++ src/conf/virconftypes.h | 3 + src/libvirt_private.syms | 2 + src/qemu/qemu_alias.c | 16 ++ src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 21 +++ src/qemu/qemu_domain.c | 14 ++ src/qemu/qemu_domain_address.c | 2 + src/qemu/qemu_driver.c | 5 + src/qemu/qemu_hotplug.c | 3 + src/qemu/qemu_validate.c | 37 ++++ .../qemucapabilitiesdata/caps_4.2.0.ppc64.xml | 1 + .../qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + tests/qemuxml2argvdata/ppc64-tpmproxy.args | 28 +++ tests/qemuxml2argvdata/ppc64-tpmproxy.xml | 31 ++++ tests/qemuxml2argvtest.c | 4 + tests/qemuxml2xmloutdata/ppc64-tpmproxy.xml | 37 ++++ tests/qemuxml2xmltest.c | 4 + 24 files changed, 465 insertions(+) create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy.args create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy.xml create mode 100644 tests/qemuxml2xmloutdata/ppc64-tpmproxy.xml

On 5/8/20 5:39 PM, Daniel Henrique Barboza wrote:
(CCing Mike Roth since he implemented the QEMU support for this device)
On 5/8/20 5:18 PM, Stefan Berger wrote:
On 5/8/20 8:06 AM, Daniel Henrique Barboza wrote:
Hello,
This series implements a new device type for Libvirt called "TPM Proxy". This device acts as a proxy for TPM requisitions that the guest can make for an existing TPM Resource Manager in the host. The TPM Resource Manager multiplexes TPM access to multiple processes, allowing more than one process (guest) to use the host TPM at the same time.
A guest using a TPM Proxy device does not have access to all possible TPM features. In that case the guest will need to
'... does not have access to all possible TPM features': Is this device filtering? Since I never used this device, I am wondering what does this mean? What is the usage model of this device and in what case do you intend to use it?
Do you give any guest now access to the host HW TPM and its PCRs and let the guest extend them? That's not something you would want, at least not for untrusted guests... keeping the device busy creating keys or loading it up with keys is another possible issue.
This device is part of the machinery the guest need to orchestrate with the PPC64 Ultravisor the transition to the Secure VM (SVM) mode. Inside QEMU, the 'host-path' provided in this device will be used with the following hypercall:
- H_TPM_COMM (0xef10)
For TPM_COMM_OP_EXECUTE operation: Send a request to a TPM and receive a response, opening a new TPM session if one has not already been opened.
For TPM_COMM_OP_CLOSE_SESSION operation: Close the existing TPM session, if any.
This was extracted from docs/specs/ppc-spapr-uv-hcalls.txt in QEMU tree. This document also has a use case notes for this specific hypercall and how it interacts with the TPM Resource Manager:
----
Use-case/notes:
SVM filesystems are encrypted using a symmetric key. This key is then wrapped/encrypted using the public key of a trusted system which has the private key stored in the system's TPM. An Ultravisor will use this hcall to unwrap/unseal the symmetric key using the system's TPM device or a TPM Resource Manager associated with the device.
The Ultravisor sets up a separate session key with the TPM in advance during host system boot. All sensitive in and out values will be encrypted using the session key. Though the hypervisor will see the 'in' and 'out' buffers in raw form, any sensitive contents will generally be encrypted using this session key.
----
I am not aware of any other use case for this device, aside from helping enable SVM mode for PPC64 guests in coordination with an Ultravisor. Hope this clarifies a bit what role the TPM Proxy/spapr-tpm-proxy plays out.
All this said, I made the decision to not treat it as a new type of the regular vTPM device in Libvirt, given that there is no restriction of a guest using both devices at the same time and the TPM Proxy plays a different role than vTPM. If we decide that allowing both devices is a bad idea then we can limit the guest to use either one or the other. In that case, we can discuss whether it makes sense to change the logic in this series to make spapr-tpm-proxy another TPM passthrough model like tpm-spapr, instead of creating a new device type.
No I think both should be accessible. H_COMM_TPM would only be used at the start of the secure VM, right? It should probably shut down once it's not needed anymore so it cannot be abused by anything that happens to want to abuse H_COMM_TPM , like a malicious driver in Linux or so if that could be implemented. But that's obviously not something to worry about on the libvirt level, but I didn't understand what this devices exposes. I looked over the patches. They look good to me on first glance. Stefan
Thanks,
DHB
assign a vTPM device (tpm-spapr for PPC64). There is no restrictions of using both a vTPM and a TPM Proxy device at the same time, but only one TPM Proxy is allowed per guest.
At this moment, this device exists only for QEMU pSeries guests. A "model" field was added device to allow more models to be added when/if other architectures implements it.
Daniel Henrique Barboza (8): docs: documentation and schema for the new TPM Proxy device qemu: Extend QEMU capabilities with 'spapr-tpm-proxy' conf, qemu: adding VIR_DOMAIN_DEVICE_TPMPROXY device domain_conf.c: XML parsing for VIR_DOMAIN_DEVICE_TPMPROXY tests: add test for domain XML with TPM Proxy device model qemu: build command line for the TPM Proxy device tests/qemuxml2argvtest.c: add TPM Proxy command line test docs/news.xml: update for the new TPM Proxy device
docs/formatdomain.html.in | 42 +++++ docs/news.xml | 14 ++ docs/schemas/domaincommon.rng | 18 ++ src/conf/domain_capabilities.c | 1 + src/conf/domain_conf.c | 160 ++++++++++++++++++ src/conf/domain_conf.h | 18 ++ src/conf/virconftypes.h | 3 + src/libvirt_private.syms | 2 + src/qemu/qemu_alias.c | 16 ++ src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 21 +++ src/qemu/qemu_domain.c | 14 ++ src/qemu/qemu_domain_address.c | 2 + src/qemu/qemu_driver.c | 5 + src/qemu/qemu_hotplug.c | 3 + src/qemu/qemu_validate.c | 37 ++++ .../qemucapabilitiesdata/caps_4.2.0.ppc64.xml | 1 + .../qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + tests/qemuxml2argvdata/ppc64-tpmproxy.args | 28 +++ tests/qemuxml2argvdata/ppc64-tpmproxy.xml | 31 ++++ tests/qemuxml2argvtest.c | 4 + tests/qemuxml2xmloutdata/ppc64-tpmproxy.xml | 37 ++++ tests/qemuxml2xmltest.c | 4 + 24 files changed, 465 insertions(+) create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy.args create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy.xml create mode 100644 tests/qemuxml2xmloutdata/ppc64-tpmproxy.xml
participants (4)
-
Daniel Henrique Barboza
-
Daniel P. Berrangé
-
David Gibson
-
Stefan Berger