qemu: add external backend for tpm

Introduce a new backend type 'external' for connecting to a swtpm daemon
not managed by libvirtd.

Mostly in one commit, thanks to -Wswitch and the way we generate
capabilities.

https://bugzilla.redhat.com/show_bug.cgi?id=2063723

Signed-off-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Ján Tomko 2022-10-17 15:20:24 +02:00
parent 443eb2330d
commit ad3f33a992
61 changed files with 202 additions and 2 deletions

View File

@ -556,6 +556,17 @@ virDomainAuditTPM(virDomainObj *vm, virDomainTPMDef *tpm,
"virt=%s resrc=tpm-emulator reason=%s %s uuid=%s %s",
virt, reason, vmname, uuidstr, device);
break;
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
path = tpm->data.external.source->data.nix.path;
if (!(device = virAuditEncode("device", VIR_AUDIT_STR(path)))) {
VIR_WARN("OOM while encoding audit message");
goto cleanup;
}
VIR_AUDIT(VIR_AUDIT_RECORD_RESOURCE, success,
"virt=%s resrc=tpm-external reason=%s %s uuid=%s %s",
virt, reason, vmname, uuidstr, device);
break;
case VIR_DOMAIN_TPM_TYPE_LAST:
default:
break;

View File

@ -1281,6 +1281,7 @@ VIR_ENUM_IMPL(virDomainTPMBackend,
VIR_DOMAIN_TPM_TYPE_LAST,
"passthrough",
"emulator",
"external",
);
VIR_ENUM_IMPL(virDomainTPMVersion,
@ -3309,6 +3310,9 @@ void virDomainTPMDefFree(virDomainTPMDef *def)
g_free(def->data.emulator.logfile);
virBitmapFree(def->data.emulator.activePcrBanks);
break;
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
virObjectUnref(def->data.external.source);
break;
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
@ -10257,6 +10261,7 @@ virDomainTPMDefParseXML(virDomainXMLOption *xmlopt,
g_autofree char *persistent_state = NULL;
g_autofree xmlNodePtr *backends = NULL;
g_autofree xmlNodePtr *nodes = NULL;
g_autofree char *type = NULL;
int bank;
if (!(def = virDomainTPMDefNew(xmlopt)))
@ -10344,6 +10349,28 @@ virDomainTPMDefParseXML(virDomainXMLOption *xmlopt,
virBitmapSetBitExpand(def->data.emulator.activePcrBanks, bank);
}
break;
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
if (!(type = virXPathString("string(./backend/source/@type)", ctxt))) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("missing external TPM backend type"));
goto error;
}
if (!(def->data.external.source = virDomainChrSourceDefNew(xmlopt)))
goto error;
def->data.external.source->type = virDomainChrTypeFromString(type);
if (def->data.external.source->type < 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("unknown backend type '%s' for external TPM"),
type);
goto error;
}
if (virDomainChrSourceDefParseXML(def->data.external.source,
backends[0], flags, NULL, ctxt) < 0)
goto error;
break;
case VIR_DOMAIN_TPM_TYPE_LAST:
goto error;
}
@ -20443,6 +20470,7 @@ virDomainTPMDefCheckABIStability(virDomainTPMDef *src,
break;
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
@ -24047,6 +24075,13 @@ virDomainTPMDefFormat(virBuffer *buf,
virXMLFormatElement(&backendChildBuf, "active_pcr_banks", NULL, &activePcrBanksBuf);
}
break;
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
if (def->data.external.source->type == VIR_DOMAIN_CHR_TYPE_UNIX) {
virBufferAddLit(&backendChildBuf, "<source type='unix' mode='connect'");
virBufferEscapeString(&backendChildBuf, " path='%s'/>\n",
def->data.external.source->data.nix.path);
}
break;
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}

View File

@ -1421,6 +1421,7 @@ typedef enum {
typedef enum {
VIR_DOMAIN_TPM_TYPE_PASSTHROUGH,
VIR_DOMAIN_TPM_TYPE_EMULATOR,
VIR_DOMAIN_TPM_TYPE_EXTERNAL,
VIR_DOMAIN_TPM_TYPE_LAST
} virDomainTPMBackendType;
@ -1464,6 +1465,9 @@ struct _virDomainTPMDef {
bool persistent_state;
virBitmap *activePcrBanks;
} emulator;
struct {
virDomainChrSourceDef *source;
} external;
} data;
};

View File

@ -2727,6 +2727,24 @@ virDomainTPMDevValidate(const virDomainTPMDef *tpm)
break;
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
break;
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
if (tpm->data.external.source->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("only source type 'unix' is supported for external TPM device"));
return -1;
}
if (tpm->data.external.source->data.nix.listen) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("only 'client' mode is supported for external TPM device"));
return -1;
}
if (tpm->data.external.source->data.nix.path == NULL) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("missing socket path for external TPM device"));
return -1;
}
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}

View File

@ -5583,6 +5583,12 @@
</attribute>
</optional>
</group>
<group>
<attribute name="type">
<value>external</value>
</attribute>
<ref name="tpm-external-source"/>
</group>
</choice>
<optional>
<attribute name="version">
@ -5607,6 +5613,22 @@
</optional>
</define>
<define name="tpm-external-source">
<optional>
<element name="source">
<attribute name="type">
<value>unix</value>
</attribute>
<attribute name="path">
<ref name="filePath"/>
</attribute>
<attribute name="mode">
<value>connect</value>
</attribute>
</element>
</optional>
</define>
<define name="tpm-backend-emulator-encryption">
<optional>
<element name="encryption">

View File

@ -6471,8 +6471,10 @@ virQEMUCapsFillDomainDeviceTPMCaps(virQEMUCaps *qemuCaps,
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_TPM_PASSTHROUGH))
VIR_DOMAIN_CAPS_ENUM_SET(tpm->backendModel, VIR_DOMAIN_TPM_TYPE_PASSTHROUGH);
if (virTPMHasSwtpm()) {
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_TPM_EMULATOR))
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_TPM_EMULATOR)) {
VIR_DOMAIN_CAPS_ENUM_SET(tpm->backendModel, VIR_DOMAIN_TPM_TYPE_EMULATOR);
VIR_DOMAIN_CAPS_ENUM_SET(tpm->backendModel, VIR_DOMAIN_TPM_TYPE_EXTERNAL);
}
if (virTPMSwtpmSetupCapsGet(VIR_TPM_SWTPM_SETUP_FEATURE_TPM_1_2)) {
VIR_DOMAIN_CAPS_ENUM_SET(tpm->backendVersion, VIR_DOMAIN_TPM_VERSION_1_2);
tpm->backendVersion.report = true;

View File

@ -397,6 +397,7 @@ qemuSetupTPMCgroup(virDomainObj *vm,
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
return qemuSetupChrSourceCgroup(vm, dev->data.passthrough.source);
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}

View File

@ -9241,7 +9241,10 @@ qemuBuildTPMBackendStr(virDomainTPMDef *tpm,
{
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
virBufferAsprintf(&buf, "%s", virDomainTPMBackendTypeToString(tpm->type));
if (tpm->type == VIR_DOMAIN_TPM_TYPE_EXTERNAL)
virBufferAddLit(&buf, "emulator");
else
virBufferAsprintf(&buf, "%s", virDomainTPMBackendTypeToString(tpm->type));
virBufferAsprintf(&buf, ",id=tpm-%s", tpm->info.alias);
switch (tpm->type) {
@ -9253,6 +9256,7 @@ qemuBuildTPMBackendStr(virDomainTPMDef *tpm,
virQEMUBuildBufferEscapeComma(&buf, qemuFDPassGetPath(passcancel));
break;
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
virBufferAddLit(&buf, ",chardev=chrtpm");
break;
case VIR_DOMAIN_TPM_TYPE_LAST:
@ -9295,6 +9299,11 @@ qemuBuildTPMCommandLine(virCommand *cmd,
return -1;
break;
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
if (qemuBuildChardevCommand(cmd, tpm->data.external.source, "chrtpm", priv->qemuCaps) < 0)
return -1;
break;
case VIR_DOMAIN_TPM_TYPE_LAST:
virReportEnumRangeError(virDomainTPMBackendType, tpm->type);
return -1;

View File

@ -1201,6 +1201,7 @@ qemuDomainTPMPrivateFormat(const virDomainTPMDef *tpm,
break;
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
@ -11753,6 +11754,9 @@ qemuDomainDeviceBackendChardevForeachOne(virDomainDeviceDef *dev,
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
return cb(dev, dev->data.tpm->data.emulator.source, opaque);
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
return cb(dev, dev->data.tpm->data.external.source, opaque);
case VIR_DOMAIN_TPM_TYPE_LAST:
return 0;
}

View File

@ -457,6 +457,7 @@ qemuDomainSetupTPM(virDomainTPMDef *dev,
break;
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
/* nada */
break;

View File

@ -1028,6 +1028,7 @@ qemuTPMHasSharedStorage(virDomainDef *def)
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
return virFileIsSharedFS(tpm->data.emulator.storagepath) == 1;
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
@ -1048,6 +1049,7 @@ qemuTPMCanMigrateSharedStorage(virDomainDef *def)
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
return QEMU_DOMAIN_TPM_PRIVATE(tpm)->swtpm.can_migrate_shared_storage;
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}

View File

@ -1699,6 +1699,7 @@ virSecurityDACSetTPMFileLabel(virSecurityManager *mgr,
tpm->data.emulator.source,
false, false);
break;
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
@ -1722,6 +1723,7 @@ virSecurityDACRestoreTPMFileLabel(virSecurityManager *mgr,
break;
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
/* swtpm will have removed the Unix socket upon termination */
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}

View File

@ -1660,6 +1660,7 @@ virSecuritySELinuxSetTPMFileLabel(virSecurityManager *mgr,
if (rc < 0)
return -1;
break;
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}
@ -1695,6 +1696,7 @@ virSecuritySELinuxRestoreTPMFileLabelInt(virSecurityManager *mgr,
break;
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
/* swtpm will have removed the Unix socket upon termination */
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
case VIR_DOMAIN_TPM_TYPE_LAST:
break;
}

View File

@ -211,6 +211,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -226,6 +226,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -211,6 +211,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -213,6 +213,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -228,6 +228,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -172,6 +172,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -170,6 +170,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -137,6 +137,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -213,6 +213,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -214,6 +214,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -228,6 +228,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -214,6 +214,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -214,6 +214,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -228,6 +228,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -172,6 +172,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -170,6 +170,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -137,6 +137,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -214,6 +214,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -215,6 +215,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -230,6 +230,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -173,6 +173,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -171,6 +171,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -215,6 +215,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -216,6 +216,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -230,6 +230,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -216,6 +216,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -216,6 +216,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -232,6 +232,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -175,6 +175,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -173,6 +173,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -135,6 +135,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -216,6 +216,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>1.2</value>

View File

@ -218,6 +218,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>

View File

@ -234,6 +234,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>

View File

@ -175,6 +175,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>

View File

@ -173,6 +173,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>

View File

@ -137,6 +137,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>

View File

@ -218,6 +218,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>

View File

@ -217,6 +217,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>

View File

@ -232,6 +232,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>

View File

@ -130,6 +130,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>

View File

@ -217,6 +217,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>

View File

@ -222,6 +222,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>

View File

@ -221,6 +221,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>

View File

@ -222,6 +222,7 @@
<enum name='backendModel'>
<value>passthrough</value>
<value>emulator</value>
<value>external</value>
</enum>
<enum name='backendVersion'>
<value>2.0</value>

View File

@ -0,0 +1,40 @@
<domain type='qemu'>
<name>TPM-VM</name>
<uuid>11d7cd22-da89-3094-6212-079a48a309a1</uuid>
<memory unit='KiB'>2097152</memory>
<currentMemory unit='KiB'>512288</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='x86_64' machine='pc-i440fx-2.12'>hvm</type>
<boot dev='hd'/>
<bootmenu enable='yes'/>
</os>
<features>
<acpi/>
</features>
<cpu mode='custom' match='exact' check='none'>
<model fallback='forbid'>qemu64</model>
</cpu>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<controller type='usb' index='0' model='piix3-uhci'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<tpm model='tpm-tis'>
<backend type='external'>
<source type='unix' mode='connect' path='/tmp/path.sock'/>
</backend>
</tpm>
<audio id='1' type='none'/>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</memballoon>
</devices>
</domain>

View File

@ -0,0 +1 @@
../qemuxml2argvdata/tpm-external.xml

View File

@ -744,6 +744,7 @@ mymain(void)
DO_TEST_CAPS_LATEST("tpm-emulator-tpm2-enc");
DO_TEST_CAPS_LATEST("tpm-emulator-tpm2-pstate");
DO_TEST_CAPS_ARCH_LATEST("aarch64-tpm", "aarch64");
DO_TEST_CAPS_LATEST("tpm-external");
DO_TEST_NOCAPS("metadata");
DO_TEST_NOCAPS("metadata-duplicate");