for (i = 0; i < vm->def->nrngs; i++)
virDomainAuditRNG(vm, NULL, vm->def->rngs[i], "start", true);
- if (vm->def->tpm)
- virDomainAuditTPM(vm, vm->def->tpm, "start", true);
+ for (i = 0; i < vm->def->ntpms; i++)
+ virDomainAuditTPM(vm, vm->def->tpms[i], "start", true);
for (i = 0; i < vm->def->nshmems; i++)
virDomainAuditShmem(vm, vm->def->shmems[i], "start", true);
"tpm-tis",
"tpm-crb",
"tpm-spapr",
+ "spapr-tpm-proxy",
);
VIR_ENUM_IMPL(virDomainTPMBackend,
virDomainMemoryDefFree(def->mems[i]);
VIR_FREE(def->mems);
- virDomainTPMDefFree(def->tpm);
+ for (i = 0; i < def->ntpms; i++)
+ virDomainTPMDefFree(def->tpms[i]);
+ VIR_FREE(def->tpms);
for (i = 0; i < def->npanics; i++)
virDomainPanicDefFree(def->panics[i]);
if ((rc = cb(def, &device, &def->shmems[i]->info, opaque)) != 0)
return rc;
}
- if (def->tpm) {
- device.type = VIR_DOMAIN_DEVICE_TPM;
- device.data.tpm = def->tpm;
- if ((rc = cb(def, &device, &def->tpm->info, opaque)) != 0)
+ device.type = VIR_DOMAIN_DEVICE_TPM;
+ for (i = 0; i < def->ntpms; i++) {
+ device.data.tpm = def->tpms[i];
+ if ((rc = cb(def, &device, &def->tpms[i]->info, opaque)) != 0)
return rc;
}
device.type = VIR_DOMAIN_DEVICE_PANIC;
if ((n = virXPathNodeSet("./devices/tpm", ctxt, &nodes)) < 0)
goto error;
- if (n > 1) {
+ if (n > 2) {
virReportError(VIR_ERR_XML_ERROR, "%s",
- _("only a single TPM device is supported"));
+ _("a maximum of two TPM devices is supported, one of "
+ "them being a TPM Proxy device"));
goto error;
}
- if (n > 0) {
- if (!(def->tpm = virDomainTPMDefParseXML(xmlopt, nodes[0], ctxt, flags)))
+ if (n && VIR_ALLOC_N(def->tpms, n) < 0)
+ goto error;
+
+ for (i = 0; i < n; i++) {
+ virDomainTPMDefPtr tpm = virDomainTPMDefParseXML(xmlopt, nodes[i],
+ ctxt, flags);
+ if (!tpm)
goto error;
+
+ def->tpms[def->ntpms++] = tpm;
}
VIR_FREE(nodes);
goto error;
}
- if (src->tpm && dst->tpm) {
- if (!virDomainTPMDefCheckABIStability(src->tpm, dst->tpm))
- goto error;
- } else if (src->tpm || dst->tpm) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("Either both target and source domains or none of "
- "them must have TPM device present"));
+ if (src->ntpms != dst->ntpms) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Target domain TPM device count %zu "
+ "does not match source %zu"),
+ dst->ntpms, src->ntpms);
goto error;
}
+ for (i = 0; i < src->ntpms; i++) {
+ if (!virDomainTPMDefCheckABIStability(src->tpms[i], dst->tpms[i]))
+ goto error;
+ }
+
if (src->nmems != dst->nmems) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Target domain memory device count %zu "
goto error;
}
- if (def->tpm) {
- if (virDomainTPMDefFormat(buf, def->tpm, flags) < 0)
+ for (n = 0; n < def->ntpms; n++) {
+ if (virDomainTPMDefFormat(buf, def->tpms[n], flags) < 0)
goto error;
}
VIR_DOMAIN_TPM_MODEL_TIS,
VIR_DOMAIN_TPM_MODEL_CRB,
VIR_DOMAIN_TPM_MODEL_SPAPR,
+ VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY,
VIR_DOMAIN_TPM_MODEL_LAST
} virDomainTPMModel;
size_t nsysinfo;
virSysinfoDefPtr *sysinfo;
+ /* At maximum 2 TPMs on the domain if a TPM Proxy is present. */
+ size_t ntpms;
+ virDomainTPMDefPtr *tpms;
+
/* Only 1 */
virDomainWatchdogDefPtr watchdog;
virDomainMemballoonDefPtr memballoon;
virDomainNVRAMDefPtr nvram;
- virDomainTPMDefPtr tpm;
virCPUDefPtr cpu;
virDomainRedirFilterDefPtr redirfilter;
virDomainIOMMUDefPtr iommu;
if (qemuAssignDeviceRNGAlias(def, def->rngs[i]) < 0)
return -1;
}
- if (def->tpm) {
- if (qemuAssignDeviceTPMAlias(def->tpm, 0) < 0)
+ for (i = 0; i < def->ntpms; i++) {
+ if (qemuAssignDeviceTPMAlias(def->tpms[i], i) < 0)
return -1;
}
for (i = 0; i < def->nmems; i++) {
static int
-qemuSetupTPMCgroup(virDomainObjPtr vm)
+qemuSetupTPMCgroup(virDomainObjPtr vm,
+ virDomainTPMDefPtr dev)
{
int ret = 0;
- virDomainTPMDefPtr dev = vm->def->tpm;
switch (dev->type) {
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
vm) < 0)
return -1;
- if (vm->def->tpm && qemuSetupTPMCgroup(vm) < 0)
- return -1;
+ for (i = 0; i < vm->def->ntpms; i++) {
+ if (qemuSetupTPMCgroup(vm, vm->def->tpms[i]) < 0)
+ return -1;
+ }
for (i = 0; i < vm->def->nhostdevs; i++) {
/* This may allow /dev/vfio/vfio multiple times, but that
static char *
qemuBuildTPMDevStr(const virDomainDef *def,
+ virDomainTPMDefPtr tpm,
virQEMUCapsPtr qemuCaps)
{
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
- virDomainTPMDef *tpm = def->tpm;
const char *model = virDomainTPMModelTypeToString(tpm->model);
virBufferAsprintf(&buf, "%s,tpmdev=tpm-%s,id=%s",
static char *
-qemuBuildTPMBackendStr(const virDomainDef *def,
- virCommandPtr cmd,
+qemuBuildTPMBackendStr(virCommandPtr cmd,
+ virDomainTPMDefPtr tpm,
int *tpmfd,
int *cancelfd,
char **chardev)
{
- const virDomainTPMDef *tpm = def->tpm;
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
g_autofree char *cancel_path = NULL;
g_autofree char *devset = NULL;
static int
qemuBuildTPMCommandLine(virCommandPtr cmd,
const virDomainDef *def,
+ virDomainTPMDefPtr tpm,
virQEMUCapsPtr qemuCaps)
{
char *optstr;
int cancelfd = -1;
char *fdset;
- if (!def->tpm)
- return 0;
-
- if (!(optstr = qemuBuildTPMBackendStr(def, cmd,
+ if (!(optstr = qemuBuildTPMBackendStr(cmd, tpm,
&tpmfd, &cancelfd,
&chardev)))
return -1;
VIR_FREE(fdset);
}
- if (!(optstr = qemuBuildTPMDevStr(def, qemuCaps)))
+ if (!(optstr = qemuBuildTPMDevStr(def, tpm, qemuCaps)))
return -1;
virCommandAddArgList(cmd, "-device", optstr, NULL);
return 0;
}
+
+static int
+qemuBuildTPMsCommandLine(virCommandPtr cmd,
+ const virDomainDef *def,
+ virQEMUCapsPtr qemuCaps)
+{
+ size_t i;
+
+ for (i = 0; i < def->ntpms; i++) {
+ if (qemuBuildTPMCommandLine(cmd, def, def->tpms[i], qemuCaps) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int
qemuBuildSEVCommandLine(virDomainObjPtr vm, virCommandPtr cmd,
virDomainSEVDefPtr sev)
chardevStdioLogd) < 0)
return NULL;
- if (qemuBuildTPMCommandLine(cmd, def, qemuCaps) < 0)
+ if (qemuBuildTPMsCommandLine(cmd, def, qemuCaps) < 0)
return NULL;
if (qemuBuildInputCommandLine(cmd, def, qemuCaps) < 0)
static int
qemuDomainSetupTPM(virQEMUDriverConfigPtr cfg G_GNUC_UNUSED,
- virDomainObjPtr vm,
+ virDomainTPMDefPtr dev,
const struct qemuDomainCreateDeviceData *data)
{
- virDomainTPMDefPtr dev = vm->def->tpm;
-
- if (!dev)
- return 0;
-
- VIR_DEBUG("Setting up TPM");
-
switch (dev->type) {
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
if (qemuDomainCreateDevice(dev->data.passthrough.source.data.file.path,
break;
}
- VIR_DEBUG("Setup TPM");
+ return 0;
+}
+
+
+static int
+qemuDomainSetupAllTPMs(virQEMUDriverConfigPtr cfg G_GNUC_UNUSED,
+ virDomainObjPtr vm,
+ const struct qemuDomainCreateDeviceData *data)
+{
+ size_t i;
+
+ VIR_DEBUG("Setting up TPMs");
+
+ for (i = 0; i < vm->def->ntpms; i++) {
+ if (qemuDomainSetupTPM(cfg, vm->def->tpms[i], data) < 0)
+ return -1;
+ }
+
+ VIR_DEBUG("Setup all TPMs");
return 0;
}
if (qemuDomainSetupAllChardevs(cfg, vm, &data) < 0)
goto cleanup;
- if (qemuDomainSetupTPM(cfg, vm, &data) < 0)
+ if (qemuDomainSetupAllTPMs(cfg, vm, &data) < 0)
goto cleanup;
if (qemuDomainSetupAllGraphics(cfg, vm, &data) < 0)
return -1;
}
- if (def->tpm) {
- if (qemuDomainIsPSeries(def))
- def->tpm->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
- if (qemuDomainAssignSpaprVIOAddress(def, &def->tpm->info,
+ for (i = 0; i < def->ntpms; i++) {
+ virDomainTPMDefPtr tpm = def->tpms[i];
+
+ if (tpm->model != VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY &&
+ qemuDomainIsPSeries(def))
+ tpm->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
+ if (qemuDomainAssignSpaprVIOAddress(def, &tpm->info,
VIO_ADDR_TPM) < 0)
return -1;
}
qemuExtDevicesInitPaths(virQEMUDriverPtr driver,
virDomainDefPtr def)
{
- if (def->tpm)
+ if (def->ntpms > 0)
return qemuExtTPMInitPaths(driver, def);
return 0;
virDomainDefPtr def = vm->def;
size_t i;
- if (def->tpm &&
+ if (def->ntpms > 0 &&
qemuExtTPMPrepareHost(driver, def) < 0)
return -1;
if (qemuExtDevicesInitPaths(driver, def) < 0)
return;
- if (def->tpm)
+ if (def->ntpms > 0)
qemuExtTPMCleanupHost(def);
}
}
}
- if (def->tpm && qemuExtTPMStart(driver, vm, incomingMigration) < 0)
+ if (def->ntpms > 0 && qemuExtTPMStart(driver, vm, incomingMigration) < 0)
return -1;
for (i = 0; i < def->nnets; i++) {
qemuExtVhostUserGPUStop(driver, vm, video);
}
- if (def->tpm)
+ if (def->ntpms > 0)
qemuExtTPMStop(driver, vm);
for (i = 0; i < def->nnets; i++) {
return true;
}
- if (def->tpm && def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR)
- return true;
+ for (i = 0; i < def->ntpms; i++) {
+ if (def->tpms[i]->type == VIR_DOMAIN_TPM_TYPE_EMULATOR)
+ return true;
+ }
for (i = 0; i < def->nfss; i++) {
virDomainFSDefPtr fs = def->fss[i];
return -1;
}
- if (def->tpm &&
+ if (def->ntpms > 0 &&
qemuExtTPMSetupCgroup(driver, def, cgroup) < 0)
return -1;
virDomainDefPtr def)
{
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+ size_t i;
- if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR)
- return qemuTPMEmulatorInitPaths(def->tpm, cfg->swtpmStorageDir,
+ for (i = 0; i < def->ntpms; i++) {
+ if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR)
+ continue;
+
+ return qemuTPMEmulatorInitPaths(def->tpms[i], cfg->swtpmStorageDir,
def->uuid);
+ }
return 0;
}
{
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
g_autofree char *shortName = NULL;
+ size_t i;
+
+ for (i = 0; i < def->ntpms; i++) {
+ if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR)
+ continue;
- if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) {
shortName = virDomainDefGetShortName(def);
if (!shortName)
return -1;
- return qemuTPMEmulatorPrepareHost(def->tpm, cfg->swtpmLogDir,
+ return qemuTPMEmulatorPrepareHost(def->tpms[i], cfg->swtpmLogDir,
def->name, cfg->swtpm_user,
cfg->swtpm_group,
cfg->swtpmStateDir, cfg->user,
void
qemuExtTPMCleanupHost(virDomainDefPtr def)
{
- if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR)
- qemuTPMDeleteEmulatorStorage(def->tpm);
+ size_t i;
+
+ for (i = 0; i < def->ntpms; i++) {
+ if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR)
+ continue;
+
+ qemuTPMDeleteEmulatorStorage(def->tpms[i]);
+ }
}
static int
qemuExtTPMStartEmulator(virQEMUDriverPtr driver,
virDomainObjPtr vm,
+ virDomainTPMDefPtr tpm,
bool incomingMigration)
{
g_autoptr(virCommand) cmd = NULL;
int exitstatus = 0;
g_autofree char *errbuf = NULL;
g_autoptr(virQEMUDriverConfig) cfg = NULL;
- virDomainTPMDefPtr tpm = vm->def->tpm;
g_autofree char *shortName = virDomainDefGetShortName(vm->def);
int cmdret = 0, timeout, rc;
pid_t pid;
virDomainObjPtr vm,
bool incomingMigration)
{
- virDomainTPMDefPtr tpm = vm->def->tpm;
+ size_t i;
+
+ for (i = 0; i < vm->def->ntpms; i++) {
+ if (vm->def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR)
+ continue;
- if (tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR)
- return qemuExtTPMStartEmulator(driver, vm, incomingMigration);
+ return qemuExtTPMStartEmulator(driver, vm, vm->def->tpms[i],
+ incomingMigration);
+ }
return 0;
}
{
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
g_autofree char *shortName = NULL;
+ size_t i;
+
+ for (i = 0; i < vm->def->ntpms; i++) {
+ if (vm->def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR)
+ continue;
- if (vm->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) {
shortName = virDomainDefGetShortName(vm->def);
if (!shortName)
return;
g_autofree char *shortName = NULL;
int rc;
pid_t pid;
+ size_t i;
+
+ for (i = 0; i < def->ntpms; i++) {
+ if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR)
+ continue;
- if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) {
shortName = virDomainDefGetShortName(def);
if (!shortName)
return -1;
&chardevData) < 0)
rc = -1;
- if (def->tpm) {
+ for (i = 0; i < def->ntpms; i++) {
if (virSecurityDACRestoreTPMFileLabel(mgr,
def,
- def->tpm) < 0)
+ def->tpms[i]) < 0)
rc = -1;
}
&chardevData) < 0)
return -1;
- if (def->tpm) {
+ for (i = 0; i < def->ntpms; i++) {
if (virSecurityDACSetTPMFileLabel(mgr,
def,
- def->tpm) < 0)
+ def->tpms[i]) < 0)
return -1;
}
return -1;
}
- if (def->tpm) {
- if (virSecuritySELinuxRestoreTPMFileLabelInt(mgr, def, def->tpm) < 0)
+ for (i = 0; i < def->ntpms; i++) {
+ if (virSecuritySELinuxRestoreTPMFileLabelInt(mgr, def, def->tpms[i]) < 0)
rc = -1;
}
return -1;
}
- if (def->tpm) {
- if (virSecuritySELinuxSetTPMFileLabel(mgr, def, def->tpm) < 0)
+ for (i = 0; i < def->ntpms; i++) {
+ if (virSecuritySELinuxSetTPMFileLabel(mgr, def, def->tpms[i]) < 0)
return -1;
}
virDomainDefPtr def)
{
int ret = 0;
+ size_t i;
virSecurityLabelDefPtr seclabel;
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
if (seclabel == NULL)
return 0;
- if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) {
+ for (i = 0; i < def->ntpms; i++) {
+ if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR)
+ continue;
+
ret = virSecuritySELinuxSetFileLabels(
- mgr, def->tpm->data.emulator.storagepath,
+ mgr, def->tpms[i]->data.emulator.storagepath,
seclabel);
- if (ret == 0 && def->tpm->data.emulator.logfile)
+ if (ret == 0 && def->tpms[i]->data.emulator.logfile)
ret = virSecuritySELinuxSetFileLabels(
- mgr, def->tpm->data.emulator.logfile,
+ mgr, def->tpms[i]->data.emulator.logfile,
seclabel);
}
virDomainDefPtr def)
{
int ret = 0;
+ size_t i;
+
+ for (i = 0; i < def->ntpms; i++) {
+ if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR)
+ continue;
- if (def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) {
ret = virSecuritySELinuxRestoreFileLabels(
- mgr, def->tpm->data.emulator.storagepath);
- if (ret == 0 && def->tpm->data.emulator.logfile)
+ mgr, def->tpms[i]->data.emulator.storagepath);
+ if (ret == 0 && def->tpms[i]->data.emulator.logfile)
ret = virSecuritySELinuxRestoreFileLabels(
- mgr, def->tpm->data.emulator.logfile);
+ mgr, def->tpms[i]->data.emulator.logfile);
}
return ret;
}
- if (ctl->def->tpm) {
+ if (ctl->def->ntpms > 0) {
char *shortName = NULL;
const char *tpmpath = NULL;
- if (ctl->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) {
+ for (i = 0; i < ctl->def->ntpms; i++) {
+ if (ctl->def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR)
+ continue;
+
shortName = virDomainDefGetShortName(ctl->def);
- switch (ctl->def->tpm->version) {
+ switch (ctl->def->tpms[i]->version) {
case VIR_DOMAIN_TPM_VERSION_1_2:
tpmpath = "tpm1.2";
break;
vsockPriv->vhostfd = 6789;
}
- if (vm->def->tpm) {
- if (vm->def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) {
- VIR_FREE(vm->def->tpm->data.emulator.source.data.file.path);
- vm->def->tpm->data.emulator.source.data.file.path = g_strdup("/dev/test");
- vm->def->tpm->data.emulator.source.type = VIR_DOMAIN_CHR_TYPE_FILE;
- }
+ for (i = 0; i < vm->def->ntpms; i++) {
+ if (vm->def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR)
+ continue;
+
+ VIR_FREE(vm->def->tpms[i]->data.emulator.source.data.file.path);
+ vm->def->tpms[i]->data.emulator.source.data.file.path = g_strdup("/dev/test");
+ vm->def->tpms[i]->data.emulator.source.type = VIR_DOMAIN_CHR_TYPE_FILE;
}
for (i = 0; i < vm->def->nvideos; i++) {