A TPM Proxy device can coexist with a regular TPM. The TPM Proxy is also always a 'passthrough' device of the 'spapr-tpm-proxy' model. This patch adds a pointer to this device in the domain definition called 'tpmproxy'. This pointer is handled like the existing 'tpm' pointer of the VIR_DOMAIN_TPM_TYPE_PASSTHROUGH type. Cgroup, DAC/SELinux and qemu validation code was adapted to handle this new domain device. XML functions to parse and format this new device from/to XML will be added in the next patch, together with the logic that will guarantee the assumptions made in the first paragraph. Signed-off-by: Daniel Henrique Barboza <danielhb413@xxxxxxxxx> --- src/conf/domain_audit.c | 3 +++ src/conf/domain_conf.c | 18 ++++++++++++++++++ src/conf/domain_conf.h | 2 ++ src/qemu/qemu_cgroup.c | 12 +++++++++--- src/qemu/qemu_domain.c | 9 +++++---- src/qemu/qemu_validate.c | 12 ++++++++++++ src/security/security_dac.c | 14 ++++++++++++++ src/security/security_selinux.c | 11 +++++++++++ 8 files changed, 74 insertions(+), 7 deletions(-) diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c index 1b0abb21a0..4575f66e45 100644 --- a/src/conf/domain_audit.c +++ b/src/conf/domain_audit.c @@ -824,6 +824,9 @@ virDomainAuditStart(virDomainObjPtr vm, const char *reason, bool success) if (vm->def->tpm) virDomainAuditTPM(vm, vm->def->tpm, "start", true); + if (vm->def->tpmproxy) + virDomainAuditTPM(vm, vm->def->tpmproxy, "start", true); + for (i = 0; i < vm->def->nshmems; i++) virDomainAuditShmem(vm, vm->def->shmems[i], "start", true); diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index c201fc901d..01a32f62d1 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1165,6 +1165,7 @@ VIR_ENUM_IMPL(virDomainTPMModel, "tpm-tis", "tpm-crb", "tpm-spapr", + "spapr-tpm-proxy", ); VIR_ENUM_IMPL(virDomainTPMBackend, @@ -3480,6 +3481,7 @@ void virDomainDefFree(virDomainDefPtr def) VIR_FREE(def->mems); virDomainTPMDefFree(def->tpm); + virDomainTPMDefFree(def->tpmproxy); for (i = 0; i < def->npanics; i++) virDomainPanicDefFree(def->panics[i]); @@ -4318,6 +4320,12 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def, if ((rc = cb(def, &device, &def->tpm->info, opaque)) != 0) return rc; } + if (def->tpmproxy) { + device.type = VIR_DOMAIN_DEVICE_TPM; + device.data.tpm = def->tpmproxy; + if ((rc = cb(def, &device, &def->tpmproxy->info, opaque)) != 0) + return rc; + } device.type = VIR_DOMAIN_DEVICE_PANIC; for (i = 0; i < def->npanics; i++) { device.data.panic = def->panics[i]; @@ -24344,6 +24352,16 @@ virDomainDefCheckABIStabilityFlags(virDomainDefPtr src, goto error; } + if (src->tpmproxy && dst->tpmproxy) { + if (!virDomainTPMDefCheckABIStability(src->tpmproxy, dst->tpmproxy)) + goto error; + } else if (src->tpmproxy || dst->tpmproxy) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Either both target and source domains or none of " + "them must have TPM Proxy device present")); + goto error; + } + if (src->nmems != dst->nmems) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target domain memory device count %zu " diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index ddc75d8de2..8f178ade34 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1293,6 +1293,7 @@ typedef enum { 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; @@ -2628,6 +2629,7 @@ struct _virDomainDef { virDomainMemballoonDefPtr memballoon; virDomainNVRAMDefPtr nvram; virDomainTPMDefPtr tpm; + virDomainTPMDefPtr tpmproxy; virCPUDefPtr cpu; virSysinfoDefPtr sysinfo; virDomainRedirFilterDefPtr redirfilter; diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index 2e019b64af..2ed4341655 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -333,10 +333,13 @@ qemuSetupChardevCgroupCB(virDomainDefPtr def G_GNUC_UNUSED, static int -qemuSetupTPMCgroup(virDomainObjPtr vm) +qemuSetupTPMCgroup(virDomainObjPtr vm, + virDomainTPMDefPtr dev) { int ret = 0; - virDomainTPMDefPtr dev = vm->def->tpm; + + if (!dev) + return 0; switch (dev->type) { case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: @@ -806,7 +809,10 @@ qemuSetupDevicesCgroup(virDomainObjPtr vm) vm) < 0) return -1; - if (vm->def->tpm && qemuSetupTPMCgroup(vm) < 0) + if (qemuSetupTPMCgroup(vm, vm->def->tpm) < 0) + return -1; + + if (qemuSetupTPMCgroup(vm, vm->def->tpmproxy) < 0) return -1; for (i = 0; i < vm->def->nhostdevs; i++) { diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index a1b250fd0b..a344f8a0e6 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -11574,11 +11574,9 @@ qemuDomainSetupAllChardevs(virQEMUDriverConfigPtr cfg G_GNUC_UNUSED, 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; @@ -11823,7 +11821,10 @@ qemuDomainBuildNamespace(virQEMUDriverConfigPtr cfg, if (qemuDomainSetupAllChardevs(cfg, vm, &data) < 0) goto cleanup; - if (qemuDomainSetupTPM(cfg, vm, &data) < 0) + if (qemuDomainSetupTPM(cfg, vm->def->tpm, &data) < 0) + goto cleanup; + + if (qemuDomainSetupTPM(cfg, vm->def->tpmproxy, &data) < 0) goto cleanup; if (qemuDomainSetupAllGraphics(cfg, vm, &data) < 0) diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 584d1375b8..7210be3532 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -3602,6 +3602,7 @@ qemuValidateDomainDeviceDefTPM(virDomainTPMDef *tpm, case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_TPM_PASSTHROUGH)) goto no_support; + break; case VIR_DOMAIN_TPM_TYPE_EMULATOR: @@ -3623,6 +3624,17 @@ qemuValidateDomainDeviceDefTPM(virDomainTPMDef *tpm, case VIR_DOMAIN_TPM_MODEL_SPAPR: flag = QEMU_CAPS_DEVICE_TPM_SPAPR; break; + case VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY: + if (!ARCH_IS_PPC64(def->os.arch)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("TPM Proxy model %s is only available for " + "PPC64 guests"), + virDomainTPMModelTypeToString(tpm->model)); + return -1; + } + + flag = QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY; + break; case VIR_DOMAIN_TPM_MODEL_LAST: default: virReportEnumRangeError(virDomainTPMModel, tpm->model); diff --git a/src/security/security_dac.c b/src/security/security_dac.c index bdc2d7edf3..e0542d2839 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -1980,6 +1980,13 @@ virSecurityDACRestoreAllLabel(virSecurityManagerPtr mgr, rc = -1; } + if (def->tpmproxy) { + if (virSecurityDACRestoreTPMFileLabel(mgr, + def, + def->tpmproxy) < 0) + rc = -1; + } + if (def->sev) { if (virSecurityDACRestoreSEVLabel(mgr, def) < 0) rc = -1; @@ -2159,6 +2166,13 @@ virSecurityDACSetAllLabel(virSecurityManagerPtr mgr, return -1; } + if (def->tpmproxy) { + if (virSecurityDACSetTPMFileLabel(mgr, + def, + def->tpmproxy) < 0) + return -1; + } + if (def->sev) { if (virSecurityDACSetSEVLabel(mgr, def) < 0) return -1; diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 9a929debe1..e80d43c0a7 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -2763,6 +2763,12 @@ virSecuritySELinuxRestoreAllLabel(virSecurityManagerPtr mgr, rc = -1; } + if (def->tpmproxy) { + if (virSecuritySELinuxRestoreTPMFileLabelInt(mgr, def, + def->tpmproxy) < 0) + rc = -1; + } + struct _virSecuritySELinuxChardevCallbackData chardevData = { .mgr = mgr, .chardevStdioLogd = chardevStdioLogd @@ -3171,6 +3177,11 @@ virSecuritySELinuxSetAllLabel(virSecurityManagerPtr mgr, return -1; } + if (def->tpmproxy) { + if (virSecuritySELinuxSetTPMFileLabel(mgr, def, def->tpmproxy) < 0) + return -1; + } + struct _virSecuritySELinuxChardevCallbackData chardevData = { .mgr = mgr, .chardevStdioLogd = chardevStdioLogd -- 2.26.2