[libvirt] [PATCH v9 01/17] conf: Add support for external swtpm TPM emulator to domain XML

Stefan Berger stefanb at linux.vnet.ibm.com
Mon Jun 4 15:46:40 UTC 2018


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 at linux.vnet.ibm.com>
Reviewed-by: John Ferlan <jferlan at redhat.com>
Reviewed-by: Ján Tomko <jtomko at redhat.com>
---
 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 22ef81052d..5bdd01072b 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -7740,6 +7740,26 @@ qemu-kvm -net nic,model=? /dev/null
   </tpm>
 </devices>
 ...
+</pre>
+
+    <p>
+      The emulator device type gives access to a TPM emulator providing
+      TPM functionality 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.5.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>
@@ -7774,6 +7794,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 b7404e1ce0..5fd7f7487f 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -4133,6 +4133,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 14138d93af..b92779ce40 100644
--- a/src/conf/domain_audit.c
+++ b/src/conf/domain_audit.c
@@ -595,6 +595,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 86814d5f64..2e892ba5e0 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -866,7 +866,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")
@@ -2641,6 +2642,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;
     }
@@ -12763,6 +12769,11 @@ virDomainSmartcardDefParseXML(virDomainXMLOptionPtr xmlopt,
  *   </backend>
  * </tpm>
  *
+ * or like this:
+ *
+ * <tpm model='tpm-tis'>
+ *   <backend type='emulator'/>
+ * </tpm>
  */
 static virDomainTPMDefPtr
 virDomainTPMDefParseXML(virDomainXMLOptionPtr xmlopt,
@@ -12829,6 +12840,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;
     }
@@ -25210,22 +25223,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 6cc8f8a29b..5525b95261 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1291,6 +1291,7 @@ typedef enum {
 
 typedef enum {
     VIR_DOMAIN_TPM_TYPE_PASSTHROUGH,
+    VIR_DOMAIN_TPM_TYPE_EMULATOR,
 
     VIR_DOMAIN_TPM_TYPE_LAST
 } virDomainTPMBackendType;
@@ -1305,6 +1306,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 0b5ec4f2ba..572861aee8 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -9528,6 +9528,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 2c51e4c0d8..e764687a85 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -10724,6 +10724,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 5671114de0..bf3f469735 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -677,6 +677,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




More information about the libvir-list mailing list