From: Daniel P. Berrangé Date: Thu, 20 Nov 2025 11:24:31 +0000 (-0500) Subject: qemu: correctly detect working TDX support X-Git-Tag: v11.10.0-rc1~30 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=62d14ba496634d5a98f7becc3875b9311cb38931;p=thirdparty%2Flibvirt.git qemu: correctly detect working TDX support Querying existence of the 'tdx-guest' type merely tells us whether QEMU has been compiled with TDX support, not whether it is usable on the host. Thus QEMU was incorrectly reporting ... tdx on every platform with new enough QEMU. Unfortunately an earlier patch for a 'query-tdx-capabilities' QMP command in QEMU was dropped, so there is no way to ask QEMU whether it can launch a TDX guest. Libvirt must directly query the KVM device and ask for supported VM types. Reviewed-by: Peter Krempa Signed-off-by: Daniel P. Berrangé --- diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 4050d5ccc6..02ab663f3b 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -54,11 +54,17 @@ # include # include #endif +#ifdef WITH_LINUX_KVM_H +# include +# include +#endif #define VIR_FROM_THIS VIR_FROM_QEMU VIR_LOG_INIT("qemu.qemu_capabilities"); +#define KVM_DEVICE "/dev/kvm" + /* While not public, these strings must not change. They * are used in domain status files which are read on * daemon restarts @@ -3686,6 +3692,50 @@ virQEMUCapsProbeQMPSEVCapabilities(virQEMUCaps *qemuCaps, } +bool +virQEMUCapsKVMSupportsVMTypeTDX(void) +{ +#if defined(KVM_CAP_VM_TYPES) && defined(KVM_X86_TDX_VM) + VIR_AUTOCLOSE kvmfd = -1; + int types; + + if (!virFileExists(KVM_DEVICE)) + return false; + + if ((kvmfd = open(KVM_DEVICE, O_RDONLY)) < 0) { + VIR_DEBUG("Unable to open %s, cannot check TDX", KVM_DEVICE); + return false; + } + + if ((types = ioctl(kvmfd, KVM_CHECK_EXTENSION, KVM_CAP_VM_TYPES)) < 0) + types = 0; + + VIR_DEBUG("KVM VM types: 0x%x", types); + + return !!(types & (1 << KVM_X86_TDX_VM)); +#else + VIR_DEBUG("KVM not compiled"); + return false; +#endif +} + + +/* This ought to be virQEMUCapsProbeQMPTDXCapabilities, + * but there is no 'query-tdx-capabilities' command + * available in QEMU currently. If one arrives, rename + * this method & switch to using that on new enough QEMU + */ +static void +virQEMUCapsProbeTDXCapabilities(virQEMUCaps *qemuCaps) +{ + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_TDX_GUEST)) + return; + + if (!virQEMUCapsKVMSupportsVMTypeTDX()) + virQEMUCapsClear(qemuCaps, QEMU_CAPS_TDX_GUEST); +} + + static int virQEMUCapsProbeQMPSGXCapabilities(virQEMUCaps *qemuCaps, qemuMonitor *mon) @@ -5910,6 +5960,7 @@ virQEMUCapsInitQMPMonitor(virQEMUCaps *qemuCaps, return -1; if (virQEMUCapsProbeQMPSGXCapabilities(qemuCaps, mon) < 0) return -1; + virQEMUCapsProbeTDXCapabilities(qemuCaps); virQEMUCapsInitProcessCaps(qemuCaps); diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 2b519be3a8..f180844e66 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -980,3 +980,6 @@ int virQEMUCapsProbeQMPMachineTypes(virQEMUCaps *qemuCaps, virDomainVirtType virtType, qemuMonitor *mon); + +bool +virQEMUCapsKVMSupportsVMTypeTDX(void) ATTRIBUTE_MOCKABLE; diff --git a/tests/domaincapsmock.c b/tests/domaincapsmock.c index cb6e98dbb8..7bece6c8c1 100644 --- a/tests/domaincapsmock.c +++ b/tests/domaincapsmock.c @@ -48,6 +48,12 @@ virHostCPUGetPhysAddrSize(const virArch hostArch, } #if WITH_QEMU +bool +virQEMUCapsKVMSupportsVMTypeTDX(void) +{ + return true; +} + static bool (*real_virQEMUCapsGetKVMSupportsSecureGuest)(virQEMUCaps *qemuCaps); bool