Add support for storing private TPM-related data. The first private data
will be related to the capability of the started swtpm indicating whether
it is capable of migration with a shared storage setup since that requires
support for certain command line flags that were only becoming available
in v0.8.
Signed-off-by: Stefan Berger <stefanb(a)linux.ibm.com>
---
src/conf/domain_conf.c | 63 +++++++++++++++++++++++++++++++++---
src/conf/domain_conf.h | 9 ++++++
src/qemu/qemu_domain.c | 73 ++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_domain.h | 14 ++++++++
4 files changed, 154 insertions(+), 5 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 7dba65cfeb..4178583950 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -3276,6 +3276,22 @@ void virDomainHostdevDefClear(virDomainHostdevDef *def)
}
}
+static virDomainTPMDef *
+virDomainTPMDefNew(virDomainXMLOption *xmlopt)
+{
+ virDomainTPMDef *def;
+
+ def = g_new0(virDomainTPMDef, 1);
+
+ if (xmlopt && xmlopt->privateData.tpmNew &&
+ !(def->privateData = xmlopt->privateData.tpmNew())) {
+ VIR_FREE(def);
+ return NULL;
+ }
+
+ return def;
+}
+
void virDomainTPMDefFree(virDomainTPMDef *def)
{
if (!def)
@@ -3296,6 +3312,7 @@ void virDomainTPMDefFree(virDomainTPMDef *def)
}
virDomainDeviceInfoClear(&def->info);
+ virObjectUnref(def->privateData);
g_free(def);
}
@@ -10238,7 +10255,8 @@ virDomainTPMDefParseXML(virDomainXMLOption *xmlopt,
g_autofree xmlNodePtr *nodes = NULL;
int bank;
- def = g_new0(virDomainTPMDef, 1);
+ if (!(def = virDomainTPMDefNew(xmlopt)))
+ return NULL;
if (virXMLPropEnum(node, "model",
virDomainTPMModelTypeFromString,
@@ -10329,6 +10347,14 @@ virDomainTPMDefParseXML(virDomainXMLOption *xmlopt,
if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags) <
0)
goto error;
+ if (flags & VIR_DOMAIN_DEF_PARSE_STATUS &&
+ xmlopt && xmlopt->privateData.tpmParse) {
+ if ((ctxt->node = virXPathNode("./privateData", ctxt))) {
+ if (xmlopt->privateData.tpmParse(ctxt, def) < 0)
+ goto error;
+ }
+ }
+
return def;
error:
@@ -24049,10 +24075,32 @@ virDomainSoundCodecDefFormat(virBuffer *buf,
return 0;
}
-static void
+static int
+virDomainTPMDefFormatPrivateData(virBuffer *buf,
+ const virDomainTPMDef *tpm,
+ unsigned int flags,
+ virDomainXMLOption *xmlopt)
+{
+ g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
+
+ if (!(flags & VIR_DOMAIN_DEF_FORMAT_STATUS) ||
+ !xmlopt ||
+ !xmlopt->privateData.tpmFormat)
+ return 0;
+
+ if (xmlopt->privateData.tpmFormat(tpm, &childBuf) < 0)
+ return -1;
+
+ virXMLFormatElement(buf, "privateData", NULL, &childBuf);
+ return 0;
+}
+
+
+static int
virDomainTPMDefFormat(virBuffer *buf,
const virDomainTPMDef *def,
- unsigned int flags)
+ unsigned int flags,
+ virDomainXMLOption *xmlopt)
{
g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
@@ -24101,8 +24149,12 @@ virDomainTPMDefFormat(virBuffer *buf,
virXMLFormatElement(&childBuf, "backend", &backendAttrBuf,
&backendChildBuf);
virDomainDeviceInfoFormat(&childBuf, &def->info, flags);
+ if (virDomainTPMDefFormatPrivateData(&childBuf, def, flags, xmlopt) < 0)
+ return -1;
virXMLFormatElement(buf, "tpm", &attrBuf, &childBuf);
+
+ return 0;
}
@@ -27188,7 +27240,8 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def,
}
for (n = 0; n < def->ntpms; n++) {
- virDomainTPMDefFormat(buf, def->tpms[n], flags);
+ if (virDomainTPMDefFormat(buf, def->tpms[n], flags, xmlopt) < 0)
+ return -1;
}
for (n = 0; n < def->ngraphics; n++) {
@@ -28454,7 +28507,7 @@ virDomainDeviceDefCopy(virDomainDeviceDef *src,
rc = virDomainChrDefFormat(&buf, src->data.chr, flags);
break;
case VIR_DOMAIN_DEVICE_TPM:
- virDomainTPMDefFormat(&buf, src->data.tpm, flags);
+ virDomainTPMDefFormat(&buf, src->data.tpm, flags, xmlopt);
rc = 0;
break;
case VIR_DOMAIN_DEVICE_PANIC:
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 8f8a54bc41..82f71f8853 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1445,6 +1445,8 @@ typedef enum {
#define VIR_DOMAIN_TPM_DEFAULT_DEVICE "/dev/tpm0"
struct _virDomainTPMDef {
+ virObject *privateData;
+
virDomainTPMModel model;
virDomainTPMBackendType type;
virDomainDeviceInfo info;
@@ -3248,6 +3250,10 @@ typedef int
(*virDomainXMLPrivateDataStorageSourceParseFunc)(xmlXPathContextPtr
typedef int (*virDomainXMLPrivateDataStorageSourceFormatFunc)(virStorageSource *src,
virBuffer *buf);
+typedef int (*virDomainXMLPrivateDataTPMParseFunc)(xmlXPathContextPtr ctxt,
+ virDomainTPMDef *disk);
+typedef int (*virDomainXMLPrivateDataTPMFormatFunc)(const virDomainTPMDef *tpm,
+ virBuffer *buf);
struct _virDomainXMLPrivateDataCallbacks {
virDomainXMLPrivateDataAllocFunc alloc;
@@ -3264,6 +3270,9 @@ struct _virDomainXMLPrivateDataCallbacks {
virDomainXMLPrivateDataNewFunc networkNew;
virDomainXMLPrivateDataNewFunc videoNew;
virDomainXMLPrivateDataNewFunc fsNew;
+ virDomainXMLPrivateDataTPMParseFunc tpmParse;
+ virDomainXMLPrivateDataTPMFormatFunc tpmFormat;
+ virDomainXMLPrivateDataNewFunc tpmNew;
virDomainXMLPrivateDataFormatFunc format;
virDomainXMLPrivateDataParseFunc parse;
/* following function shall return a pointer which will be used as the
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 9ef6c8bb64..41333f1725 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1139,6 +1139,76 @@ qemuDomainVideoPrivateDispose(void *obj)
}
+static virClass *qemuDomainTPMPrivateClass;
+static void qemuDomainTPMPrivateDispose(void *obj);
+
+
+static int
+qemuDomainTPMPrivateOnceInit(void)
+{
+ if (!VIR_CLASS_NEW(qemuDomainTPMPrivate, virClassForObject()))
+ return -1;
+
+ return 0;
+}
+
+VIR_ONCE_GLOBAL_INIT(qemuDomainTPMPrivate);
+
+
+static virObject *
+qemuDomainTPMPrivateNew(void)
+{
+ qemuDomainTPMPrivate *priv;
+
+ if (qemuDomainTPMPrivateInitialize() < 0)
+ return NULL;
+
+ if (!(priv = virObjectNew(qemuDomainTPMPrivateClass)))
+ return NULL;
+
+ return (virObject *) priv;
+}
+
+
+static void
+qemuDomainTPMPrivateDispose(void *obj G_GNUC_UNUSED)
+{
+}
+
+
+static int
+qemuDomainTPMPrivateParse(xmlXPathContextPtr ctxt,
+ virDomainTPMDef *tpm)
+{
+ qemuDomainTPMPrivate *priv = QEMU_DOMAIN_TPM_PRIVATE(tpm);
+
+ priv->swtpm.can_migrate_shared_storage =
+ virXPathBoolean("string(./swtpm/@can_migrate_shared_storage)", ctxt);
+
+ return 0;
+}
+
+
+static int
+qemuDomainTPMPrivateFormat(const virDomainTPMDef *tpm,
+ virBuffer *buf)
+{
+ qemuDomainTPMPrivate *priv = QEMU_DOMAIN_TPM_PRIVATE(tpm);
+
+ switch (tpm->type) {
+ case VIR_DOMAIN_TPM_TYPE_EMULATOR:
+ if (priv->swtpm.can_migrate_shared_storage)
+ virBufferAddLit(buf, "<swtpm
can_migrate_shared_storage='yes'/>\n");
+ break;
+
+ case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
+ case VIR_DOMAIN_TPM_TYPE_LAST:
+ }
+
+ return 0;
+}
+
+
/* qemuDomainSecretInfoSetup:
* @priv: pointer to domain private object
* @alias: alias of the secret
@@ -3215,6 +3285,9 @@ virDomainXMLPrivateDataCallbacks virQEMUDriverPrivateDataCallbacks =
{
.graphicsNew = qemuDomainGraphicsPrivateNew,
.networkNew = qemuDomainNetworkPrivateNew,
.videoNew = qemuDomainVideoPrivateNew,
+ .tpmNew = qemuDomainTPMPrivateNew,
+ .tpmParse = qemuDomainTPMPrivateParse,
+ .tpmFormat = qemuDomainTPMPrivateFormat,
.parse = qemuDomainObjPrivateXMLParse,
.format = qemuDomainObjPrivateXMLFormat,
.getParseOpaque = qemuDomainObjPrivateXMLGetParseOpaque,
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 2bbd492d62..919ce16097 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -414,6 +414,20 @@ struct _qemuDomainNetworkPrivate {
qemuFDPass *vdpafd;
};
+
+#define QEMU_DOMAIN_TPM_PRIVATE(dev) \
+ ((qemuDomainTPMPrivate *) (dev)->privateData)
+
+typedef struct _qemuDomainTPMPrivate qemuDomainTPMPrivate;
+struct _qemuDomainTPMPrivate {
+ virObject parent;
+
+ struct {
+ bool can_migrate_shared_storage;
+ } swtpm;
+};
+
+
void
qemuDomainNetworkPrivateClearFDs(qemuDomainNetworkPrivate *priv);
--
2.37.3