[PATCH v5 00/10] Introducing TPM Proxy device support for PPC64

changes in v5: - rebased and fixed commits to master at d265171b5784 - moved two TPMs validation from domain_conf.c (patch 05) to qemu_domain.c (patch 06) Gitlab tree: https://gitlab.com/danielhb/libvirt/tree/spapr_tpm_proxy_v5 v4 link: https://www.redhat.com/archives/libvir-list/2020-May/msg00814.html v3 link: https://www.redhat.com/archives/libvir-list/2020-May/msg00642.html v2 link: https://www.redhat.com/archives/libvir-list/2020-May/msg00604.html v1 link: https://www.redhat.com/archives/libvir-list/2020-May/msg00604.html Daniel Henrique Barboza (10): docs: documentation and schema for the new TPM Proxy model qemu: Extend QEMU capabilities with 'spapr-tpm-proxy' qemu_extdevice.c: remove unneeded 'ret' variable qemu_tpm, security, tests: change 'switch' clauses for 'if' conf, qemu, security, tests: introducing 'def->tpms' array qemu: add validations after TPM Proxy model introduction tests: add XML schema tests for the TPM Proxy device qemu: build command line for the TPM Proxy device tests/qemuxml2argvtest.c: add TPM Proxy command line tests docs/news.xml: update for the new TPM Proxy device docs/formatdomain.html.in | 19 ++++- docs/news.xml | 17 +++++ docs/schemas/domaincommon.rng | 1 + src/conf/domain_audit.c | 4 +- src/conf/domain_conf.c | 50 +++++++----- src/conf/domain_conf.h | 6 +- src/qemu/qemu_alias.c | 9 ++- src/qemu/qemu_capabilities.c | 4 + src/qemu/qemu_capabilities.h | 3 + src/qemu/qemu_cgroup.c | 10 ++- src/qemu/qemu_command.c | 59 +++++++++++--- src/qemu/qemu_domain.c | 68 ++++++++++++++--- src/qemu/qemu_domain_address.c | 11 ++- src/qemu/qemu_extdevice.c | 24 +++--- src/qemu/qemu_tpm.c | 76 +++++++++---------- src/qemu/qemu_validate.c | 19 +++++ src/security/security_dac.c | 8 +- src/security/security_selinux.c | 44 +++++------ src/security/virt-aa-helper.c | 14 ++-- .../qemucapabilitiesdata/caps_4.2.0.ppc64.xml | 1 + .../qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + tests/qemuxml2argvdata/ppc64-tpm-double.xml | 34 +++++++++ .../ppc64-tpmproxy-double.xml | 38 ++++++++++ .../ppc64-tpmproxy-single.ppc64-latest.args | 34 +++++++++ .../ppc64-tpmproxy-single.xml | 33 ++++++++ .../ppc64-tpmproxy-with-tpm.ppc64-latest.args | 37 +++++++++ .../ppc64-tpmproxy-with-tpm.xml | 36 +++++++++ tests/qemuxml2argvtest.c | 33 +++++--- .../ppc64-tpmproxy-single.ppc64-latest.xml | 42 ++++++++++ .../ppc64-tpmproxy-with-tpm.ppc64-latest.xml | 46 +++++++++++ tests/qemuxml2xmltest.c | 2 + 31 files changed, 631 insertions(+), 152 deletions(-) create mode 100644 tests/qemuxml2argvdata/ppc64-tpm-double.xml create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-double.xml create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-single.ppc64-latest.args create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-single.xml create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-with-tpm.ppc64-latest.args create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-with-tpm.xml create mode 100644 tests/qemuxml2xmloutdata/ppc64-tpmproxy-single.ppc64-latest.xml create mode 100644 tests/qemuxml2xmloutdata/ppc64-tpmproxy-with-tpm.ppc64-latest.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 a new TPM model type called 'spapr-tpm-proxy' that creates this new TPM Proxy device. This model is valid only for the 'passthrough' backend. An example of a TPM Proxy device connected to a TPM Resource Manager '/dev/tpmrm0' will look like this: <tpm model='spapr-tpm-proxy'> <backend type='passthrough'> <device path='/dev/tpmrm0'/> </backend> </tpm> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- docs/formatdomain.html.in | 19 ++++++++++++++++++- docs/schemas/domaincommon.rng | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 23eb029234..15109e136c 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -8792,6 +8792,18 @@ qemu-kvm -net nic,model=? /dev/null backend device is a TPM 2.0. <span class="since">Since 6.1.0</span>, pSeries guests on PPC64 are supported and the default is <code>tpm-spapr</code>. + + <span class="since">Since 6.4.0</span>, a new model called + <code>spapr-tpm-proxy</code> was added for pSeries guests. This model + only works with the <code>passthrough</code> backend. It creates a + TPM Proxy device that communicates with an existing TPM Resource Manager + in the host, for example <code>/dev/tpmrm0</code>, enabling the guest to + run in secure virtual machine mode with the help of an Ultravisor. Adding + a TPM Proxy to a pSeries guest brings no security benefits unless the guest + is running on a PPC64 host that has an Ultravisor and a TPM Resource Manager. + Only one TPM Proxy device is allowed per guest, but a TPM Proxy device can + be added together with + other TPM devices. </p> </dd> <dt><code>backend</code></dt> @@ -8804,7 +8816,7 @@ qemu-kvm -net nic,model=? /dev/null <dt><code>passthrough</code></dt> <dd> <p> - Use the host's TPM device. + Use the host's TPM or TPM Resource Manager device. </p> <p> This backend type requires exclusive access to a TPM device on @@ -8812,6 +8824,11 @@ qemu-kvm -net nic,model=? /dev/null qualified file name is specified by path attribute of the <code>source</code> element. If no file name is specified then /dev/tpm0 is automatically used. + + <span class="since">Since 6.4.0</span>, when choosing the + <code>spapr-tpm-proxy</code> model, the file name specified is + expected to be a TPM Resource Manager device, e.g. + <code>/dev/tpmrm0</code>. </p> </dd> </dl> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 9d60b090f3..50860419c3 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4610,6 +4610,7 @@ <value>tpm-tis</value> <value>tpm-crb</value> <value>tpm-spapr</value> + <value>spapr-tpm-proxy</value> </choice> </attribute> </optional> -- 2.26.2

Expose the TPM Proxy support for PPC64 guests by creating a new cap called QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY. 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, this device will be used with the H_TPM_COMM hypercall to connect with the TPM Resource Manager, enabling the guest to open and close TPM sessions with the host TPM. Reviewed-by: Stefan Berger <stefanb@linux.ibm.com> Reviewed-by: Ján Tomko <jtomko@redhat.com> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- src/qemu/qemu_capabilities.c | 4 ++++ src/qemu/qemu_capabilities.h | 3 +++ tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + 4 files changed, 9 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index d9b339cbfb..56bb013d7e 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -582,6 +582,9 @@ VIR_ENUM_IMPL(virQEMUCaps, "tcg", "virtio-blk-pci.scsi.default.disabled", "pvscsi", + + /* 370 */ + "spapr-tpm-proxy", ); @@ -1305,6 +1308,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "vhost-user-fs-device", QEMU_CAPS_DEVICE_VHOST_USER_FS }, { "tcg-accel", QEMU_CAPS_TCG }, { "pvscsi", QEMU_CAPS_SCSI_PVSCSI }, + { "spapr-tpm-proxy", QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY }, }; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 076ecad0f7..478cd2398f 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -564,6 +564,9 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_VIRTIO_BLK_SCSI_DEFAULT_DISABLED, /* virtio-blk-pci.scsi disabled by default */ QEMU_CAPS_SCSI_PVSCSI, /* -device pvscsi */ + /* 370 */ + 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 eeec181f62..b6b226da51 100644 --- a/tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_4.2.0.ppc64.xml @@ -185,6 +185,7 @@ <flag name='machine.pseries.cap-ibs'/> <flag name='tcg'/> <flag name='pvscsi'/> + <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 69e5b4c8fa..ee5ab416aa 100644 --- a/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml @@ -201,6 +201,7 @@ <flag name='tcg'/> <flag name='virtio-blk-pci.scsi.default.disabled'/> <flag name='pvscsi'/> + <flag name='spapr-tpm-proxy'/> <version>5000000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>42900241</microcodeVersion> -- 2.26.2

qemuExtDevicesInitPaths() does not need 'ret'. Reviewed-by: Stefan Berger <stefanb@linux.ibm.com> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- src/qemu/qemu_extdevice.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c index 2096272761..2ff3f68f5d 100644 --- a/src/qemu/qemu_extdevice.c +++ b/src/qemu/qemu_extdevice.c @@ -73,12 +73,10 @@ static int qemuExtDevicesInitPaths(virQEMUDriverPtr driver, virDomainDefPtr def) { - int ret = 0; - if (def->tpm) - ret = qemuExtTPMInitPaths(driver, def); + return qemuExtTPMInitPaths(driver, def); - return ret; + return 0; } -- 2.26.2

This trivial rework is aimed to reduce the amount of line changes made by the next patch, when 'def->tpm' will become a 'def->tpms' array. Instead of using a 'switch' where only the VIR_DOMAIN_TPM_TYPE_EMULATOR label does something, use an 'if' clause instead. Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- src/qemu/qemu_tpm.c | 44 +++++---------------------------- src/security/security_selinux.c | 16 ++---------- src/security/virt-aa-helper.c | 7 +----- tests/qemuxml2argvtest.c | 7 +----- 4 files changed, 10 insertions(+), 64 deletions(-) diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c index fe567f440c..afec0e5328 100644 --- a/src/qemu/qemu_tpm.c +++ b/src/qemu/qemu_tpm.c @@ -680,14 +680,9 @@ qemuExtTPMInitPaths(virQEMUDriverPtr driver, { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); - switch (def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) return qemuTPMEmulatorInitPaths(def->tpm, cfg->swtpmStorageDir, def->uuid); - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - case VIR_DOMAIN_TPM_TYPE_LAST: - break; - } return 0; } @@ -700,8 +695,7 @@ qemuExtTPMPrepareHost(virQEMUDriverPtr driver, g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); g_autofree char *shortName = NULL; - switch (def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { shortName = virDomainDefGetShortName(def); if (!shortName) return -1; @@ -711,9 +705,6 @@ qemuExtTPMPrepareHost(virQEMUDriverPtr driver, cfg->swtpm_group, cfg->swtpmStateDir, cfg->user, shortName); - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - case VIR_DOMAIN_TPM_TYPE_LAST: - break; } return 0; @@ -723,15 +714,8 @@ qemuExtTPMPrepareHost(virQEMUDriverPtr driver, void qemuExtTPMCleanupHost(virDomainDefPtr def) { - switch (def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) qemuTPMDeleteEmulatorStorage(def->tpm); - break; - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - case VIR_DOMAIN_TPM_TYPE_LAST: - /* nothing to do */ - break; - } } @@ -825,15 +809,9 @@ qemuExtTPMStart(virQEMUDriverPtr driver, { virDomainTPMDefPtr tpm = vm->def->tpm; - switch (tpm->type) { - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) return qemuExtTPMStartEmulator(driver, vm, incomingMigration); - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - case VIR_DOMAIN_TPM_TYPE_LAST: - break; - } - return 0; } @@ -845,18 +823,13 @@ qemuExtTPMStop(virQEMUDriverPtr driver, g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); g_autofree char *shortName = NULL; - switch (vm->def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (vm->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { shortName = virDomainDefGetShortName(vm->def); if (!shortName) return; qemuTPMEmulatorStop(cfg->swtpmStateDir, shortName); qemuSecurityCleanupTPMEmulator(driver, vm); - break; - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - case VIR_DOMAIN_TPM_TYPE_LAST: - break; } return; @@ -873,8 +846,7 @@ qemuExtTPMSetupCgroup(virQEMUDriverPtr driver, int rc; pid_t pid; - switch (def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { shortName = virDomainDefGetShortName(def); if (!shortName) return -1; @@ -886,10 +858,6 @@ qemuExtTPMSetupCgroup(virQEMUDriverPtr driver, } if (virCgroupAddProcess(cgroup, pid) < 0) return -1; - break; - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - case VIR_DOMAIN_TPM_TYPE_LAST: - break; } return 0; diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 9a929debe1..914a252df1 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -3493,10 +3493,7 @@ virSecuritySELinuxSetTPMLabels(virSecurityManagerPtr mgr, if (seclabel == NULL) return 0; - switch (def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - break; - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { ret = virSecuritySELinuxSetFileLabels( mgr, def->tpm->data.emulator.storagepath, seclabel); @@ -3504,9 +3501,6 @@ virSecuritySELinuxSetTPMLabels(virSecurityManagerPtr mgr, ret = virSecuritySELinuxSetFileLabels( mgr, def->tpm->data.emulator.logfile, seclabel); - break; - case VIR_DOMAIN_TPM_TYPE_LAST: - break; } return ret; @@ -3519,18 +3513,12 @@ virSecuritySELinuxRestoreTPMLabels(virSecurityManagerPtr mgr, { int ret = 0; - switch (def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - break; - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { ret = virSecuritySELinuxRestoreFileLabels( mgr, def->tpm->data.emulator.storagepath); if (ret == 0 && def->tpm->data.emulator.logfile) ret = virSecuritySELinuxRestoreFileLabels( mgr, def->tpm->data.emulator.logfile); - break; - case VIR_DOMAIN_TPM_TYPE_LAST: - break; } return ret; diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index 6e6dd1b1db..6e8f77e4dd 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -1210,8 +1210,7 @@ get_files(vahControl * ctl) char *shortName = NULL; const char *tpmpath = NULL; - switch (ctl->def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (ctl->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { shortName = virDomainDefGetShortName(ctl->def); switch (ctl->def->tpm->version) { @@ -1244,10 +1243,6 @@ get_files(vahControl * ctl) RUNSTATEDIR, shortName); VIR_FREE(shortName); - break; - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - case VIR_DOMAIN_TPM_TYPE_LAST: - break; } } diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 4f613e8f1a..c40ce64cbf 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -438,15 +438,10 @@ testCompareXMLToArgvCreateArgs(virQEMUDriverPtr drv, } if (vm->def->tpm) { - switch (vm->def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (vm->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { VIR_FREE(vm->def->tpm->data.emulator.source.data.file.path); vm->def->tpm->data.emulator.source.data.file.path = g_strdup("/dev/test"); vm->def->tpm->data.emulator.source.type = VIR_DOMAIN_CHR_TYPE_FILE; - break; - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - case VIR_DOMAIN_TPM_TYPE_LAST: - break; } } -- 2.26.2

On 5/21/20 9:07 AM, Daniel Henrique Barboza wrote:
This trivial rework is aimed to reduce the amount of line changes made by the next patch, when 'def->tpm' will become a 'def->tpms' array.
Instead of using a 'switch' where only the VIR_DOMAIN_TPM_TYPE_EMULATOR label does something, use an 'if' clause instead.
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
--- src/qemu/qemu_tpm.c | 44 +++++---------------------------- src/security/security_selinux.c | 16 ++---------- src/security/virt-aa-helper.c | 7 +----- tests/qemuxml2argvtest.c | 7 +----- 4 files changed, 10 insertions(+), 64 deletions(-)
diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c index fe567f440c..afec0e5328 100644 --- a/src/qemu/qemu_tpm.c +++ b/src/qemu/qemu_tpm.c @@ -680,14 +680,9 @@ qemuExtTPMInitPaths(virQEMUDriverPtr driver, { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
- switch (def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) return qemuTPMEmulatorInitPaths(def->tpm, cfg->swtpmStorageDir, def->uuid); - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - case VIR_DOMAIN_TPM_TYPE_LAST: - break; - }
return 0; } @@ -700,8 +695,7 @@ qemuExtTPMPrepareHost(virQEMUDriverPtr driver, g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); g_autofree char *shortName = NULL;
- switch (def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { shortName = virDomainDefGetShortName(def); if (!shortName) return -1; @@ -711,9 +705,6 @@ qemuExtTPMPrepareHost(virQEMUDriverPtr driver, cfg->swtpm_group, cfg->swtpmStateDir, cfg->user, shortName); - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - case VIR_DOMAIN_TPM_TYPE_LAST: - break; }
return 0; @@ -723,15 +714,8 @@ qemuExtTPMPrepareHost(virQEMUDriverPtr driver, void qemuExtTPMCleanupHost(virDomainDefPtr def) { - switch (def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) qemuTPMDeleteEmulatorStorage(def->tpm); - break; - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - case VIR_DOMAIN_TPM_TYPE_LAST: - /* nothing to do */ - break; - } }
@@ -825,15 +809,9 @@ qemuExtTPMStart(virQEMUDriverPtr driver, { virDomainTPMDefPtr tpm = vm->def->tpm;
- switch (tpm->type) { - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) return qemuExtTPMStartEmulator(driver, vm, incomingMigration);
- case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - case VIR_DOMAIN_TPM_TYPE_LAST: - break; - } - return 0; }
@@ -845,18 +823,13 @@ qemuExtTPMStop(virQEMUDriverPtr driver, g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); g_autofree char *shortName = NULL;
- switch (vm->def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (vm->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { shortName = virDomainDefGetShortName(vm->def); if (!shortName) return;
qemuTPMEmulatorStop(cfg->swtpmStateDir, shortName); qemuSecurityCleanupTPMEmulator(driver, vm); - break; - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - case VIR_DOMAIN_TPM_TYPE_LAST: - break; }
return; @@ -873,8 +846,7 @@ qemuExtTPMSetupCgroup(virQEMUDriverPtr driver, int rc; pid_t pid;
- switch (def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { shortName = virDomainDefGetShortName(def); if (!shortName) return -1; @@ -886,10 +858,6 @@ qemuExtTPMSetupCgroup(virQEMUDriverPtr driver, } if (virCgroupAddProcess(cgroup, pid) < 0) return -1; - break; - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - case VIR_DOMAIN_TPM_TYPE_LAST: - break; }
return 0; diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 9a929debe1..914a252df1 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -3493,10 +3493,7 @@ virSecuritySELinuxSetTPMLabels(virSecurityManagerPtr mgr, if (seclabel == NULL) return 0;
- switch (def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - break; - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { ret = virSecuritySELinuxSetFileLabels( mgr, def->tpm->data.emulator.storagepath, seclabel); @@ -3504,9 +3501,6 @@ virSecuritySELinuxSetTPMLabels(virSecurityManagerPtr mgr, ret = virSecuritySELinuxSetFileLabels( mgr, def->tpm->data.emulator.logfile, seclabel); - break; - case VIR_DOMAIN_TPM_TYPE_LAST: - break; }
return ret; @@ -3519,18 +3513,12 @@ virSecuritySELinuxRestoreTPMLabels(virSecurityManagerPtr mgr, { int ret = 0;
- switch (def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - break; - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { ret = virSecuritySELinuxRestoreFileLabels( mgr, def->tpm->data.emulator.storagepath); if (ret == 0 && def->tpm->data.emulator.logfile) ret = virSecuritySELinuxRestoreFileLabels( mgr, def->tpm->data.emulator.logfile); - break; - case VIR_DOMAIN_TPM_TYPE_LAST: - break; }
return ret; diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index 6e6dd1b1db..6e8f77e4dd 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -1210,8 +1210,7 @@ get_files(vahControl * ctl) char *shortName = NULL; const char *tpmpath = NULL;
- switch (ctl->def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (ctl->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { shortName = virDomainDefGetShortName(ctl->def);
switch (ctl->def->tpm->version) { @@ -1244,10 +1243,6 @@ get_files(vahControl * ctl) RUNSTATEDIR, shortName);
VIR_FREE(shortName); - break; - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - case VIR_DOMAIN_TPM_TYPE_LAST: - break; } }
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 4f613e8f1a..c40ce64cbf 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -438,15 +438,10 @@ testCompareXMLToArgvCreateArgs(virQEMUDriverPtr drv, }
if (vm->def->tpm) { - switch (vm->def->tpm->type) { - case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (vm->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { VIR_FREE(vm->def->tpm->data.emulator.source.data.file.path); vm->def->tpm->data.emulator.source.data.file.path = g_strdup("/dev/test"); vm->def->tpm->data.emulator.source.type = VIR_DOMAIN_CHR_TYPE_FILE; - break; - case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: - case VIR_DOMAIN_TPM_TYPE_LAST: - break; } }

A TPM Proxy device can coexist with a regular TPM, but the current domain definition supports only a single TPM device in the 'tpm' pointer. This patch replaces this existing pointer in the domain definition to an array of TPM devices. All files that references the old pointer were adapted to handle the new array instead. virDomainDefParseXML() TPM related code was adapted to handle the parsing of an extra TPM device. TPM validations after this new scenario will be updated in the next patch. Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- src/conf/domain_audit.c | 4 +-- src/conf/domain_conf.c | 50 +++++++++++++++++++------------ src/conf/domain_conf.h | 6 +++- src/qemu/qemu_alias.c | 4 +-- src/qemu/qemu_cgroup.c | 10 ++++--- src/qemu/qemu_command.c | 34 ++++++++++++++------- src/qemu/qemu_domain.c | 31 +++++++++++++------- src/qemu/qemu_domain_address.c | 11 ++++--- src/qemu/qemu_extdevice.c | 18 +++++++----- src/qemu/qemu_tpm.c | 52 +++++++++++++++++++++++++-------- src/security/security_dac.c | 8 ++--- src/security/security_selinux.c | 32 ++++++++++++-------- src/security/virt-aa-helper.c | 9 ++++-- tests/qemuxml2argvtest.c | 13 +++++---- 14 files changed, 186 insertions(+), 96 deletions(-) diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c index 1b0abb21a0..8bc6633af4 100644 --- a/src/conf/domain_audit.c +++ b/src/conf/domain_audit.c @@ -821,8 +821,8 @@ virDomainAuditStart(virDomainObjPtr vm, const char *reason, bool success) for (i = 0; i < vm->def->nrngs; i++) virDomainAuditRNG(vm, NULL, vm->def->rngs[i], "start", true); - if (vm->def->tpm) - virDomainAuditTPM(vm, vm->def->tpm, "start", true); + for (i = 0; i < vm->def->ntpms; i++) + virDomainAuditTPM(vm, vm->def->tpms[i], "start", true); for (i = 0; i < vm->def->nshmems; i++) virDomainAuditShmem(vm, vm->def->shmems[i], "start", true); diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index c201fc901d..be90762af4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1165,6 +1165,7 @@ VIR_ENUM_IMPL(virDomainTPMModel, "tpm-tis", "tpm-crb", "tpm-spapr", + "spapr-tpm-proxy", ); VIR_ENUM_IMPL(virDomainTPMBackend, @@ -3479,7 +3480,9 @@ void virDomainDefFree(virDomainDefPtr def) virDomainMemoryDefFree(def->mems[i]); VIR_FREE(def->mems); - virDomainTPMDefFree(def->tpm); + for (i = 0; i < def->ntpms; i++) + virDomainTPMDefFree(def->tpms[i]); + VIR_FREE(def->tpms); for (i = 0; i < def->npanics; i++) virDomainPanicDefFree(def->panics[i]); @@ -4312,10 +4315,10 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def, if ((rc = cb(def, &device, &def->shmems[i]->info, opaque)) != 0) return rc; } - if (def->tpm) { - device.type = VIR_DOMAIN_DEVICE_TPM; - device.data.tpm = def->tpm; - if ((rc = cb(def, &device, &def->tpm->info, opaque)) != 0) + device.type = VIR_DOMAIN_DEVICE_TPM; + for (i = 0; i < def->ntpms; i++) { + device.data.tpm = def->tpms[i]; + if ((rc = cb(def, &device, &def->tpms[i]->info, opaque)) != 0) return rc; } device.type = VIR_DOMAIN_DEVICE_PANIC; @@ -21964,15 +21967,23 @@ virDomainDefParseXML(xmlDocPtr xml, if ((n = virXPathNodeSet("./devices/tpm", ctxt, &nodes)) < 0) goto error; - if (n > 1) { + if (n > 2) { virReportError(VIR_ERR_XML_ERROR, "%s", - _("only a single TPM device is supported")); + _("a maximum of two TPM devices is supported, one of " + "them being a TPM Proxy device")); goto error; } - if (n > 0) { - if (!(def->tpm = virDomainTPMDefParseXML(xmlopt, nodes[0], ctxt, flags))) + if (n && VIR_ALLOC_N(def->tpms, n) < 0) + goto error; + + for (i = 0; i < n; i++) { + virDomainTPMDefPtr tpm = virDomainTPMDefParseXML(xmlopt, nodes[i], + ctxt, flags); + if (!tpm) goto error; + + def->tpms[def->ntpms++] = tpm; } VIR_FREE(nodes); @@ -24334,16 +24345,19 @@ virDomainDefCheckABIStabilityFlags(virDomainDefPtr src, goto error; } - if (src->tpm && dst->tpm) { - if (!virDomainTPMDefCheckABIStability(src->tpm, dst->tpm)) - goto error; - } else if (src->tpm || dst->tpm) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Either both target and source domains or none of " - "them must have TPM device present")); + if (src->ntpms != dst->ntpms) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target domain TPM device count %zu " + "does not match source %zu"), + dst->ntpms, src->ntpms); goto error; } + for (i = 0; i < src->ntpms; i++) { + if (!virDomainTPMDefCheckABIStability(src->tpms[i], dst->tpms[i])) + goto error; + } + if (src->nmems != dst->nmems) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target domain memory device count %zu " @@ -29784,8 +29798,8 @@ virDomainDefFormatInternalSetRootName(virDomainDefPtr def, goto error; } - if (def->tpm) { - if (virDomainTPMDefFormat(buf, def->tpm, flags) < 0) + for (n = 0; n < def->ntpms; n++) { + if (virDomainTPMDefFormat(buf, def->tpms[n], flags) < 0) goto error; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index ddc75d8de2..32ae272cac 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1293,6 +1293,7 @@ typedef enum { VIR_DOMAIN_TPM_MODEL_TIS, VIR_DOMAIN_TPM_MODEL_CRB, VIR_DOMAIN_TPM_MODEL_SPAPR, + VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY, VIR_DOMAIN_TPM_MODEL_LAST } virDomainTPMModel; @@ -2623,11 +2624,14 @@ struct _virDomainDef { size_t npanics; virDomainPanicDefPtr *panics; + /* At maximum 2 TPMs on the domain, if a TPM Proxy is present. */ + size_t ntpms; + virDomainTPMDefPtr *tpms; + /* Only 1 */ virDomainWatchdogDefPtr watchdog; virDomainMemballoonDefPtr memballoon; virDomainNVRAMDefPtr nvram; - virDomainTPMDefPtr tpm; virCPUDefPtr cpu; virSysinfoDefPtr sysinfo; virDomainRedirFilterDefPtr redirfilter; diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index d6527cb046..85fdb85940 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -669,8 +669,8 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps) if (qemuAssignDeviceRNGAlias(def, def->rngs[i]) < 0) return -1; } - if (def->tpm) { - if (qemuAssignDeviceTPMAlias(def->tpm, 0) < 0) + for (i = 0; i < def->ntpms; i++) { + if (qemuAssignDeviceTPMAlias(def->tpms[i], 0) < 0) return -1; } for (i = 0; i < def->nmems; i++) { diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index d92202f847..eb0f03d4aa 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -332,10 +332,10 @@ qemuSetupChardevCgroupCB(virDomainDefPtr def G_GNUC_UNUSED, static int -qemuSetupTPMCgroup(virDomainObjPtr vm) +qemuSetupTPMCgroup(virDomainObjPtr vm, + virDomainTPMDefPtr dev) { int ret = 0; - virDomainTPMDefPtr dev = vm->def->tpm; switch (dev->type) { case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: @@ -805,8 +805,10 @@ qemuSetupDevicesCgroup(virDomainObjPtr vm) vm) < 0) return -1; - if (vm->def->tpm && qemuSetupTPMCgroup(vm) < 0) - return -1; + for (i = 0; i < vm->def->ntpms; i++) { + if (qemuSetupTPMCgroup(vm, vm->def->tpms[i]) < 0) + return -1; + } for (i = 0; i < vm->def->nhostdevs; i++) { /* This may allow /dev/vfio/vfio multiple times, but that diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 419eca5675..59caff08f2 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8890,10 +8890,10 @@ qemuBuildDomainLoaderCommandLine(virCommandPtr cmd, static char * qemuBuildTPMDevStr(const virDomainDef *def, + virDomainTPMDefPtr tpm, virQEMUCapsPtr qemuCaps) { g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; - virDomainTPMDef *tpm = def->tpm; const char *model = virDomainTPMModelTypeToString(tpm->model); virBufferAsprintf(&buf, "%s,tpmdev=tpm-%s,id=%s", @@ -8932,13 +8932,12 @@ qemuBuildTPMOpenBackendFDs(const char *tpmdev, static char * -qemuBuildTPMBackendStr(const virDomainDef *def, - virCommandPtr cmd, +qemuBuildTPMBackendStr(virCommandPtr cmd, + virDomainTPMDefPtr tpm, int *tpmfd, int *cancelfd, char **chardev) { - const virDomainTPMDef *tpm = def->tpm; g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; g_autofree char *cancel_path = NULL; g_autofree char *devset = NULL; @@ -8992,6 +8991,7 @@ qemuBuildTPMBackendStr(const virDomainDef *def, static int qemuBuildTPMCommandLine(virCommandPtr cmd, const virDomainDef *def, + virDomainTPMDefPtr tpm, virQEMUCapsPtr qemuCaps) { char *optstr; @@ -9000,10 +9000,7 @@ qemuBuildTPMCommandLine(virCommandPtr cmd, int cancelfd = -1; char *fdset; - if (!def->tpm) - return 0; - - if (!(optstr = qemuBuildTPMBackendStr(def, cmd, + if (!(optstr = qemuBuildTPMBackendStr(cmd, tpm, &tpmfd, &cancelfd, &chardev))) return -1; @@ -9032,7 +9029,7 @@ qemuBuildTPMCommandLine(virCommandPtr cmd, VIR_FREE(fdset); } - if (!(optstr = qemuBuildTPMDevStr(def, qemuCaps))) + if (!(optstr = qemuBuildTPMDevStr(def, tpm, qemuCaps))) return -1; virCommandAddArgList(cmd, "-device", optstr, NULL); @@ -9041,6 +9038,23 @@ qemuBuildTPMCommandLine(virCommandPtr cmd, return 0; } + +static int +qemuBuildTPMsCommandLine(virCommandPtr cmd, + const virDomainDef *def, + virQEMUCapsPtr qemuCaps) +{ + size_t i; + + for (i = 0; i < def->ntpms; i++) { + if (qemuBuildTPMCommandLine(cmd, def, def->tpms[i], qemuCaps) < 0) + return -1; + } + + return 0; +} + + static int qemuBuildSEVCommandLine(virDomainObjPtr vm, virCommandPtr cmd, virDomainSEVDefPtr sev) @@ -9720,7 +9734,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, chardevStdioLogd) < 0) return NULL; - if (qemuBuildTPMCommandLine(cmd, def, qemuCaps) < 0) + if (qemuBuildTPMsCommandLine(cmd, def, qemuCaps) < 0) return NULL; if (qemuBuildInputCommandLine(cmd, def, qemuCaps) < 0) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index d5e3d1a3cc..3173fc3a3b 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -11585,16 +11585,9 @@ qemuDomainSetupAllChardevs(virQEMUDriverConfigPtr cfg G_GNUC_UNUSED, static int qemuDomainSetupTPM(virQEMUDriverConfigPtr cfg G_GNUC_UNUSED, - virDomainObjPtr vm, + virDomainTPMDefPtr dev, const struct qemuDomainCreateDeviceData *data) { - virDomainTPMDefPtr dev = vm->def->tpm; - - if (!dev) - return 0; - - VIR_DEBUG("Setting up TPM"); - switch (dev->type) { case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: if (qemuDomainCreateDevice(dev->data.passthrough.source.data.file.path, @@ -11608,7 +11601,25 @@ qemuDomainSetupTPM(virQEMUDriverConfigPtr cfg G_GNUC_UNUSED, break; } - VIR_DEBUG("Setup TPM"); + return 0; +} + + +static int +qemuDomainSetupAllTPMs(virQEMUDriverConfigPtr cfg G_GNUC_UNUSED, + virDomainObjPtr vm, + const struct qemuDomainCreateDeviceData *data) +{ + size_t i; + + VIR_DEBUG("Setting up TPMs"); + + for (i = 0; i < vm->def->ntpms; i++) { + if (qemuDomainSetupTPM(cfg, vm->def->tpms[i], data) < 0) + return -1; + } + + VIR_DEBUG("Setup all TPMs"); return 0; } @@ -11834,7 +11845,7 @@ qemuDomainBuildNamespace(virQEMUDriverConfigPtr cfg, if (qemuDomainSetupAllChardevs(cfg, vm, &data) < 0) goto cleanup; - if (qemuDomainSetupTPM(cfg, vm, &data) < 0) + if (qemuDomainSetupAllTPMs(cfg, vm, &data) < 0) goto cleanup; if (qemuDomainSetupAllGraphics(cfg, vm, &data) < 0) diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 07431343ed..4c26070022 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -268,10 +268,13 @@ qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def) return -1; } - if (def->tpm) { - if (qemuDomainIsPSeries(def)) - def->tpm->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO; - if (qemuDomainAssignSpaprVIOAddress(def, &def->tpm->info, + for (i = 0; i < def->ntpms; i++) { + virDomainTPMDefPtr tpm = def->tpms[i]; + + if (tpm->model != VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY && + qemuDomainIsPSeries(def)) + tpm->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO; + if (qemuDomainAssignSpaprVIOAddress(def, &tpm->info, VIO_ADDR_TPM) < 0) return -1; } diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c index 2ff3f68f5d..db18c82640 100644 --- a/src/qemu/qemu_extdevice.c +++ b/src/qemu/qemu_extdevice.c @@ -73,7 +73,7 @@ static int qemuExtDevicesInitPaths(virQEMUDriverPtr driver, virDomainDefPtr def) { - if (def->tpm) + if (def->ntpms > 0) return qemuExtTPMInitPaths(driver, def); return 0; @@ -132,7 +132,7 @@ qemuExtDevicesPrepareHost(virQEMUDriverPtr driver, virDomainDefPtr def = vm->def; size_t i; - if (def->tpm && + if (def->ntpms > 0 && qemuExtTPMPrepareHost(driver, def) < 0) return -1; @@ -155,7 +155,7 @@ qemuExtDevicesCleanupHost(virQEMUDriverPtr driver, if (qemuExtDevicesInitPaths(driver, def) < 0) return; - if (def->tpm) + if (def->ntpms > 0) qemuExtTPMCleanupHost(def); } @@ -181,7 +181,7 @@ qemuExtDevicesStart(virQEMUDriverPtr driver, } } - if (def->tpm && qemuExtTPMStart(driver, vm, incomingMigration) < 0) + if (def->ntpms > 0 && qemuExtTPMStart(driver, vm, incomingMigration) < 0) return -1; for (i = 0; i < def->nnets; i++) { @@ -223,7 +223,7 @@ qemuExtDevicesStop(virQEMUDriverPtr driver, qemuExtVhostUserGPUStop(driver, vm, video); } - if (def->tpm) + if (def->ntpms > 0) qemuExtTPMStop(driver, vm); for (i = 0; i < def->nnets; i++) { @@ -253,8 +253,10 @@ qemuExtDevicesHasDevice(virDomainDefPtr def) return true; } - if (def->tpm && def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) - return true; + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) + return true; + } for (i = 0; i < def->nfss; i++) { virDomainFSDefPtr fs = def->fss[i]; @@ -294,7 +296,7 @@ qemuExtDevicesSetupCgroup(virQEMUDriverPtr driver, return -1; } - if (def->tpm && + if (def->ntpms > 0 && qemuExtTPMSetupCgroup(driver, def, cgroup) < 0) return -1; diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c index afec0e5328..8adb0e42b8 100644 --- a/src/qemu/qemu_tpm.c +++ b/src/qemu/qemu_tpm.c @@ -679,10 +679,15 @@ qemuExtTPMInitPaths(virQEMUDriverPtr driver, virDomainDefPtr def) { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + size_t i; - if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) - return qemuTPMEmulatorInitPaths(def->tpm, cfg->swtpmStorageDir, + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; + + return qemuTPMEmulatorInitPaths(def->tpms[i], cfg->swtpmStorageDir, def->uuid); + } return 0; } @@ -694,13 +699,17 @@ qemuExtTPMPrepareHost(virQEMUDriverPtr driver, { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); g_autofree char *shortName = NULL; + size_t i; + + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; - if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { shortName = virDomainDefGetShortName(def); if (!shortName) return -1; - return qemuTPMEmulatorPrepareHost(def->tpm, cfg->swtpmLogDir, + return qemuTPMEmulatorPrepareHost(def->tpms[i], cfg->swtpmLogDir, def->name, cfg->swtpm_user, cfg->swtpm_group, cfg->swtpmStateDir, cfg->user, @@ -714,8 +723,14 @@ qemuExtTPMPrepareHost(virQEMUDriverPtr driver, void qemuExtTPMCleanupHost(virDomainDefPtr def) { - if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) - qemuTPMDeleteEmulatorStorage(def->tpm); + size_t i; + + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; + + qemuTPMDeleteEmulatorStorage(def->tpms[i]); + } } @@ -733,13 +748,13 @@ qemuExtTPMCleanupHost(virDomainDefPtr def) static int qemuExtTPMStartEmulator(virQEMUDriverPtr driver, virDomainObjPtr vm, + virDomainTPMDefPtr tpm, bool incomingMigration) { g_autoptr(virCommand) cmd = NULL; int exitstatus = 0; g_autofree char *errbuf = NULL; g_autoptr(virQEMUDriverConfig) cfg = NULL; - virDomainTPMDefPtr tpm = vm->def->tpm; g_autofree char *shortName = virDomainDefGetShortName(vm->def); int cmdret = 0, timeout, rc; pid_t pid; @@ -807,10 +822,15 @@ qemuExtTPMStart(virQEMUDriverPtr driver, virDomainObjPtr vm, bool incomingMigration) { - virDomainTPMDefPtr tpm = vm->def->tpm; + size_t i; + + for (i = 0; i < vm->def->ntpms; i++) { + if (vm->def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; - if (tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) - return qemuExtTPMStartEmulator(driver, vm, incomingMigration); + return qemuExtTPMStartEmulator(driver, vm, vm->def->tpms[i], + incomingMigration); + } return 0; } @@ -822,8 +842,12 @@ qemuExtTPMStop(virQEMUDriverPtr driver, { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); g_autofree char *shortName = NULL; + size_t i; + + for (i = 0; i < vm->def->ntpms; i++) { + if (vm->def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; - if (vm->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { shortName = virDomainDefGetShortName(vm->def); if (!shortName) return; @@ -845,8 +869,12 @@ qemuExtTPMSetupCgroup(virQEMUDriverPtr driver, g_autofree char *shortName = NULL; int rc; pid_t pid; + size_t i; + + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; - if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { shortName = virDomainDefGetShortName(def); if (!shortName) return -1; diff --git a/src/security/security_dac.c b/src/security/security_dac.c index bdc2d7edf3..79123f384c 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -1973,10 +1973,10 @@ virSecurityDACRestoreAllLabel(virSecurityManagerPtr mgr, &chardevData) < 0) rc = -1; - if (def->tpm) { + for (i = 0; i < def->ntpms; i++) { if (virSecurityDACRestoreTPMFileLabel(mgr, def, - def->tpm) < 0) + def->tpms[i]) < 0) rc = -1; } @@ -2152,10 +2152,10 @@ virSecurityDACSetAllLabel(virSecurityManagerPtr mgr, &chardevData) < 0) return -1; - if (def->tpm) { + for (i = 0; i < def->ntpms; i++) { if (virSecurityDACSetTPMFileLabel(mgr, def, - def->tpm) < 0) + def->tpms[i]) < 0) return -1; } diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 914a252df1..39928aef3e 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -2758,8 +2758,8 @@ virSecuritySELinuxRestoreAllLabel(virSecurityManagerPtr mgr, return -1; } - if (def->tpm) { - if (virSecuritySELinuxRestoreTPMFileLabelInt(mgr, def, def->tpm) < 0) + for (i = 0; i < def->ntpms; i++) { + if (virSecuritySELinuxRestoreTPMFileLabelInt(mgr, def, def->tpms[i]) < 0) rc = -1; } @@ -3166,8 +3166,8 @@ virSecuritySELinuxSetAllLabel(virSecurityManagerPtr mgr, return -1; } - if (def->tpm) { - if (virSecuritySELinuxSetTPMFileLabel(mgr, def, def->tpm) < 0) + for (i = 0; i < def->ntpms; i++) { + if (virSecuritySELinuxSetTPMFileLabel(mgr, def, def->tpms[i]) < 0) return -1; } @@ -3487,19 +3487,23 @@ virSecuritySELinuxSetTPMLabels(virSecurityManagerPtr mgr, virDomainDefPtr def) { int ret = 0; + size_t i; virSecurityLabelDefPtr seclabel; seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); if (seclabel == NULL) return 0; - if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; + ret = virSecuritySELinuxSetFileLabels( - mgr, def->tpm->data.emulator.storagepath, + mgr, def->tpms[i]->data.emulator.storagepath, seclabel); - if (ret == 0 && def->tpm->data.emulator.logfile) + if (ret == 0 && def->tpms[i]->data.emulator.logfile) ret = virSecuritySELinuxSetFileLabels( - mgr, def->tpm->data.emulator.logfile, + mgr, def->tpms[i]->data.emulator.logfile, seclabel); } @@ -3512,13 +3516,17 @@ virSecuritySELinuxRestoreTPMLabels(virSecurityManagerPtr mgr, virDomainDefPtr def) { int ret = 0; + size_t i; + + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; - if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { ret = virSecuritySELinuxRestoreFileLabels( - mgr, def->tpm->data.emulator.storagepath); - if (ret == 0 && def->tpm->data.emulator.logfile) + mgr, def->tpms[i]->data.emulator.storagepath); + if (ret == 0 && def->tpms[i]->data.emulator.logfile) ret = virSecuritySELinuxRestoreFileLabels( - mgr, def->tpm->data.emulator.logfile); + mgr, def->tpms[i]->data.emulator.logfile); } return ret; diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index 6e8f77e4dd..7abb6e70be 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -1206,14 +1206,17 @@ get_files(vahControl * ctl) } - if (ctl->def->tpm) { + if (ctl->def->ntpms > 0) { char *shortName = NULL; const char *tpmpath = NULL; - if (ctl->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { + for (i = 0; i < ctl->def->ntpms; i++) { + if (ctl->def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; + shortName = virDomainDefGetShortName(ctl->def); - switch (ctl->def->tpm->version) { + switch (ctl->def->tpms[i]->version) { case VIR_DOMAIN_TPM_VERSION_1_2: tpmpath = "tpm1.2"; break; diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index c40ce64cbf..5b27cf9ae4 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -437,12 +437,13 @@ testCompareXMLToArgvCreateArgs(virQEMUDriverPtr drv, vsockPriv->vhostfd = 6789; } - if (vm->def->tpm) { - if (vm->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { - VIR_FREE(vm->def->tpm->data.emulator.source.data.file.path); - vm->def->tpm->data.emulator.source.data.file.path = g_strdup("/dev/test"); - vm->def->tpm->data.emulator.source.type = VIR_DOMAIN_CHR_TYPE_FILE; - } + for (i = 0; i < vm->def->ntpms; i++) { + if (vm->def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; + + VIR_FREE(vm->def->tpms[i]->data.emulator.source.data.file.path); + vm->def->tpms[i]->data.emulator.source.data.file.path = g_strdup("/dev/test"); + vm->def->tpms[i]->data.emulator.source.type = VIR_DOMAIN_CHR_TYPE_FILE; } for (i = 0; i < vm->def->nvideos; i++) { -- 2.26.2

On 5/21/20 9:07 AM, Daniel Henrique Barboza wrote:
A TPM Proxy device can coexist with a regular TPM, but the current domain definition supports only a single TPM device in the 'tpm' pointer. This patch replaces this existing pointer in the domain definition to an array of TPM devices.
All files that references the old pointer were adapted to handle the new array instead. virDomainDefParseXML() TPM related code was adapted to handle the parsing of an extra TPM device. TPM validations after this new scenario will be updated in the next patch.
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- src/conf/domain_audit.c | 4 +-- src/conf/domain_conf.c | 50 +++++++++++++++++++------------ src/conf/domain_conf.h | 6 +++- src/qemu/qemu_alias.c | 4 +-- src/qemu/qemu_cgroup.c | 10 ++++--- src/qemu/qemu_command.c | 34 ++++++++++++++------- src/qemu/qemu_domain.c | 31 +++++++++++++------- src/qemu/qemu_domain_address.c | 11 ++++--- src/qemu/qemu_extdevice.c | 18 +++++++----- src/qemu/qemu_tpm.c | 52 +++++++++++++++++++++++++-------- src/security/security_dac.c | 8 ++--- src/security/security_selinux.c | 32 ++++++++++++-------- src/security/virt-aa-helper.c | 9 ++++-- tests/qemuxml2argvtest.c | 13 +++++---- 14 files changed, 186 insertions(+), 96 deletions(-)
diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c index 1b0abb21a0..8bc6633af4 100644 --- a/src/conf/domain_audit.c +++ b/src/conf/domain_audit.c @@ -821,8 +821,8 @@ virDomainAuditStart(virDomainObjPtr vm, const char *reason, bool success) for (i = 0; i < vm->def->nrngs; i++) virDomainAuditRNG(vm, NULL, vm->def->rngs[i], "start", true);
- if (vm->def->tpm) - virDomainAuditTPM(vm, vm->def->tpm, "start", true); + for (i = 0; i < vm->def->ntpms; i++) + virDomainAuditTPM(vm, vm->def->tpms[i], "start", true);
for (i = 0; i < vm->def->nshmems; i++) virDomainAuditShmem(vm, vm->def->shmems[i], "start", true); diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index c201fc901d..be90762af4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1165,6 +1165,7 @@ VIR_ENUM_IMPL(virDomainTPMModel, "tpm-tis", "tpm-crb", "tpm-spapr", + "spapr-tpm-proxy", );
VIR_ENUM_IMPL(virDomainTPMBackend, @@ -3479,7 +3480,9 @@ void virDomainDefFree(virDomainDefPtr def) virDomainMemoryDefFree(def->mems[i]); VIR_FREE(def->mems);
- virDomainTPMDefFree(def->tpm); + for (i = 0; i < def->ntpms; i++) + virDomainTPMDefFree(def->tpms[i]); + VIR_FREE(def->tpms);
for (i = 0; i < def->npanics; i++) virDomainPanicDefFree(def->panics[i]); @@ -4312,10 +4315,10 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def, if ((rc = cb(def, &device, &def->shmems[i]->info, opaque)) != 0) return rc; } - if (def->tpm) { - device.type = VIR_DOMAIN_DEVICE_TPM; - device.data.tpm = def->tpm; - if ((rc = cb(def, &device, &def->tpm->info, opaque)) != 0) + device.type = VIR_DOMAIN_DEVICE_TPM; + for (i = 0; i < def->ntpms; i++) { + device.data.tpm = def->tpms[i]; + if ((rc = cb(def, &device, &def->tpms[i]->info, opaque)) != 0) return rc; } device.type = VIR_DOMAIN_DEVICE_PANIC; @@ -21964,15 +21967,23 @@ virDomainDefParseXML(xmlDocPtr xml, if ((n = virXPathNodeSet("./devices/tpm", ctxt, &nodes)) < 0) goto error;
- if (n > 1) { + if (n > 2) { virReportError(VIR_ERR_XML_ERROR, "%s", - _("only a single TPM device is supported")); + _("a maximum of two TPM devices is supported, one of " + "them being a TPM Proxy device")); goto error; }
- if (n > 0) { - if (!(def->tpm = virDomainTPMDefParseXML(xmlopt, nodes[0], ctxt, flags))) + if (n && VIR_ALLOC_N(def->tpms, n) < 0) + goto error; + + for (i = 0; i < n; i++) { + virDomainTPMDefPtr tpm = virDomainTPMDefParseXML(xmlopt, nodes[i], + ctxt, flags); + if (!tpm) goto error; + + def->tpms[def->ntpms++] = tpm; } VIR_FREE(nodes);
@@ -24334,16 +24345,19 @@ virDomainDefCheckABIStabilityFlags(virDomainDefPtr src, goto error; }
- if (src->tpm && dst->tpm) { - if (!virDomainTPMDefCheckABIStability(src->tpm, dst->tpm)) - goto error; - } else if (src->tpm || dst->tpm) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Either both target and source domains or none of " - "them must have TPM device present")); + if (src->ntpms != dst->ntpms) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target domain TPM device count %zu " + "does not match source %zu"), + dst->ntpms, src->ntpms); goto error; }
+ for (i = 0; i < src->ntpms; i++) { + if (!virDomainTPMDefCheckABIStability(src->tpms[i], dst->tpms[i])) + goto error; + } + if (src->nmems != dst->nmems) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target domain memory device count %zu " @@ -29784,8 +29798,8 @@ virDomainDefFormatInternalSetRootName(virDomainDefPtr def, goto error; }
- if (def->tpm) { - if (virDomainTPMDefFormat(buf, def->tpm, flags) < 0) + for (n = 0; n < def->ntpms; n++) { + if (virDomainTPMDefFormat(buf, def->tpms[n], flags) < 0) goto error; }
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index ddc75d8de2..32ae272cac 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1293,6 +1293,7 @@ typedef enum { VIR_DOMAIN_TPM_MODEL_TIS, VIR_DOMAIN_TPM_MODEL_CRB, VIR_DOMAIN_TPM_MODEL_SPAPR, + VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY,
VIR_DOMAIN_TPM_MODEL_LAST } virDomainTPMModel; @@ -2623,11 +2624,14 @@ struct _virDomainDef { size_t npanics; virDomainPanicDefPtr *panics;
+ /* At maximum 2 TPMs on the domain, if a TPM Proxy is present. */ + size_t ntpms; + virDomainTPMDefPtr *tpms; + /* Only 1 */ virDomainWatchdogDefPtr watchdog; virDomainMemballoonDefPtr memballoon; virDomainNVRAMDefPtr nvram; - virDomainTPMDefPtr tpm; virCPUDefPtr cpu; virSysinfoDefPtr sysinfo; virDomainRedirFilterDefPtr redirfilter; diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index d6527cb046..85fdb85940 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -669,8 +669,8 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps) if (qemuAssignDeviceRNGAlias(def, def->rngs[i]) < 0) return -1; } - if (def->tpm) { - if (qemuAssignDeviceTPMAlias(def->tpm, 0) < 0) + for (i = 0; i < def->ntpms; i++) { + if (qemuAssignDeviceTPMAlias(def->tpms[i], 0) < 0) return -1; } for (i = 0; i < def->nmems; i++) { diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index d92202f847..eb0f03d4aa 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -332,10 +332,10 @@ qemuSetupChardevCgroupCB(virDomainDefPtr def G_GNUC_UNUSED,
static int -qemuSetupTPMCgroup(virDomainObjPtr vm) +qemuSetupTPMCgroup(virDomainObjPtr vm, + virDomainTPMDefPtr dev) { int ret = 0; - virDomainTPMDefPtr dev = vm->def->tpm;
switch (dev->type) { case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: @@ -805,8 +805,10 @@ qemuSetupDevicesCgroup(virDomainObjPtr vm) vm) < 0) return -1;
- if (vm->def->tpm && qemuSetupTPMCgroup(vm) < 0) - return -1; + for (i = 0; i < vm->def->ntpms; i++) { + if (qemuSetupTPMCgroup(vm, vm->def->tpms[i]) < 0) + return -1; + }
for (i = 0; i < vm->def->nhostdevs; i++) { /* This may allow /dev/vfio/vfio multiple times, but that diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 419eca5675..59caff08f2 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8890,10 +8890,10 @@ qemuBuildDomainLoaderCommandLine(virCommandPtr cmd,
static char * qemuBuildTPMDevStr(const virDomainDef *def, + virDomainTPMDefPtr tpm, virQEMUCapsPtr qemuCaps) { g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; - virDomainTPMDef *tpm = def->tpm; const char *model = virDomainTPMModelTypeToString(tpm->model);
virBufferAsprintf(&buf, "%s,tpmdev=tpm-%s,id=%s", @@ -8932,13 +8932,12 @@ qemuBuildTPMOpenBackendFDs(const char *tpmdev,
static char * -qemuBuildTPMBackendStr(const virDomainDef *def, - virCommandPtr cmd, +qemuBuildTPMBackendStr(virCommandPtr cmd, + virDomainTPMDefPtr tpm, int *tpmfd, int *cancelfd, char **chardev) { - const virDomainTPMDef *tpm = def->tpm; g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; g_autofree char *cancel_path = NULL; g_autofree char *devset = NULL; @@ -8992,6 +8991,7 @@ qemuBuildTPMBackendStr(const virDomainDef *def, static int qemuBuildTPMCommandLine(virCommandPtr cmd, const virDomainDef *def, + virDomainTPMDefPtr tpm, virQEMUCapsPtr qemuCaps) { char *optstr; @@ -9000,10 +9000,7 @@ qemuBuildTPMCommandLine(virCommandPtr cmd, int cancelfd = -1; char *fdset;
- if (!def->tpm) - return 0; - - if (!(optstr = qemuBuildTPMBackendStr(def, cmd, + if (!(optstr = qemuBuildTPMBackendStr(cmd, tpm, &tpmfd, &cancelfd, &chardev))) return -1; @@ -9032,7 +9029,7 @@ qemuBuildTPMCommandLine(virCommandPtr cmd, VIR_FREE(fdset); }
- if (!(optstr = qemuBuildTPMDevStr(def, qemuCaps))) + if (!(optstr = qemuBuildTPMDevStr(def, tpm, qemuCaps))) return -1;
virCommandAddArgList(cmd, "-device", optstr, NULL); @@ -9041,6 +9038,23 @@ qemuBuildTPMCommandLine(virCommandPtr cmd, return 0; }
+ +static int +qemuBuildTPMsCommandLine(virCommandPtr cmd, + const virDomainDef *def, + virQEMUCapsPtr qemuCaps) +{ + size_t i; + + for (i = 0; i < def->ntpms; i++) { + if (qemuBuildTPMCommandLine(cmd, def, def->tpms[i], qemuCaps) < 0) + return -1; + } + + return 0; +} + + static int qemuBuildSEVCommandLine(virDomainObjPtr vm, virCommandPtr cmd, virDomainSEVDefPtr sev) @@ -9720,7 +9734,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, chardevStdioLogd) < 0) return NULL;
- if (qemuBuildTPMCommandLine(cmd, def, qemuCaps) < 0) + if (qemuBuildTPMsCommandLine(cmd, def, qemuCaps) < 0) return NULL;
if (qemuBuildInputCommandLine(cmd, def, qemuCaps) < 0) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index d5e3d1a3cc..3173fc3a3b 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -11585,16 +11585,9 @@ qemuDomainSetupAllChardevs(virQEMUDriverConfigPtr cfg G_GNUC_UNUSED,
static int qemuDomainSetupTPM(virQEMUDriverConfigPtr cfg G_GNUC_UNUSED, - virDomainObjPtr vm, + virDomainTPMDefPtr dev, const struct qemuDomainCreateDeviceData *data) { - virDomainTPMDefPtr dev = vm->def->tpm; - - if (!dev) - return 0; - - VIR_DEBUG("Setting up TPM"); - switch (dev->type) { case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: if (qemuDomainCreateDevice(dev->data.passthrough.source.data.file.path, @@ -11608,7 +11601,25 @@ qemuDomainSetupTPM(virQEMUDriverConfigPtr cfg G_GNUC_UNUSED, break; }
- VIR_DEBUG("Setup TPM"); + return 0; +} + + +static int +qemuDomainSetupAllTPMs(virQEMUDriverConfigPtr cfg G_GNUC_UNUSED, + virDomainObjPtr vm, + const struct qemuDomainCreateDeviceData *data) +{ + size_t i; + + VIR_DEBUG("Setting up TPMs"); + + for (i = 0; i < vm->def->ntpms; i++) { + if (qemuDomainSetupTPM(cfg, vm->def->tpms[i], data) < 0) + return -1; + } + + VIR_DEBUG("Setup all TPMs"); return 0; }
@@ -11834,7 +11845,7 @@ qemuDomainBuildNamespace(virQEMUDriverConfigPtr cfg, if (qemuDomainSetupAllChardevs(cfg, vm, &data) < 0) goto cleanup;
- if (qemuDomainSetupTPM(cfg, vm, &data) < 0) + if (qemuDomainSetupAllTPMs(cfg, vm, &data) < 0) goto cleanup;
if (qemuDomainSetupAllGraphics(cfg, vm, &data) < 0) diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 07431343ed..4c26070022 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -268,10 +268,13 @@ qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def) return -1; }
- if (def->tpm) { - if (qemuDomainIsPSeries(def)) - def->tpm->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO; - if (qemuDomainAssignSpaprVIOAddress(def, &def->tpm->info, + for (i = 0; i < def->ntpms; i++) { + virDomainTPMDefPtr tpm = def->tpms[i]; + + if (tpm->model != VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY && + qemuDomainIsPSeries(def)) + tpm->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO; + if (qemuDomainAssignSpaprVIOAddress(def, &tpm->info, VIO_ADDR_TPM) < 0)
It looks like tike proxy will also get a VIOAddress. Is that necessary?
return -1; } diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c index 2ff3f68f5d..db18c82640 100644 --- a/src/qemu/qemu_extdevice.c +++ b/src/qemu/qemu_extdevice.c @@ -73,7 +73,7 @@ static int qemuExtDevicesInitPaths(virQEMUDriverPtr driver, virDomainDefPtr def) { - if (def->tpm) + if (def->ntpms > 0) return qemuExtTPMInitPaths(driver, def);
return 0; @@ -132,7 +132,7 @@ qemuExtDevicesPrepareHost(virQEMUDriverPtr driver, virDomainDefPtr def = vm->def; size_t i;
- if (def->tpm && + if (def->ntpms > 0 && qemuExtTPMPrepareHost(driver, def) < 0) return -1;
@@ -155,7 +155,7 @@ qemuExtDevicesCleanupHost(virQEMUDriverPtr driver, if (qemuExtDevicesInitPaths(driver, def) < 0) return;
- if (def->tpm) + if (def->ntpms > 0) qemuExtTPMCleanupHost(def); }
@@ -181,7 +181,7 @@ qemuExtDevicesStart(virQEMUDriverPtr driver, } }
- if (def->tpm && qemuExtTPMStart(driver, vm, incomingMigration) < 0) + if (def->ntpms > 0 && qemuExtTPMStart(driver, vm, incomingMigration) < 0) return -1;
for (i = 0; i < def->nnets; i++) { @@ -223,7 +223,7 @@ qemuExtDevicesStop(virQEMUDriverPtr driver, qemuExtVhostUserGPUStop(driver, vm, video); }
- if (def->tpm) + if (def->ntpms > 0) qemuExtTPMStop(driver, vm);
for (i = 0; i < def->nnets; i++) { @@ -253,8 +253,10 @@ qemuExtDevicesHasDevice(virDomainDefPtr def) return true; }
- if (def->tpm && def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) - return true; + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) + return true; + }
for (i = 0; i < def->nfss; i++) { virDomainFSDefPtr fs = def->fss[i]; @@ -294,7 +296,7 @@ qemuExtDevicesSetupCgroup(virQEMUDriverPtr driver, return -1; }
- if (def->tpm && + if (def->ntpms > 0 && qemuExtTPMSetupCgroup(driver, def, cgroup) < 0) return -1;
diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c index afec0e5328..8adb0e42b8 100644 --- a/src/qemu/qemu_tpm.c +++ b/src/qemu/qemu_tpm.c @@ -679,10 +679,15 @@ qemuExtTPMInitPaths(virQEMUDriverPtr driver, virDomainDefPtr def) { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + size_t i;
- if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) - return qemuTPMEmulatorInitPaths(def->tpm, cfg->swtpmStorageDir, + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; + + return qemuTPMEmulatorInitPaths(def->tpms[i], cfg->swtpmStorageDir, def->uuid); + }
return 0; } @@ -694,13 +699,17 @@ qemuExtTPMPrepareHost(virQEMUDriverPtr driver, { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); g_autofree char *shortName = NULL; + size_t i; + + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue;
- if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { shortName = virDomainDefGetShortName(def); if (!shortName) return -1;
- return qemuTPMEmulatorPrepareHost(def->tpm, cfg->swtpmLogDir, + return qemuTPMEmulatorPrepareHost(def->tpms[i], cfg->swtpmLogDir, def->name, cfg->swtpm_user, cfg->swtpm_group, cfg->swtpmStateDir, cfg->user, @@ -714,8 +723,14 @@ qemuExtTPMPrepareHost(virQEMUDriverPtr driver, void qemuExtTPMCleanupHost(virDomainDefPtr def) { - if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) - qemuTPMDeleteEmulatorStorage(def->tpm); + size_t i; + + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; + + qemuTPMDeleteEmulatorStorage(def->tpms[i]); + } }
@@ -733,13 +748,13 @@ qemuExtTPMCleanupHost(virDomainDefPtr def) static int qemuExtTPMStartEmulator(virQEMUDriverPtr driver, virDomainObjPtr vm, + virDomainTPMDefPtr tpm, bool incomingMigration) { g_autoptr(virCommand) cmd = NULL; int exitstatus = 0; g_autofree char *errbuf = NULL; g_autoptr(virQEMUDriverConfig) cfg = NULL; - virDomainTPMDefPtr tpm = vm->def->tpm; g_autofree char *shortName = virDomainDefGetShortName(vm->def); int cmdret = 0, timeout, rc; pid_t pid; @@ -807,10 +822,15 @@ qemuExtTPMStart(virQEMUDriverPtr driver, virDomainObjPtr vm, bool incomingMigration) { - virDomainTPMDefPtr tpm = vm->def->tpm; + size_t i; + + for (i = 0; i < vm->def->ntpms; i++) { + if (vm->def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue;
- if (tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) - return qemuExtTPMStartEmulator(driver, vm, incomingMigration); + return qemuExtTPMStartEmulator(driver, vm, vm->def->tpms[i], + incomingMigration); + }
return 0; } @@ -822,8 +842,12 @@ qemuExtTPMStop(virQEMUDriverPtr driver, { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); g_autofree char *shortName = NULL; + size_t i; + + for (i = 0; i < vm->def->ntpms; i++) { + if (vm->def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue;
- if (vm->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { shortName = virDomainDefGetShortName(vm->def); if (!shortName) return; @@ -845,8 +869,12 @@ qemuExtTPMSetupCgroup(virQEMUDriverPtr driver, g_autofree char *shortName = NULL; int rc; pid_t pid; + size_t i; + + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue;
- if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { shortName = virDomainDefGetShortName(def); if (!shortName) return -1; diff --git a/src/security/security_dac.c b/src/security/security_dac.c index bdc2d7edf3..79123f384c 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -1973,10 +1973,10 @@ virSecurityDACRestoreAllLabel(virSecurityManagerPtr mgr, &chardevData) < 0) rc = -1;
- if (def->tpm) { + for (i = 0; i < def->ntpms; i++) { if (virSecurityDACRestoreTPMFileLabel(mgr, def, - def->tpm) < 0) + def->tpms[i]) < 0) rc = -1; }
@@ -2152,10 +2152,10 @@ virSecurityDACSetAllLabel(virSecurityManagerPtr mgr, &chardevData) < 0) return -1;
- if (def->tpm) { + for (i = 0; i < def->ntpms; i++) { if (virSecurityDACSetTPMFileLabel(mgr, def, - def->tpm) < 0) + def->tpms[i]) < 0) return -1; }
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 914a252df1..39928aef3e 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -2758,8 +2758,8 @@ virSecuritySELinuxRestoreAllLabel(virSecurityManagerPtr mgr, return -1; }
- if (def->tpm) { - if (virSecuritySELinuxRestoreTPMFileLabelInt(mgr, def, def->tpm) < 0) + for (i = 0; i < def->ntpms; i++) { + if (virSecuritySELinuxRestoreTPMFileLabelInt(mgr, def, def->tpms[i]) < 0) rc = -1; }
@@ -3166,8 +3166,8 @@ virSecuritySELinuxSetAllLabel(virSecurityManagerPtr mgr, return -1; }
- if (def->tpm) { - if (virSecuritySELinuxSetTPMFileLabel(mgr, def, def->tpm) < 0) + for (i = 0; i < def->ntpms; i++) { + if (virSecuritySELinuxSetTPMFileLabel(mgr, def, def->tpms[i]) < 0) return -1; }
@@ -3487,19 +3487,23 @@ virSecuritySELinuxSetTPMLabels(virSecurityManagerPtr mgr, virDomainDefPtr def) { int ret = 0; + size_t i; virSecurityLabelDefPtr seclabel;
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); if (seclabel == NULL) return 0;
- if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; + ret = virSecuritySELinuxSetFileLabels( - mgr, def->tpm->data.emulator.storagepath, + mgr, def->tpms[i]->data.emulator.storagepath, seclabel); - if (ret == 0 && def->tpm->data.emulator.logfile) + if (ret == 0 && def->tpms[i]->data.emulator.logfile) ret = virSecuritySELinuxSetFileLabels( - mgr, def->tpm->data.emulator.logfile, + mgr, def->tpms[i]->data.emulator.logfile, seclabel); }
@@ -3512,13 +3516,17 @@ virSecuritySELinuxRestoreTPMLabels(virSecurityManagerPtr mgr, virDomainDefPtr def) { int ret = 0; + size_t i; + + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue;
- if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { ret = virSecuritySELinuxRestoreFileLabels( - mgr, def->tpm->data.emulator.storagepath); - if (ret == 0 && def->tpm->data.emulator.logfile) + mgr, def->tpms[i]->data.emulator.storagepath); + if (ret == 0 && def->tpms[i]->data.emulator.logfile) ret = virSecuritySELinuxRestoreFileLabels( - mgr, def->tpm->data.emulator.logfile); + mgr, def->tpms[i]->data.emulator.logfile); }
return ret; diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index 6e8f77e4dd..7abb6e70be 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -1206,14 +1206,17 @@ get_files(vahControl * ctl) }
- if (ctl->def->tpm) { + if (ctl->def->ntpms > 0) { char *shortName = NULL; const char *tpmpath = NULL;
- if (ctl->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { + for (i = 0; i < ctl->def->ntpms; i++) { + if (ctl->def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; + shortName = virDomainDefGetShortName(ctl->def);
- switch (ctl->def->tpm->version) { + switch (ctl->def->tpms[i]->version) { case VIR_DOMAIN_TPM_VERSION_1_2: tpmpath = "tpm1.2"; break; diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index c40ce64cbf..5b27cf9ae4 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -437,12 +437,13 @@ testCompareXMLToArgvCreateArgs(virQEMUDriverPtr drv, vsockPriv->vhostfd = 6789; }
- if (vm->def->tpm) { - if (vm->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { - VIR_FREE(vm->def->tpm->data.emulator.source.data.file.path); - vm->def->tpm->data.emulator.source.data.file.path = g_strdup("/dev/test"); - vm->def->tpm->data.emulator.source.type = VIR_DOMAIN_CHR_TYPE_FILE; - } + for (i = 0; i < vm->def->ntpms; i++) { + if (vm->def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; + + VIR_FREE(vm->def->tpms[i]->data.emulator.source.data.file.path); + vm->def->tpms[i]->data.emulator.source.data.file.path = g_strdup("/dev/test"); + vm->def->tpms[i]->data.emulator.source.type = VIR_DOMAIN_CHR_TYPE_FILE; }
for (i = 0; i < vm->def->nvideos; i++) {
Maybe you need to address the comment above: Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>

On 5/27/20 3:42 PM, Stefan Berger wrote:
On 5/21/20 9:07 AM, Daniel Henrique Barboza wrote:
A TPM Proxy device can coexist with a regular TPM, but the
[...]
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 07431343ed..4c26070022 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -268,10 +268,13 @@ qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def) return -1; } - if (def->tpm) { - if (qemuDomainIsPSeries(def)) - def->tpm->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO; - if (qemuDomainAssignSpaprVIOAddress(def, &def->tpm->info, + for (i = 0; i < def->ntpms; i++) { + virDomainTPMDefPtr tpm = def->tpms[i]; + + if (tpm->model != VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY && + qemuDomainIsPSeries(def)) + tpm->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO; + if (qemuDomainAssignSpaprVIOAddress(def, &tpm->info, VIO_ADDR_TPM) < 0)
It looks like tike proxy will also get a VIOAddress. Is that necessary?
It won't. qemuDomainAssignSpaprVIOAddress() does a check for info.type equals SPAPRVIO, being a NO-OP in case it doesn't: static int qemuDomainAssignSpaprVIOAddress(virDomainDefPtr def, virDomainDeviceInfoPtr info, unsigned long long default_reg) { bool user_reg; int ret; if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO) return 0; (...) This chunk of code will prevent the type to be SPAPRVIO for the proxy:
+ if (tpm->model != VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY && + qemuDomainIsPSeries(def)) + tpm->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
At first I wasn't bothering preventing a SPAPRVIO address for the proxy, but qemu_command.c is adding additional stuff in this case: } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO) { if (info->addr.spaprvio.has_reg) virBufferAsprintf(buf, ",reg=0x%08llx", info->addr.spaprvio.reg); And this extra argument broke the TPM Proxy tests I've made before. Thanks, DHB
return -1; } diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c index 2ff3f68f5d..db18c82640 100644 --- a/src/qemu/qemu_extdevice.c +++ b/src/qemu/qemu_extdevice.c @@ -73,7 +73,7 @@ static int qemuExtDevicesInitPaths(virQEMUDriverPtr driver, virDomainDefPtr def) { - if (def->tpm) + if (def->ntpms > 0) return qemuExtTPMInitPaths(driver, def); return 0; @@ -132,7 +132,7 @@ qemuExtDevicesPrepareHost(virQEMUDriverPtr driver, virDomainDefPtr def = vm->def; size_t i; - if (def->tpm && + if (def->ntpms > 0 && qemuExtTPMPrepareHost(driver, def) < 0) return -1; @@ -155,7 +155,7 @@ qemuExtDevicesCleanupHost(virQEMUDriverPtr driver, if (qemuExtDevicesInitPaths(driver, def) < 0) return; - if (def->tpm) + if (def->ntpms > 0) qemuExtTPMCleanupHost(def); } @@ -181,7 +181,7 @@ qemuExtDevicesStart(virQEMUDriverPtr driver, } } - if (def->tpm && qemuExtTPMStart(driver, vm, incomingMigration) < 0) + if (def->ntpms > 0 && qemuExtTPMStart(driver, vm, incomingMigration) < 0) return -1; for (i = 0; i < def->nnets; i++) { @@ -223,7 +223,7 @@ qemuExtDevicesStop(virQEMUDriverPtr driver, qemuExtVhostUserGPUStop(driver, vm, video); } - if (def->tpm) + if (def->ntpms > 0) qemuExtTPMStop(driver, vm); for (i = 0; i < def->nnets; i++) { @@ -253,8 +253,10 @@ qemuExtDevicesHasDevice(virDomainDefPtr def) return true; } - if (def->tpm && def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) - return true; + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) + return true; + } for (i = 0; i < def->nfss; i++) { virDomainFSDefPtr fs = def->fss[i]; @@ -294,7 +296,7 @@ qemuExtDevicesSetupCgroup(virQEMUDriverPtr driver, return -1; } - if (def->tpm && + if (def->ntpms > 0 && qemuExtTPMSetupCgroup(driver, def, cgroup) < 0) return -1; diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c index afec0e5328..8adb0e42b8 100644 --- a/src/qemu/qemu_tpm.c +++ b/src/qemu/qemu_tpm.c @@ -679,10 +679,15 @@ qemuExtTPMInitPaths(virQEMUDriverPtr driver, virDomainDefPtr def) { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + size_t i; - if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) - return qemuTPMEmulatorInitPaths(def->tpm, cfg->swtpmStorageDir, + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; + + return qemuTPMEmulatorInitPaths(def->tpms[i], cfg->swtpmStorageDir, def->uuid); + } return 0; } @@ -694,13 +699,17 @@ qemuExtTPMPrepareHost(virQEMUDriverPtr driver, { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); g_autofree char *shortName = NULL; + size_t i; + + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; - if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { shortName = virDomainDefGetShortName(def); if (!shortName) return -1; - return qemuTPMEmulatorPrepareHost(def->tpm, cfg->swtpmLogDir, + return qemuTPMEmulatorPrepareHost(def->tpms[i], cfg->swtpmLogDir, def->name, cfg->swtpm_user, cfg->swtpm_group, cfg->swtpmStateDir, cfg->user, @@ -714,8 +723,14 @@ qemuExtTPMPrepareHost(virQEMUDriverPtr driver, void qemuExtTPMCleanupHost(virDomainDefPtr def) { - if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) - qemuTPMDeleteEmulatorStorage(def->tpm); + size_t i; + + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; + + qemuTPMDeleteEmulatorStorage(def->tpms[i]); + } } @@ -733,13 +748,13 @@ qemuExtTPMCleanupHost(virDomainDefPtr def) static int qemuExtTPMStartEmulator(virQEMUDriverPtr driver, virDomainObjPtr vm, + virDomainTPMDefPtr tpm, bool incomingMigration) { g_autoptr(virCommand) cmd = NULL; int exitstatus = 0; g_autofree char *errbuf = NULL; g_autoptr(virQEMUDriverConfig) cfg = NULL; - virDomainTPMDefPtr tpm = vm->def->tpm; g_autofree char *shortName = virDomainDefGetShortName(vm->def); int cmdret = 0, timeout, rc; pid_t pid; @@ -807,10 +822,15 @@ qemuExtTPMStart(virQEMUDriverPtr driver, virDomainObjPtr vm, bool incomingMigration) { - virDomainTPMDefPtr tpm = vm->def->tpm; + size_t i; + + for (i = 0; i < vm->def->ntpms; i++) { + if (vm->def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; - if (tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) - return qemuExtTPMStartEmulator(driver, vm, incomingMigration); + return qemuExtTPMStartEmulator(driver, vm, vm->def->tpms[i], + incomingMigration); + } return 0; } @@ -822,8 +842,12 @@ qemuExtTPMStop(virQEMUDriverPtr driver, { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); g_autofree char *shortName = NULL; + size_t i; + + for (i = 0; i < vm->def->ntpms; i++) { + if (vm->def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; - if (vm->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { shortName = virDomainDefGetShortName(vm->def); if (!shortName) return; @@ -845,8 +869,12 @@ qemuExtTPMSetupCgroup(virQEMUDriverPtr driver, g_autofree char *shortName = NULL; int rc; pid_t pid; + size_t i; + + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; - if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { shortName = virDomainDefGetShortName(def); if (!shortName) return -1; diff --git a/src/security/security_dac.c b/src/security/security_dac.c index bdc2d7edf3..79123f384c 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -1973,10 +1973,10 @@ virSecurityDACRestoreAllLabel(virSecurityManagerPtr mgr, &chardevData) < 0) rc = -1; - if (def->tpm) { + for (i = 0; i < def->ntpms; i++) { if (virSecurityDACRestoreTPMFileLabel(mgr, def, - def->tpm) < 0) + def->tpms[i]) < 0) rc = -1; } @@ -2152,10 +2152,10 @@ virSecurityDACSetAllLabel(virSecurityManagerPtr mgr, &chardevData) < 0) return -1; - if (def->tpm) { + for (i = 0; i < def->ntpms; i++) { if (virSecurityDACSetTPMFileLabel(mgr, def, - def->tpm) < 0) + def->tpms[i]) < 0) return -1; } diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 914a252df1..39928aef3e 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -2758,8 +2758,8 @@ virSecuritySELinuxRestoreAllLabel(virSecurityManagerPtr mgr, return -1; } - if (def->tpm) { - if (virSecuritySELinuxRestoreTPMFileLabelInt(mgr, def, def->tpm) < 0) + for (i = 0; i < def->ntpms; i++) { + if (virSecuritySELinuxRestoreTPMFileLabelInt(mgr, def, def->tpms[i]) < 0) rc = -1; } @@ -3166,8 +3166,8 @@ virSecuritySELinuxSetAllLabel(virSecurityManagerPtr mgr, return -1; } - if (def->tpm) { - if (virSecuritySELinuxSetTPMFileLabel(mgr, def, def->tpm) < 0) + for (i = 0; i < def->ntpms; i++) { + if (virSecuritySELinuxSetTPMFileLabel(mgr, def, def->tpms[i]) < 0) return -1; } @@ -3487,19 +3487,23 @@ virSecuritySELinuxSetTPMLabels(virSecurityManagerPtr mgr, virDomainDefPtr def) { int ret = 0; + size_t i; virSecurityLabelDefPtr seclabel; seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); if (seclabel == NULL) return 0; - if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; + ret = virSecuritySELinuxSetFileLabels( - mgr, def->tpm->data.emulator.storagepath, + mgr, def->tpms[i]->data.emulator.storagepath, seclabel); - if (ret == 0 && def->tpm->data.emulator.logfile) + if (ret == 0 && def->tpms[i]->data.emulator.logfile) ret = virSecuritySELinuxSetFileLabels( - mgr, def->tpm->data.emulator.logfile, + mgr, def->tpms[i]->data.emulator.logfile, seclabel); } @@ -3512,13 +3516,17 @@ virSecuritySELinuxRestoreTPMLabels(virSecurityManagerPtr mgr, virDomainDefPtr def) { int ret = 0; + size_t i; + + for (i = 0; i < def->ntpms; i++) { + if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; - if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { ret = virSecuritySELinuxRestoreFileLabels( - mgr, def->tpm->data.emulator.storagepath); - if (ret == 0 && def->tpm->data.emulator.logfile) + mgr, def->tpms[i]->data.emulator.storagepath); + if (ret == 0 && def->tpms[i]->data.emulator.logfile) ret = virSecuritySELinuxRestoreFileLabels( - mgr, def->tpm->data.emulator.logfile); + mgr, def->tpms[i]->data.emulator.logfile); } return ret; diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index 6e8f77e4dd..7abb6e70be 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -1206,14 +1206,17 @@ get_files(vahControl * ctl) } - if (ctl->def->tpm) { + if (ctl->def->ntpms > 0) { char *shortName = NULL; const char *tpmpath = NULL; - if (ctl->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { + for (i = 0; i < ctl->def->ntpms; i++) { + if (ctl->def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; + shortName = virDomainDefGetShortName(ctl->def); - switch (ctl->def->tpm->version) { + switch (ctl->def->tpms[i]->version) { case VIR_DOMAIN_TPM_VERSION_1_2: tpmpath = "tpm1.2"; break; diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index c40ce64cbf..5b27cf9ae4 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -437,12 +437,13 @@ testCompareXMLToArgvCreateArgs(virQEMUDriverPtr drv, vsockPriv->vhostfd = 6789; } - if (vm->def->tpm) { - if (vm->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) { - VIR_FREE(vm->def->tpm->data.emulator.source.data.file.path); - vm->def->tpm->data.emulator.source.data.file.path = g_strdup("/dev/test"); - vm->def->tpm->data.emulator.source.type = VIR_DOMAIN_CHR_TYPE_FILE; - } + for (i = 0; i < vm->def->ntpms; i++) { + if (vm->def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR) + continue; + + VIR_FREE(vm->def->tpms[i]->data.emulator.source.data.file.path); + vm->def->tpms[i]->data.emulator.source.data.file.path = g_strdup("/dev/test"); + vm->def->tpms[i]->data.emulator.source.type = VIR_DOMAIN_CHR_TYPE_FILE; } for (i = 0; i < vm->def->nvideos; i++) {
Maybe you need to address the comment above:
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>

Previous patch handled the conversion of def->tpm to the array def->tpms and the XML parsing logic. This patch handles the validations needed to ensure the intended behavior. The existing qemuValidateDomainDeviceDefTPM() function was updated to guarantee that the VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY model is exclusive to PPC64 guests and to the VIR_DOMAIN_TPM_TYPE_PASSTHROUGH backend. A new function called qemuDomainDefTPMsPostParse() was added to guarantee that the following combinations in the same domain are valid: - a single TPM device - a single TPM Proxy device - a single TPM + single TPM Proxy devices And these combinations in the same domain are NOT valid: - 2 or more TPM devices - 2 or more TPM Proxy devices Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- src/qemu/qemu_domain.c | 37 +++++++++++++++++++++++++++++++++++++ src/qemu/qemu_validate.c | 19 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 3173fc3a3b..b1b50f05d4 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -4953,6 +4953,40 @@ qemuDomainDefTsegPostParse(virDomainDefPtr def, } +static int +qemuDomainDefTPMsPostParse(virDomainDefPtr def) +{ + virDomainTPMDefPtr proxyTPM = NULL; + virDomainTPMDefPtr regularTPM = NULL; + size_t i; + + if (def->ntpms < 2) + return 0; + + for (i = 0; i < def->ntpms; i++) { + virDomainTPMDefPtr tpm = def->tpms[i]; + + if (tpm->model == VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY) { + if (proxyTPM) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("only a single TPM Proxy device is supported")); + return -1; + } else { + proxyTPM = tpm; + } + } else if (regularTPM) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("only a single TPM non-proxy device is supported")); + return -1; + } else { + regularTPM = tpm; + } + } + + return 0; +} + + static int qemuDomainDefPostParseBasic(virDomainDefPtr def, void *opaque G_GNUC_UNUSED) @@ -5039,6 +5073,9 @@ qemuDomainDefPostParse(virDomainDefPtr def, if (qemuDomainDefTsegPostParse(def, qemuCaps) < 0) return -1; + if (qemuDomainDefTPMsPostParse(def) < 0) + return -1; + return 0; } diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 584d1375b8..28e02ebefc 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -3623,6 +3623,25 @@ qemuValidateDomainDeviceDefTPM(virDomainTPMDef *tpm, case VIR_DOMAIN_TPM_MODEL_SPAPR: flag = QEMU_CAPS_DEVICE_TPM_SPAPR; break; + case VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY: + if (!ARCH_IS_PPC64(def->os.arch)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("TPM Proxy model %s is only available for " + "PPC64 guests"), + virDomainTPMModelTypeToString(tpm->model)); + return -1; + } + + /* TPM Proxy devices have 'passthrough' backend */ + if (tpm->type != VIR_DOMAIN_TPM_TYPE_PASSTHROUGH) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("TPM Proxy model %s requires " + "'Passthrough' backend"), + virDomainTPMModelTypeToString(tpm->model)); + } + + flag = QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY; + break; case VIR_DOMAIN_TPM_MODEL_LAST: default: virReportEnumRangeError(virDomainTPMModel, tpm->model); -- 2.26.2

On 5/21/20 9:07 AM, Daniel Henrique Barboza wrote:
Previous patch handled the conversion of def->tpm to the array def->tpms and the XML parsing logic. This patch handles the validations needed to ensure the intended behavior.
The existing qemuValidateDomainDeviceDefTPM() function was updated to guarantee that the VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY model is exclusive to PPC64 guests and to the VIR_DOMAIN_TPM_TYPE_PASSTHROUGH backend.
A new function called qemuDomainDefTPMsPostParse() was added to guarantee that the following combinations in the same domain are valid:
- a single TPM device - a single TPM Proxy device - a single TPM + single TPM Proxy devices
And these combinations in the same domain are NOT valid:
- 2 or more TPM devices - 2 or more TPM Proxy devices
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- src/qemu/qemu_domain.c | 37 +++++++++++++++++++++++++++++++++++++ src/qemu/qemu_validate.c | 19 +++++++++++++++++++ 2 files changed, 56 insertions(+)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 3173fc3a3b..b1b50f05d4 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -4953,6 +4953,40 @@ qemuDomainDefTsegPostParse(virDomainDefPtr def, }
+static int +qemuDomainDefTPMsPostParse(virDomainDefPtr def) +{ + virDomainTPMDefPtr proxyTPM = NULL; + virDomainTPMDefPtr regularTPM = NULL; + size_t i; + + if (def->ntpms < 2) + return 0; + + for (i = 0; i < def->ntpms; i++) { + virDomainTPMDefPtr tpm = def->tpms[i]; + + if (tpm->model == VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY) { + if (proxyTPM) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("only a single TPM Proxy device is supported")); + return -1; + } else { + proxyTPM = tpm; + } + } else if (regularTPM) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("only a single TPM non-proxy device is supported")); + return -1; + } else { + regularTPM = tpm; + } + } + + return 0; +} + + static int qemuDomainDefPostParseBasic(virDomainDefPtr def, void *opaque G_GNUC_UNUSED) @@ -5039,6 +5073,9 @@ qemuDomainDefPostParse(virDomainDefPtr def, if (qemuDomainDefTsegPostParse(def, qemuCaps) < 0) return -1;
+ if (qemuDomainDefTPMsPostParse(def) < 0) + return -1; + return 0; }
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 584d1375b8..28e02ebefc 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -3623,6 +3623,25 @@ qemuValidateDomainDeviceDefTPM(virDomainTPMDef *tpm, case VIR_DOMAIN_TPM_MODEL_SPAPR: flag = QEMU_CAPS_DEVICE_TPM_SPAPR; break; + case VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY: + if (!ARCH_IS_PPC64(def->os.arch)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("TPM Proxy model %s is only available for " + "PPC64 guests"), + virDomainTPMModelTypeToString(tpm->model)); + return -1; + } + + /* TPM Proxy devices have 'passthrough' backend */ + if (tpm->type != VIR_DOMAIN_TPM_TYPE_PASSTHROUGH) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("TPM Proxy model %s requires " + "'Passthrough' backend"), + virDomainTPMModelTypeToString(tpm->model)); + } + + flag = QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY; + break; case VIR_DOMAIN_TPM_MODEL_LAST: default: virReportEnumRangeError(virDomainTPMModel, tpm->model);
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>

This tests aims to exercise how a TPM Proxy device can be added in the domain, either alone or with a regular TPM device. It also ensures that we do not allow bogus scenarios to slip by. Reviewed-by: Stefan Berger <stefanb@linux.ibm.com> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- tests/qemuxml2argvdata/ppc64-tpm-double.xml | 34 ++++++++++++++ .../ppc64-tpmproxy-double.xml | 38 +++++++++++++++ .../ppc64-tpmproxy-single.xml | 33 +++++++++++++ .../ppc64-tpmproxy-with-tpm.xml | 36 +++++++++++++++ tests/qemuxml2argvtest.c | 12 +++++ .../ppc64-tpmproxy-single.ppc64-latest.xml | 42 +++++++++++++++++ .../ppc64-tpmproxy-with-tpm.ppc64-latest.xml | 46 +++++++++++++++++++ tests/qemuxml2xmltest.c | 2 + 8 files changed, 243 insertions(+) create mode 100644 tests/qemuxml2argvdata/ppc64-tpm-double.xml create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-double.xml create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-single.xml create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-with-tpm.xml create mode 100644 tests/qemuxml2xmloutdata/ppc64-tpmproxy-single.ppc64-latest.xml create mode 100644 tests/qemuxml2xmloutdata/ppc64-tpmproxy-with-tpm.ppc64-latest.xml diff --git a/tests/qemuxml2argvdata/ppc64-tpm-double.xml b/tests/qemuxml2argvdata/ppc64-tpm-double.xml new file mode 100644 index 0000000000..8730547a4d --- /dev/null +++ b/tests/qemuxml2argvdata/ppc64-tpm-double.xml @@ -0,0 +1,34 @@ +<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> + <tpm model='tpm-spapr'> + <backend type='emulator' version='2.0'/> + </tpm> + <tpm model='tpm-spapr'> + <backend type='emulator' version='2.0'/> + </tpm> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/ppc64-tpmproxy-double.xml b/tests/qemuxml2argvdata/ppc64-tpmproxy-double.xml new file mode 100644 index 0000000000..12abda509e --- /dev/null +++ b/tests/qemuxml2argvdata/ppc64-tpmproxy-double.xml @@ -0,0 +1,38 @@ +<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> + <tpm model='spapr-tpm-proxy'> + <backend type='passthrough'> + <device path='/dev/tpmrm0'/> + </backend> + </tpm> + <tpm model='spapr-tpm-proxy'> + <backend type='passthrough'> + <device path='/dev/tpmrm0'/> + </backend> + </tpm> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/ppc64-tpmproxy-single.xml b/tests/qemuxml2argvdata/ppc64-tpmproxy-single.xml new file mode 100644 index 0000000000..729a2cdf28 --- /dev/null +++ b/tests/qemuxml2argvdata/ppc64-tpmproxy-single.xml @@ -0,0 +1,33 @@ +<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> + <tpm model='spapr-tpm-proxy'> + <backend type='passthrough'> + <device path='/dev/tpmrm0'/> + </backend> + </tpm> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/ppc64-tpmproxy-with-tpm.xml b/tests/qemuxml2argvdata/ppc64-tpmproxy-with-tpm.xml new file mode 100644 index 0000000000..a61ec9845c --- /dev/null +++ b/tests/qemuxml2argvdata/ppc64-tpmproxy-with-tpm.xml @@ -0,0 +1,36 @@ +<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> + <tpm model='spapr-tpm-proxy'> + <backend type='passthrough'> + <device path='/dev/tpmrm0'/> + </backend> + </tpm> + <tpm model='tpm-spapr'> + <backend type='emulator' version='2.0'/> + </tpm> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 5b27cf9ae4..1db9c89e12 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -3054,6 +3054,18 @@ mymain(void) QEMU_CAPS_NEC_USB_XHCI, QEMU_CAPS_DEVICE_QEMU_XHCI); + DO_TEST_PARSE_ERROR("ppc64-tpmproxy-double", + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_PCI_OHCI, + QEMU_CAPS_DEVICE_TPM_PASSTHROUGH, + QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY); + + DO_TEST_PARSE_ERROR("ppc64-tpm-double", + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_PCI_OHCI, + QEMU_CAPS_DEVICE_TPM_PASSTHROUGH, + QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY); + DO_TEST("aarch64-usb-controller-qemu-xhci", QEMU_CAPS_OBJECT_GPEX, QEMU_CAPS_NEC_USB_XHCI, diff --git a/tests/qemuxml2xmloutdata/ppc64-tpmproxy-single.ppc64-latest.xml b/tests/qemuxml2xmloutdata/ppc64-tpmproxy-single.ppc64-latest.xml new file mode 100644 index 0000000000..4e0e5f24b8 --- /dev/null +++ b/tests/qemuxml2xmloutdata/ppc64-tpmproxy-single.ppc64-latest.xml @@ -0,0 +1,42 @@ +<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> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>POWER9</model> + </cpu> + <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> + <tpm model='spapr-tpm-proxy'> + <backend type='passthrough'> + <device path='/dev/tpmrm0'/> + </backend> + </tpm> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/ppc64-tpmproxy-with-tpm.ppc64-latest.xml b/tests/qemuxml2xmloutdata/ppc64-tpmproxy-with-tpm.ppc64-latest.xml new file mode 100644 index 0000000000..9b64f914f0 --- /dev/null +++ b/tests/qemuxml2xmloutdata/ppc64-tpmproxy-with-tpm.ppc64-latest.xml @@ -0,0 +1,46 @@ +<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> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>POWER9</model> + </cpu> + <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> + <tpm model='spapr-tpm-proxy'> + <backend type='passthrough'> + <device path='/dev/tpmrm0'/> + </backend> + </tpm> + <tpm model='tpm-spapr'> + <backend type='emulator' version='2.0'/> + <address type='spapr-vio' reg='0x00004000'/> + </tpm> + <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 033f81013e..8360d5eeca 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -609,6 +609,8 @@ mymain(void) DO_TEST("controller-usb-order", QEMU_CAPS_PIIX_DISABLE_S3, QEMU_CAPS_PIIX_DISABLE_S4); + DO_TEST_CAPS_ARCH_LATEST("ppc64-tpmproxy-single", "ppc64"); + DO_TEST_CAPS_ARCH_LATEST("ppc64-tpmproxy-with-tpm", "ppc64"); 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, qemuValidateDomainDeviceDefTPM(), on domain define time. We don't need to verify QEMU capabilities for this device again inside qemu_command.c. Reviewed-by: Stefan Berger <stefanb@linux.ibm.com> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- src/qemu/qemu_alias.c | 5 ++++- src/qemu/qemu_command.c | 27 ++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index 85fdb85940..bb7145d630 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -408,7 +408,10 @@ qemuAssignDeviceTPMAlias(virDomainTPMDefPtr tpm, if (tpm->info.alias) return 0; - tpm->info.alias = g_strdup_printf("tpm%d", idx); + if (tpm->model == VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY) + tpm->info.alias = g_strdup_printf("tpmproxy%d", idx); + else + tpm->info.alias = g_strdup_printf("tpm%d", idx); return 0; } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 59caff08f2..ab3828ec57 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -9039,6 +9039,26 @@ qemuBuildTPMCommandLine(virCommandPtr cmd, } +static int +qemuBuildTPMProxyCommandLine(virCommandPtr cmd, + virDomainTPMDefPtr tpm) +{ + g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; + const char *filePath = NULL; + + filePath = tpm->data.passthrough.source.data.file.path; + + virCommandAddArg(cmd, "-device"); + virBufferAsprintf(&buf, "%s,id=%s,host-path=", + virDomainTPMModelTypeToString(tpm->model), + tpm->info.alias); + virQEMUBuildBufferEscapeComma(&buf, filePath); + virCommandAddArgBuffer(cmd, &buf); + + return 0; +} + + static int qemuBuildTPMsCommandLine(virCommandPtr cmd, const virDomainDef *def, @@ -9047,8 +9067,13 @@ qemuBuildTPMsCommandLine(virCommandPtr cmd, size_t i; for (i = 0; i < def->ntpms; i++) { - if (qemuBuildTPMCommandLine(cmd, def, def->tpms[i], qemuCaps) < 0) + if (def->tpms[i]->model == VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY) { + if (qemuBuildTPMProxyCommandLine(cmd, def->tpms[i]) < 0) + return -1; + } else if (qemuBuildTPMCommandLine(cmd, def, + def->tpms[i], qemuCaps) < 0) { return -1; + } } return 0; -- 2.26.2

Add tests for both supported scenarios: a single TPM Proxy and a TPM Proxy with a regular TPM device in the same domain. Reviewed-by: Stefan Berger <stefanb@linux.ibm.com> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- .../ppc64-tpmproxy-single.ppc64-latest.args | 34 +++++++++++++++++ .../ppc64-tpmproxy-with-tpm.ppc64-latest.args | 37 +++++++++++++++++++ tests/qemuxml2argvtest.c | 3 ++ 3 files changed, 74 insertions(+) create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-single.ppc64-latest.args create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-with-tpm.ppc64-latest.args diff --git a/tests/qemuxml2argvdata/ppc64-tpmproxy-single.ppc64-latest.args b/tests/qemuxml2argvdata/ppc64-tpmproxy-single.ppc64-latest.args new file mode 100644 index 0000000000..f606cee16b --- /dev/null +++ b/tests/qemuxml2argvdata/ppc64-tpmproxy-single.ppc64-latest.args @@ -0,0 +1,34 @@ +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 guest=QEMUGuest1,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,\ +file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \ +-machine pseries,accel=tcg,usb=off,dump-guest-core=off \ +-cpu POWER9 \ +-m 256 \ +-overcommit mem-lock=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,fd=1729,server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-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 \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\ +resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/ppc64-tpmproxy-with-tpm.ppc64-latest.args b/tests/qemuxml2argvdata/ppc64-tpmproxy-with-tpm.ppc64-latest.args new file mode 100644 index 0000000000..83eb58ae19 --- /dev/null +++ b/tests/qemuxml2argvdata/ppc64-tpmproxy-with-tpm.ppc64-latest.args @@ -0,0 +1,37 @@ +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 guest=QEMUGuest1,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,\ +file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \ +-machine pseries,accel=tcg,usb=off,dump-guest-core=off \ +-cpu POWER9 \ +-m 256 \ +-overcommit mem-lock=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,fd=1729,server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device pci-ohci,id=usb,bus=pci.0,addr=0x1 \ +-device spapr-tpm-proxy,id=tpmproxy0,host-path=/dev/tpmrm0 \ +-tpmdev emulator,id=tpm-tpm0,chardev=chrtpm \ +-chardev socket,id=chrtpm,path=/dev/test \ +-device tpm-spapr,tpmdev=tpm-tpm0,id=tpm0,reg=0x00004000 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6 \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\ +resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 1db9c89e12..a494be7b81 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -3066,6 +3066,9 @@ mymain(void) QEMU_CAPS_DEVICE_TPM_PASSTHROUGH, QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY); + DO_TEST_CAPS_LATEST_PPC64("ppc64-tpmproxy-single"); + DO_TEST_CAPS_LATEST_PPC64("ppc64-tpmproxy-with-tpm"); + DO_TEST("aarch64-usb-controller-qemu-xhci", QEMU_CAPS_OBJECT_GPEX, QEMU_CAPS_NEC_USB_XHCI, -- 2.26.2

Reviewed-by: Stefan Berger <stefanb@linux.ibm.com> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> --- docs/news.xml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/news.xml b/docs/news.xml index 4cef804aac..c22a0f0a18 100644 --- a/docs/news.xml +++ b/docs/news.xml @@ -44,6 +44,23 @@ <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". The TPM Proxy connects to a TPM Resource Manager + present in the host, enabling the guest to run in secure virtual + machine mode with the help of an Ultravisor. Adding a TPM Proxy to + a pSeries guest brings no security benefits unless the guest is + running on a PPC64 host that has Ultravisor and TPM Resource Manager + support. Only one TPM Proxy is allowed per guest. A guest using + a TPM Proxy device can instantiate another TPM device at the same + time. This device is supported only for pSeries guests via the new + 'spapr-tpm-proxy' model of the TPM 'passthrough' backend. + </description> + </change> </section> <section title="Improvements"> </section> -- 2.26.2

On Thu, May 21, 2020 at 10:07:20AM -0300, Daniel Henrique Barboza wrote:
changes in v5: - rebased and fixed commits to master at d265171b5784 - moved two TPMs validation from domain_conf.c (patch 05) to qemu_domain.c (patch 06)
Gitlab tree: https://gitlab.com/danielhb/libvirt/tree/spapr_tpm_proxy_v5
Tested-by: Satheesh Rajendran <sathnaga@linux.vnet.ibm.com> libvirt xml: ... <tpm model='spapr-tpm-proxy'> <backend type='passthrough'> <device path='/dev/tpm0'/> </backend> <alias name='tpmproxy0'/> </tpm> ... <qemu:commandline> <qemu:arg value='-trace'/> <qemu:arg value='events=/home/sath/tpm_events_log/tpm_events'/> </qemu:commandline> ... $ cat /home/sath/tpm_events_log/tpm_events spapr_tpm_execute spapr_h_tpm_comm qemu log, trace outputs: ... 4359@1590140133.539001:spapr_tpm_execute data_in=0x2ff40000, data_in_sz=63, data_out=0x2ff40000, data_out_sz=4096 4359@1590140133.556488:spapr_h_tpm_comm tpm_device_path=/dev/tpm0 operation=0x1 .. .. 4359@1590140133.576494:spapr_tpm_execute data_in=0x2ff40000, data_in_sz=14, data_out=0x2ff40000, data_out_sz=4096 4359@1590140133.585730:spapr_h_tpm_comm tpm_device_path=/dev/tpm0 operation=0x1 ... 4359@1590140133.585740:spapr_tpm_execute data_in=0x2ff40000, data_in_sz=86, data_out=0x2ff40000, data_out_sz=4096 4359@1590140133.602373:spapr_h_tpm_comm tpm_device_path=/dev/tpm0 operation=0x1 ... --- Regards, -Satheesh.
v4 link: https://www.redhat.com/archives/libvir-list/2020-May/msg00814.html v3 link: https://www.redhat.com/archives/libvir-list/2020-May/msg00642.html v2 link: https://www.redhat.com/archives/libvir-list/2020-May/msg00604.html v1 link: https://www.redhat.com/archives/libvir-list/2020-May/msg00604.html
Daniel Henrique Barboza (10): docs: documentation and schema for the new TPM Proxy model qemu: Extend QEMU capabilities with 'spapr-tpm-proxy' qemu_extdevice.c: remove unneeded 'ret' variable qemu_tpm, security, tests: change 'switch' clauses for 'if' conf, qemu, security, tests: introducing 'def->tpms' array qemu: add validations after TPM Proxy model introduction tests: add XML schema tests for the TPM Proxy device qemu: build command line for the TPM Proxy device tests/qemuxml2argvtest.c: add TPM Proxy command line tests docs/news.xml: update for the new TPM Proxy device
docs/formatdomain.html.in | 19 ++++- docs/news.xml | 17 +++++ docs/schemas/domaincommon.rng | 1 + src/conf/domain_audit.c | 4 +- src/conf/domain_conf.c | 50 +++++++----- src/conf/domain_conf.h | 6 +- src/qemu/qemu_alias.c | 9 ++- src/qemu/qemu_capabilities.c | 4 + src/qemu/qemu_capabilities.h | 3 + src/qemu/qemu_cgroup.c | 10 ++- src/qemu/qemu_command.c | 59 +++++++++++--- src/qemu/qemu_domain.c | 68 ++++++++++++++--- src/qemu/qemu_domain_address.c | 11 ++- src/qemu/qemu_extdevice.c | 24 +++--- src/qemu/qemu_tpm.c | 76 +++++++++---------- src/qemu/qemu_validate.c | 19 +++++ src/security/security_dac.c | 8 +- src/security/security_selinux.c | 44 +++++------ src/security/virt-aa-helper.c | 14 ++-- .../qemucapabilitiesdata/caps_4.2.0.ppc64.xml | 1 + .../qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + tests/qemuxml2argvdata/ppc64-tpm-double.xml | 34 +++++++++ .../ppc64-tpmproxy-double.xml | 38 ++++++++++ .../ppc64-tpmproxy-single.ppc64-latest.args | 34 +++++++++ .../ppc64-tpmproxy-single.xml | 33 ++++++++ .../ppc64-tpmproxy-with-tpm.ppc64-latest.args | 37 +++++++++ .../ppc64-tpmproxy-with-tpm.xml | 36 +++++++++ tests/qemuxml2argvtest.c | 33 +++++--- .../ppc64-tpmproxy-single.ppc64-latest.xml | 42 ++++++++++ .../ppc64-tpmproxy-with-tpm.ppc64-latest.xml | 46 +++++++++++ tests/qemuxml2xmltest.c | 2 + 31 files changed, 631 insertions(+), 152 deletions(-) create mode 100644 tests/qemuxml2argvdata/ppc64-tpm-double.xml create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-double.xml create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-single.ppc64-latest.args create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-single.xml create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-with-tpm.ppc64-latest.args create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-with-tpm.xml create mode 100644 tests/qemuxml2xmloutdata/ppc64-tpmproxy-single.ppc64-latest.xml create mode 100644 tests/qemuxml2xmloutdata/ppc64-tpmproxy-with-tpm.ppc64-latest.xml
-- 2.26.2

Ping On 5/21/20 10:07 AM, Daniel Henrique Barboza wrote:
changes in v5: - rebased and fixed commits to master at d265171b5784 - moved two TPMs validation from domain_conf.c (patch 05) to qemu_domain.c (patch 06)
Gitlab tree: https://gitlab.com/danielhb/libvirt/tree/spapr_tpm_proxy_v5
v4 link: https://www.redhat.com/archives/libvir-list/2020-May/msg00814.html v3 link: https://www.redhat.com/archives/libvir-list/2020-May/msg00642.html v2 link: https://www.redhat.com/archives/libvir-list/2020-May/msg00604.html v1 link: https://www.redhat.com/archives/libvir-list/2020-May/msg00604.html
Daniel Henrique Barboza (10): docs: documentation and schema for the new TPM Proxy model qemu: Extend QEMU capabilities with 'spapr-tpm-proxy' qemu_extdevice.c: remove unneeded 'ret' variable qemu_tpm, security, tests: change 'switch' clauses for 'if' conf, qemu, security, tests: introducing 'def->tpms' array qemu: add validations after TPM Proxy model introduction tests: add XML schema tests for the TPM Proxy device qemu: build command line for the TPM Proxy device tests/qemuxml2argvtest.c: add TPM Proxy command line tests docs/news.xml: update for the new TPM Proxy device
docs/formatdomain.html.in | 19 ++++- docs/news.xml | 17 +++++ docs/schemas/domaincommon.rng | 1 + src/conf/domain_audit.c | 4 +- src/conf/domain_conf.c | 50 +++++++----- src/conf/domain_conf.h | 6 +- src/qemu/qemu_alias.c | 9 ++- src/qemu/qemu_capabilities.c | 4 + src/qemu/qemu_capabilities.h | 3 + src/qemu/qemu_cgroup.c | 10 ++- src/qemu/qemu_command.c | 59 +++++++++++--- src/qemu/qemu_domain.c | 68 ++++++++++++++--- src/qemu/qemu_domain_address.c | 11 ++- src/qemu/qemu_extdevice.c | 24 +++--- src/qemu/qemu_tpm.c | 76 +++++++++---------- src/qemu/qemu_validate.c | 19 +++++ src/security/security_dac.c | 8 +- src/security/security_selinux.c | 44 +++++------ src/security/virt-aa-helper.c | 14 ++-- .../qemucapabilitiesdata/caps_4.2.0.ppc64.xml | 1 + .../qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + tests/qemuxml2argvdata/ppc64-tpm-double.xml | 34 +++++++++ .../ppc64-tpmproxy-double.xml | 38 ++++++++++ .../ppc64-tpmproxy-single.ppc64-latest.args | 34 +++++++++ .../ppc64-tpmproxy-single.xml | 33 ++++++++ .../ppc64-tpmproxy-with-tpm.ppc64-latest.args | 37 +++++++++ .../ppc64-tpmproxy-with-tpm.xml | 36 +++++++++ tests/qemuxml2argvtest.c | 33 +++++--- .../ppc64-tpmproxy-single.ppc64-latest.xml | 42 ++++++++++ .../ppc64-tpmproxy-with-tpm.ppc64-latest.xml | 46 +++++++++++ tests/qemuxml2xmltest.c | 2 + 31 files changed, 631 insertions(+), 152 deletions(-) create mode 100644 tests/qemuxml2argvdata/ppc64-tpm-double.xml create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-double.xml create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-single.ppc64-latest.args create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-single.xml create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-with-tpm.ppc64-latest.args create mode 100644 tests/qemuxml2argvdata/ppc64-tpmproxy-with-tpm.xml create mode 100644 tests/qemuxml2xmloutdata/ppc64-tpmproxy-single.ppc64-latest.xml create mode 100644 tests/qemuxml2xmloutdata/ppc64-tpmproxy-with-tpm.ppc64-latest.xml
participants (3)
-
Daniel Henrique Barboza
-
Satheesh Rajendran
-
Stefan Berger