This patch adds support for an external swtpm TPM emulator. The XML for this type of TPM looks as follows: <tpm model='tpm-tis'> <backend type='emulator'/> </tpm> The XML will currently only define a TPM 1.2. Extend the documentation. Add a test case testing the XML parser and formatter. Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxxxxxxxxxx> Reviewed-by: John Ferlan <jferlan@xxxxxxxxxx> --- docs/formatdomain.html.in | 30 +++++++++++++++++++++++++++ docs/schemas/domaincommon.rng | 5 +++++ src/conf/domain_audit.c | 2 ++ src/conf/domain_conf.c | 28 +++++++++++++++++++------ src/conf/domain_conf.h | 6 ++++++ src/qemu/qemu_cgroup.c | 1 + src/qemu/qemu_command.c | 1 + src/qemu/qemu_domain.c | 1 + src/security/security_dac.c | 2 ++ src/security/security_selinux.c | 2 ++ tests/qemuxml2argvdata/tpm-emulator.xml | 30 +++++++++++++++++++++++++++ tests/qemuxml2xmloutdata/tpm-emulator.xml | 34 +++++++++++++++++++++++++++++++ tests/qemuxml2xmltest.c | 1 + 13 files changed, 137 insertions(+), 6 deletions(-) create mode 100644 tests/qemuxml2argvdata/tpm-emulator.xml create mode 100644 tests/qemuxml2xmloutdata/tpm-emulator.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 0d0fd3b9f3..08a57bd751 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -7704,6 +7704,26 @@ qemu-kvm -net nic,model=? /dev/null </tpm> </devices> ... +</pre> + + <p> + The emulator device type gives access to a TPM emulator providing + TPM functionlity for each VM. QEMU talks to it over a Unix socket. With + the emulator device type each guest gets its own private TPM. + <span class="since">'emulator' since 4.4.0</span> + </p> + <p> + Example: usage of the TPM Emulator + </p> +<pre> + ... + <devices> + <tpm model='tpm-tis'> + <backend type='emulator'> + </backend> + </tpm> + </devices> + ... </pre> <dl> <dt><code>model</code></dt> @@ -7738,6 +7758,16 @@ qemu-kvm -net nic,model=? /dev/null </p> </dd> </dl> + <dl> + <dt><code>emulator</code></dt> + <dd> + <p> + For this backend type the 'swtpm' TPM Emulator must be installed on the + host. Libvirt will automatically start an independent TPM emulator + for each QEMU guest requesting access to it. + </p> + </dd> + </dl> </dd> </dl> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 71ac3d079c..3582cb5019 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4124,6 +4124,11 @@ </attribute> <ref name="tpm-passthrough-device"/> </group> + <group> + <attribute name="type"> + <value>emulator</value> + </attribute> + </group> </choice> </element> </define> diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c index 82868bca76..25cccddb56 100644 --- a/src/conf/domain_audit.c +++ b/src/conf/domain_audit.c @@ -586,6 +586,8 @@ virDomainAuditTPM(virDomainObjPtr vm, virDomainTPMDefPtr tpm, "virt=%s resrc=dev reason=%s %s uuid=%s %s", virt, reason, vmname, uuidstr, device); break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + break; case VIR_DOMAIN_TPM_TYPE_LAST: default: break; diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 3689ac0a82..15dd490d17 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -864,7 +864,8 @@ VIR_ENUM_IMPL(virDomainTPMModel, VIR_DOMAIN_TPM_MODEL_LAST, "tpm-crb") VIR_ENUM_IMPL(virDomainTPMBackend, VIR_DOMAIN_TPM_TYPE_LAST, - "passthrough") + "passthrough", + "emulator") VIR_ENUM_IMPL(virDomainIOMMUModel, VIR_DOMAIN_IOMMU_MODEL_LAST, "intel") @@ -2601,6 +2602,11 @@ void virDomainTPMDefFree(virDomainTPMDefPtr def) case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: VIR_FREE(def->data.passthrough.source.data.file.path); break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + virDomainChrSourceDefClear(&def->data.emulator.source); + VIR_FREE(def->data.emulator.storagepath); + VIR_FREE(def->data.emulator.logfile); + break; case VIR_DOMAIN_TPM_TYPE_LAST: break; } @@ -12648,6 +12654,11 @@ virDomainSmartcardDefParseXML(virDomainXMLOptionPtr xmlopt, * </backend> * </tpm> * + * or like this: + * + * <tpm model='tpm-tis'> + * <backend type='emulator'/> + * </tpm> */ static virDomainTPMDefPtr virDomainTPMDefParseXML(virDomainXMLOptionPtr xmlopt, @@ -12714,6 +12725,8 @@ virDomainTPMDefParseXML(virDomainXMLOptionPtr xmlopt, def->data.passthrough.source.type = VIR_DOMAIN_CHR_TYPE_DEV; path = NULL; break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + break; case VIR_DOMAIN_TPM_TYPE_LAST: goto error; } @@ -24925,22 +24938,25 @@ virDomainTPMDefFormat(virBufferPtr buf, virBufferAsprintf(buf, "<tpm model='%s'>\n", virDomainTPMModelTypeToString(def->model)); virBufferAdjustIndent(buf, 2); - virBufferAsprintf(buf, "<backend type='%s'>\n", + virBufferAsprintf(buf, "<backend type='%s'", virDomainTPMBackendTypeToString(def->type)); - virBufferAdjustIndent(buf, 2); switch (def->type) { case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: + virBufferAddLit(buf, ">\n"); + virBufferAdjustIndent(buf, 2); virBufferEscapeString(buf, "<device path='%s'/>\n", def->data.passthrough.source.data.file.path); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</backend>\n"); + break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + virBufferAddLit(buf, "/>\n"); break; case VIR_DOMAIN_TPM_TYPE_LAST: break; } - virBufferAdjustIndent(buf, -2); - virBufferAddLit(buf, "</backend>\n"); - virDomainDeviceInfoFormat(buf, &def->info, flags); virBufferAdjustIndent(buf, -2); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index a78fdee40c..92466278ab 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1286,6 +1286,7 @@ typedef enum { typedef enum { VIR_DOMAIN_TPM_TYPE_PASSTHROUGH, + VIR_DOMAIN_TPM_TYPE_EMULATOR, VIR_DOMAIN_TPM_TYPE_LAST } virDomainTPMBackendType; @@ -1300,6 +1301,11 @@ struct _virDomainTPMDef { struct { virDomainChrSourceDef source; } passthrough; + struct { + virDomainChrSourceDef source; + char *storagepath; + char *logfile; + } emulator; } data; }; diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index 546a4c8e63..54b00a5da5 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -305,6 +305,7 @@ qemuSetupTPMCgroup(virDomainObjPtr vm) case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: ret = qemuSetupChrSourceCgroup(vm, &dev->data.passthrough.source); break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: case VIR_DOMAIN_TPM_TYPE_LAST: break; } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 9da2d609e8..fe6d0912cb 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -9482,6 +9482,7 @@ qemuBuildTPMBackendStr(const virDomainDef *def, VIR_FREE(cancel_path); break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: case VIR_DOMAIN_TPM_TYPE_LAST: goto error; } diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index d3beee5d87..ca5b2c3485 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -10418,6 +10418,7 @@ qemuDomainSetupTPM(virQEMUDriverConfigPtr cfg ATTRIBUTE_UNUSED, return -1; break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: case VIR_DOMAIN_TPM_TYPE_LAST: /* nada */ break; diff --git a/src/security/security_dac.c b/src/security/security_dac.c index 8938e2dd89..3ab229992a 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -1372,6 +1372,7 @@ virSecurityDACSetTPMFileLabel(virSecurityManagerPtr mgr, &tpm->data.passthrough.source, false); break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: case VIR_DOMAIN_TPM_TYPE_LAST: break; } @@ -1393,6 +1394,7 @@ virSecurityDACRestoreTPMFileLabel(virSecurityManagerPtr mgr, &tpm->data.passthrough.source, false); break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: case VIR_DOMAIN_TPM_TYPE_LAST: break; } diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 5f74ef739b..5d20fdae70 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -1472,6 +1472,7 @@ virSecuritySELinuxSetTPMFileLabel(virSecurityManagerPtr mgr, return -1; } break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: case VIR_DOMAIN_TPM_TYPE_LAST: break; } @@ -1505,6 +1506,7 @@ virSecuritySELinuxRestoreTPMFileLabelInt(virSecurityManagerPtr mgr, VIR_FREE(cancel_path); } break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: case VIR_DOMAIN_TPM_TYPE_LAST: break; } diff --git a/tests/qemuxml2argvdata/tpm-emulator.xml b/tests/qemuxml2argvdata/tpm-emulator.xml new file mode 100644 index 0000000000..7f1e5756cb --- /dev/null +++ b/tests/qemuxml2argvdata/tpm-emulator.xml @@ -0,0 +1,30 @@ +<domain type='qemu'> + <name>TPM-VM</name> + <uuid>11d7cd22-da89-3094-6212-079a48a309a1</uuid> + <memory unit='KiB'>2097152</memory> + <currentMemory unit='KiB'>512288</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-2.12'>hvm</type> + <boot dev='hd'/> + <bootmenu enable='yes'/> + </os> + <features> + <acpi/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <tpm model='tpm-tis'> + <backend type='emulator'/> + </tpm> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/tpm-emulator.xml b/tests/qemuxml2xmloutdata/tpm-emulator.xml new file mode 100644 index 0000000000..1b66e8b08a --- /dev/null +++ b/tests/qemuxml2xmloutdata/tpm-emulator.xml @@ -0,0 +1,34 @@ +<domain type='qemu'> + <name>TPM-VM</name> + <uuid>11d7cd22-da89-3094-6212-079a48a309a1</uuid> + <memory unit='KiB'>2097152</memory> + <currentMemory unit='KiB'>512288</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-2.12'>hvm</type> + <boot dev='hd'/> + <bootmenu enable='yes'/> + </os> + <features> + <acpi/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <tpm model='tpm-tis'> + <backend type='emulator'/> + </tpm> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 7cedc2b999..3068e92ee6 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -675,6 +675,7 @@ mymain(void) DO_TEST("disk-copy_on_read", NONE); DO_TEST("tpm-passthrough", NONE); DO_TEST("tpm-passthrough-crb", NONE); + DO_TEST("tpm-emulator", NONE); DO_TEST("metadata", NONE); DO_TEST("metadata-duplicate", NONE); -- 2.14.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list