]> xenbits.xensource.com Git - libvirt.git/commitdiff
conf: Add support for external swtpm TPM emulator to domain XML
authorStefan Berger <stefanb@linux.vnet.ibm.com>
Tue, 4 Apr 2017 16:22:31 +0000 (12:22 -0400)
committerStefan Berger <stefanb@linux.vnet.ibm.com>
Wed, 6 Jun 2018 14:48:41 +0000 (10:48 -0400)
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@linux.vnet.ibm.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
13 files changed:
docs/formatdomain.html.in
docs/schemas/domaincommon.rng
src/conf/domain_audit.c
src/conf/domain_conf.c
src/conf/domain_conf.h
src/qemu/qemu_cgroup.c
src/qemu/qemu_command.c
src/qemu/qemu_domain.c
src/security/security_dac.c
src/security/security_selinux.c
tests/qemuxml2argvdata/tpm-emulator.xml [new file with mode: 0644]
tests/qemuxml2xmloutdata/tpm-emulator.xml [new file with mode: 0644]
tests/qemuxml2xmltest.c

index 7f4de657c6afd952026b394229515c6037ea37fe..1f1fda9dd3c64ef64c0b9add80b76cbf62384734 100644 (file)
@@ -7750,6 +7750,26 @@ qemu-kvm -net nic,model=? /dev/null
   &lt;/tpm&gt;
 &lt;/devices&gt;
 ...
+</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>
+  ...
+  &lt;devices&gt;
+    &lt;tpm model='tpm-tis'&gt;
+      &lt;backend type='emulator'&gt;
+      &lt;/backend&gt;
+    &lt;/tpm&gt;
+  &lt;/devices&gt;
+  ...
 </pre>
     <dl>
       <dt><code>model</code></dt>
@@ -7784,6 +7804,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>
 
index 6379ab1e63f9805982aecedd559b4fa7bff92ad1..8ee6eebcf47ab51ea04073e6c6f847f633e79159 100644 (file)
           </attribute>
           <ref name="tpm-passthrough-device"/>
         </group>
+        <group>
+          <attribute name="type">
+             <value>emulator</value>
+          </attribute>
+        </group>
       </choice>
     </element>
   </define>
index 14138d93aff0c7e2fa7b24103b67959080d8c1bc..b92779ce409acabc76deea251444db6ece5fd3e2 100644 (file)
@@ -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;
index 4aaad2a1d4cbecacd401944e34f2c4d19d788072..4e3861d227364635823a06d5479b671376363bd6 100644 (file)
@@ -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;
     }
@@ -12757,6 +12763,11 @@ virDomainSmartcardDefParseXML(virDomainXMLOptionPtr xmlopt,
  *   </backend>
  * </tpm>
  *
+ * or like this:
+ *
+ * <tpm model='tpm-tis'>
+ *   <backend type='emulator'/>
+ * </tpm>
  */
 static virDomainTPMDefPtr
 virDomainTPMDefParseXML(virDomainXMLOptionPtr xmlopt,
@@ -12823,6 +12834,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;
     }
@@ -25223,22 +25236,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);
index b6c4090ea1fc1768b1e2fbcb967d4e1e5586987b..066d8bbb442916f7e0ed86b9d86cfc2267962f49 100644 (file)
@@ -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;
 };
 
index 546a4c8e6330fdf6af903a3c900c58d29aebfa88..54b00a5da55654e98e53fcd82fc648236f3c584c 100644 (file)
@@ -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;
     }
index 1324c672ba6d49cecacfa0fb8480479d1c7c7bf5..11ada72dfd0717a8a254b8a4c35fab277b046a46 100644 (file)
@@ -9580,6 +9580,7 @@ qemuBuildTPMBackendStr(const virDomainDef *def,
         VIR_FREE(cancel_path);
 
         break;
+    case VIR_DOMAIN_TPM_TYPE_EMULATOR:
     case VIR_DOMAIN_TPM_TYPE_LAST:
         goto error;
     }
index 1fb1ef1deb802e407ab8aac675118222d20ac13c..efe494d2e151cd676b1ac6e3d183d2b60fc7fedc 100644 (file)
@@ -11012,6 +11012,7 @@ qemuDomainSetupTPM(virQEMUDriverConfigPtr cfg ATTRIBUTE_UNUSED,
             return -1;
         break;
 
+    case VIR_DOMAIN_TPM_TYPE_EMULATOR:
     case VIR_DOMAIN_TPM_TYPE_LAST:
         /* nada */
         break;
index 8938e2dd89dde9f767ab75d67f61970baba56d6e..3ab229992a24299094455d8ab8dac94bbd352602 100644 (file)
@@ -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;
     }
index 5f74ef739b2fd311c0dfb039a2301c3cc47b436f..5d20fdae705fbcb7306350b5cb880801e84023f6 100644 (file)
@@ -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 (file)
index 0000000..7f1e575
--- /dev/null
@@ -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 (file)
index 0000000..1b66e8b
--- /dev/null
@@ -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>
index 56b666256f5e8d9ad02a03e773f3a26d30f710c7..115db6e64bf617d45183baf9532f8b0355ce7fdb 100644 (file)
@@ -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);