mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-21 20:15:17 +00:00
qemu: tpm: Add support for storing private TPM-related data
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@linux.ibm.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
68103e9daf
commit
5597476e40
@ -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);
|
||||
}
|
||||
|
||||
@ -10240,7 +10257,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,
|
||||
@ -10331,6 +10349,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:
|
||||
@ -23921,10 +23947,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);
|
||||
@ -23973,8 +24021,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;
|
||||
}
|
||||
|
||||
|
||||
@ -27060,7 +27112,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++) {
|
||||
@ -28326,7 +28379,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:
|
||||
|
@ -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
|
||||
|
@ -1138,6 +1138,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
|
||||
@ -3212,6 +3282,9 @@ virDomainXMLPrivateDataCallbacks virQEMUDriverPrivateDataCallbacks = {
|
||||
.graphicsNew = qemuDomainGraphicsPrivateNew,
|
||||
.networkNew = qemuDomainNetworkPrivateNew,
|
||||
.videoNew = qemuDomainVideoPrivateNew,
|
||||
.tpmNew = qemuDomainTPMPrivateNew,
|
||||
.tpmParse = qemuDomainTPMPrivateParse,
|
||||
.tpmFormat = qemuDomainTPMPrivateFormat,
|
||||
.parse = qemuDomainObjPrivateXMLParse,
|
||||
.format = qemuDomainObjPrivateXMLFormat,
|
||||
.getParseOpaque = qemuDomainObjPrivateXMLGetParseOpaque,
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user