"virt=%s resrc=tpm-emulator reason=%s %s uuid=%s %s",
virt, reason, vmname, uuidstr, device);
break;
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
+ path = tpm->data.external.source->data.nix.path;
+ if (!(device = virAuditEncode("device", VIR_AUDIT_STR(path)))) {
+ VIR_WARN("OOM while encoding audit message");
+ goto cleanup;
+ }
+
+ VIR_AUDIT(VIR_AUDIT_RECORD_RESOURCE, success,
+ "virt=%s resrc=tpm-external reason=%s %s uuid=%s %s",
+ virt, reason, vmname, uuidstr, device);
+ break;
case VIR_DOMAIN_TPM_TYPE_LAST:
default:
break;
VIR_DOMAIN_TPM_TYPE_LAST,
"passthrough",
"emulator",
+ "external",
);
VIR_ENUM_IMPL(virDomainTPMVersion,
g_free(def->data.emulator.logfile);
virBitmapFree(def->data.emulator.activePcrBanks);
break;
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
+ virObjectUnref(def->data.external.source);
+ break;
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
g_autofree char *persistent_state = NULL;
g_autofree xmlNodePtr *backends = NULL;
g_autofree xmlNodePtr *nodes = NULL;
+ g_autofree char *type = NULL;
int bank;
if (!(def = virDomainTPMDefNew(xmlopt)))
virBitmapSetBitExpand(def->data.emulator.activePcrBanks, bank);
}
break;
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
+ if (!(type = virXPathString("string(./backend/source/@type)", ctxt))) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing external TPM backend type"));
+ goto error;
+ }
+
+ if (!(def->data.external.source = virDomainChrSourceDefNew(xmlopt)))
+ goto error;
+
+ def->data.external.source->type = virDomainChrTypeFromString(type);
+ if (def->data.external.source->type < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown backend type '%s' for external TPM"),
+ type);
+ goto error;
+ }
+
+ if (virDomainChrSourceDefParseXML(def->data.external.source,
+ backends[0], flags, NULL, ctxt) < 0)
+ goto error;
+ break;
case VIR_DOMAIN_TPM_TYPE_LAST:
goto error;
}
break;
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
virXMLFormatElement(&backendChildBuf, "active_pcr_banks", NULL, &activePcrBanksBuf);
}
break;
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
+ if (def->data.external.source->type == VIR_DOMAIN_CHR_TYPE_UNIX) {
+ virBufferAddLit(&backendChildBuf, "<source type='unix' mode='connect'");
+ virBufferEscapeString(&backendChildBuf, " path='%s'/>\n",
+ def->data.external.source->data.nix.path);
+ }
+ break;
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
typedef enum {
VIR_DOMAIN_TPM_TYPE_PASSTHROUGH,
VIR_DOMAIN_TPM_TYPE_EMULATOR,
+ VIR_DOMAIN_TPM_TYPE_EXTERNAL,
VIR_DOMAIN_TPM_TYPE_LAST
} virDomainTPMBackendType;
bool persistent_state;
virBitmap *activePcrBanks;
} emulator;
+ struct {
+ virDomainChrSourceDef *source;
+ } external;
} data;
};
break;
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
+ break;
+
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
+ if (tpm->data.external.source->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("only source type 'unix' is supported for external TPM device"));
+ return -1;
+ }
+ if (tpm->data.external.source->data.nix.listen) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("only 'client' mode is supported for external TPM device"));
+ return -1;
+ }
+ if (tpm->data.external.source->data.nix.path == NULL) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing socket path for external TPM device"));
+ return -1;
+ }
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
</attribute>
</optional>
</group>
+ <group>
+ <attribute name="type">
+ <value>external</value>
+ </attribute>
+ <ref name="tpm-external-source"/>
+ </group>
</choice>
<optional>
<attribute name="version">
</optional>
</define>
+ <define name="tpm-external-source">
+ <optional>
+ <element name="source">
+ <attribute name="type">
+ <value>unix</value>
+ </attribute>
+ <attribute name="path">
+ <ref name="filePath"/>
+ </attribute>
+ <attribute name="mode">
+ <value>connect</value>
+ </attribute>
+ </element>
+ </optional>
+ </define>
+
<define name="tpm-backend-emulator-encryption">
<optional>
<element name="encryption">
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_TPM_PASSTHROUGH))
VIR_DOMAIN_CAPS_ENUM_SET(tpm->backendModel, VIR_DOMAIN_TPM_TYPE_PASSTHROUGH);
if (virTPMHasSwtpm()) {
- if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_TPM_EMULATOR))
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_TPM_EMULATOR)) {
VIR_DOMAIN_CAPS_ENUM_SET(tpm->backendModel, VIR_DOMAIN_TPM_TYPE_EMULATOR);
+ VIR_DOMAIN_CAPS_ENUM_SET(tpm->backendModel, VIR_DOMAIN_TPM_TYPE_EXTERNAL);
+ }
if (virTPMSwtpmSetupCapsGet(VIR_TPM_SWTPM_SETUP_FEATURE_TPM_1_2)) {
VIR_DOMAIN_CAPS_ENUM_SET(tpm->backendVersion, VIR_DOMAIN_TPM_VERSION_1_2);
tpm->backendVersion.report = true;
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
return qemuSetupChrSourceCgroup(vm, dev->data.passthrough.source);
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
{
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
- virBufferAsprintf(&buf, "%s", virDomainTPMBackendTypeToString(tpm->type));
+ if (tpm->type == VIR_DOMAIN_TPM_TYPE_EXTERNAL)
+ virBufferAddLit(&buf, "emulator");
+ else
+ virBufferAsprintf(&buf, "%s", virDomainTPMBackendTypeToString(tpm->type));
virBufferAsprintf(&buf, ",id=tpm-%s", tpm->info.alias);
switch (tpm->type) {
virQEMUBuildBufferEscapeComma(&buf, qemuFDPassGetPath(passcancel));
break;
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
virBufferAddLit(&buf, ",chardev=chrtpm");
break;
case VIR_DOMAIN_TPM_TYPE_LAST:
return -1;
break;
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
+ if (qemuBuildChardevCommand(cmd, tpm->data.external.source, "chrtpm", priv->qemuCaps) < 0)
+ return -1;
+ break;
+
case VIR_DOMAIN_TPM_TYPE_LAST:
virReportEnumRangeError(virDomainTPMBackendType, tpm->type);
return -1;
break;
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
return cb(dev, dev->data.tpm->data.emulator.source, opaque);
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
+ return cb(dev, dev->data.tpm->data.external.source, opaque);
+
case VIR_DOMAIN_TPM_TYPE_LAST:
return 0;
}
break;
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
/* nada */
break;
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
return virFileIsSharedFS(tpm->data.emulator.storagepath) == 1;
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
return QEMU_DOMAIN_TPM_PRIVATE(tpm)->swtpm.can_migrate_shared_storage;
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
tpm->data.emulator.source,
false, false);
break;
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
break;
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
/* swtpm will have removed the Unix socket upon termination */
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
if (rc < 0)
return -1;
break;
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
break;
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
/* swtpm will have removed the Unix socket upon termination */
+ case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
+ <value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>
--- /dev/null
+<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>
+ <cpu mode='custom' match='exact' check='none'>
+ <model fallback='forbid'>qemu64</model>
+ </cpu>
+ <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' model='piix3-uhci'>
+ <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='external'>
+ <source type='unix' mode='connect' path='/tmp/path.sock'/>
+ </backend>
+ </tpm>
+ <audio id='1' type='none'/>
+ <memballoon model='virtio'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
+ </memballoon>
+ </devices>
+</domain>
--- /dev/null
+../qemuxml2argvdata/tpm-external.xml
\ No newline at end of file
DO_TEST_CAPS_LATEST("tpm-emulator-tpm2-enc");
DO_TEST_CAPS_LATEST("tpm-emulator-tpm2-pstate");
DO_TEST_CAPS_ARCH_LATEST("aarch64-tpm", "aarch64");
+ DO_TEST_CAPS_LATEST("tpm-external");
DO_TEST_NOCAPS("metadata");
DO_TEST_NOCAPS("metadata-duplicate");