For TPM passthrough device support create command line parameters like: -tpmdev passthrough,id=tpm-tpm0,path=/dev/tpm0,cancel-path=/sys/class/misc/tpm0/device/cancel -device tpm-tis,tpmdev=tpm-tpm0,id=tpm0 Signed-off-by: Stefan Berger Reviewed-by: Corey Bryant Tested-by: Corey Bryant --- src/qemu/qemu_command.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) Index: libvirt/src/qemu/qemu_command.c =================================================================== --- libvirt.orig/src/qemu/qemu_command.c +++ libvirt/src/qemu/qemu_command.c @@ -46,6 +46,7 @@ #include "base64.h" #include "device_conf.h" #include "virstoragefile.h" +#include "virtpm.h" #include #include @@ -799,6 +800,10 @@ qemuAssignDeviceAliases(virDomainDefPtr if (virAsprintf(&def->rng->info.alias, "rng%d", 0) < 0) goto no_memory; } + if (def->tpm) { + if (virAsprintf(&def->tpm->info.alias, "tpm%d", 0) < 0) + goto no_memory; + } return 0; @@ -4825,6 +4830,89 @@ cleanup: } +static char *qemuBuildTPMBackendStr(const virDomainDefPtr def, + virQEMUCapsPtr qemuCaps, + const char *emulator) +{ + const virDomainTPMDefPtr tpm = def->tpm; + virBuffer buf = VIR_BUFFER_INITIALIZER; + const char *type = virDomainTPMBackendTypeToString(tpm->type); + const char *cancel_path, *tpmdev; + + virBufferAsprintf(&buf, "%s,id=tpm-%s", type, tpm->info.alias); + + switch (tpm->type) { + case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_TPM_PASSTHROUGH)) + goto no_support; + + tpmdev = tpm->data.passthrough.source.data.file.path; + if (!(cancel_path = virTPMFindCancelPath(tpmdev))) + goto error; + + virBufferAddLit(&buf, ",path="); + virBufferEscape(&buf, ',', ",", "%s", tpmdev); + + virBufferAddLit(&buf, ",cancel-path="); + virBufferEscape(&buf, ',', ",", "%s", cancel_path); + VIR_FREE(cancel_path); + + break; + case VIR_DOMAIN_TPM_TYPE_LAST: + goto error; + } + + if (virBufferError(&buf)) { + virReportOOMError(); + goto error; + } + + return virBufferContentAndReset(&buf); + + no_support: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("The QEMU executable %s does not support TPM " + "backend type %s"), + emulator, type); + + error: + virBufferFreeAndReset(&buf); + return NULL; +} + + +static char *qemuBuildTPMDevStr(const virDomainDefPtr def, + virQEMUCapsPtr qemuCaps, + const char *emulator) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + const virDomainTPMDefPtr tpm = def->tpm; + const char *model = virDomainTPMModelTypeToString(tpm->model); + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_TPM_TIS)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("The QEMU executable %s does not support TPM " + "model %s"), + emulator, model); + goto error; + } + + virBufferAsprintf(&buf, "%s,tpmdev=tpm-%s,id=%s", + model, tpm->info.alias, tpm->info.alias); + + if (virBufferError(&buf)) { + virReportOOMError(); + goto error; + } + + return virBufferContentAndReset(&buf); + + error: + virBufferFreeAndReset(&buf); + return NULL; +} + + static char *qemuBuildSmbiosBiosStr(virSysinfoDefPtr def) { virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -7141,6 +7229,22 @@ qemuBuildCommandLine(virConnectPtr conn, } } + if (def->tpm) { + char *optstr; + + if (!(optstr = qemuBuildTPMBackendStr(def, qemuCaps, emulator))) + goto error; + + virCommandAddArgList(cmd, "-tpmdev", optstr, NULL); + VIR_FREE(optstr); + + if (!(optstr = qemuBuildTPMDevStr(def, qemuCaps, emulator))) + goto error; + + virCommandAddArgList(cmd, "-device", optstr, NULL); + VIR_FREE(optstr); + } + for (i = 0 ; i < def->ninputs ; i++) { virDomainInputDefPtr input = def->inputs[i];