Add a firmware descriptor support for TDVF, then libvirt can auto match TDVF fimware with td-guest. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@xxxxxxxxx> --- docs/schemas/domaincommon.rng | 1 + src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_firmware.c | 101 +++++++++++++++++++++++++++++++++- src/qemu/qemu_validate.c | 7 +++ 4 files changed, 108 insertions(+), 3 deletions(-) diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 9d0b51ee12..8232025bf7 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -275,6 +275,7 @@ <choice> <value>bios</value> <value>efi</value> + <value>generic</value> </choice> </attribute> </optional> diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index d3c30a17e7..a01d4c26db 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -5934,6 +5934,8 @@ virQEMUCapsFillDomainOSCaps(virDomainCapsOS *os, VIR_DOMAIN_CAPS_ENUM_SET(os->firmware, VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS); if (autoFirmwares & (1ULL << VIR_DOMAIN_OS_DEF_FIRMWARE_EFI)) VIR_DOMAIN_CAPS_ENUM_SET(os->firmware, VIR_DOMAIN_OS_DEF_FIRMWARE_EFI); + if (autoFirmwares & (1ULL << VIR_DOMAIN_OS_DEF_FIRMWARE_GENERIC)) + VIR_DOMAIN_CAPS_ENUM_SET(os->firmware, VIR_DOMAIN_OS_DEF_FIRMWARE_GENERIC); if (virQEMUCapsFillDomainLoaderCaps(capsLoader, secure, firmwaresAlt ? firmwaresAlt : firmwares, diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index e144b36f94..28e006eb82 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -84,12 +84,18 @@ struct _qemuFirmwareMappingMemory { char *filename; }; +typedef struct _qemuFirmwareMappingGeneric qemuFirmwareMappingGeneric; +struct _qemuFirmwareMappingGeneric { + char *filename; +}; + typedef enum { QEMU_FIRMWARE_DEVICE_NONE = 0, QEMU_FIRMWARE_DEVICE_FLASH, QEMU_FIRMWARE_DEVICE_KERNEL, QEMU_FIRMWARE_DEVICE_MEMORY, + QEMU_FIRMWARE_DEVICE_GENERIC, QEMU_FIRMWARE_DEVICE_LAST } qemuFirmwareDevice; @@ -101,6 +107,7 @@ VIR_ENUM_IMPL(qemuFirmwareDevice, "flash", "kernel", "memory", + "generic", ); @@ -112,6 +119,7 @@ struct _qemuFirmwareMapping { qemuFirmwareMappingFlash flash; qemuFirmwareMappingKernel kernel; qemuFirmwareMappingMemory memory; + qemuFirmwareMappingGeneric generic; } data; }; @@ -135,6 +143,7 @@ typedef enum { QEMU_FIRMWARE_FEATURE_SECURE_BOOT, QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC, QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC, + QEMU_FIRMWARE_FEATURE_INTEL_TDX, QEMU_FIRMWARE_FEATURE_LAST } qemuFirmwareFeature; @@ -151,7 +160,8 @@ VIR_ENUM_IMPL(qemuFirmwareFeature, "requires-smm", "secure-boot", "verbose-dynamic", - "verbose-static" + "verbose-static", + "intel-tdx" ); @@ -213,6 +223,13 @@ qemuFirmwareMappingMemoryFreeContent(qemuFirmwareMappingMemory *memory) } +static void +qemuFirmwareMappingGenericFreeContent(qemuFirmwareMappingGeneric *generic) +{ + g_free(generic->filename); +} + + static void qemuFirmwareMappingFreeContent(qemuFirmwareMapping *mapping) { @@ -226,6 +243,9 @@ qemuFirmwareMappingFreeContent(qemuFirmwareMapping *mapping) case QEMU_FIRMWARE_DEVICE_MEMORY: qemuFirmwareMappingMemoryFreeContent(&mapping->data.memory); break; + case QEMU_FIRMWARE_DEVICE_GENERIC: + qemuFirmwareMappingGenericFreeContent(&mapping->data.generic); + break; case QEMU_FIRMWARE_DEVICE_NONE: case QEMU_FIRMWARE_DEVICE_LAST: break; @@ -424,6 +444,25 @@ qemuFirmwareMappingMemoryParse(const char *path, } +static int +qemuFirmwareMappingGenericParse(const char *path, + virJSONValue *doc, + qemuFirmwareMappingGeneric *generic) +{ + const char *filename; + + if (!(filename = virJSONValueObjectGetString(doc, "filename"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("missing 'filename' in '%s'"), + path); + } + + generic->filename = g_strdup(filename); + + return 0; +} + + static int qemuFirmwareMappingParse(const char *path, virJSONValue *doc, @@ -469,6 +508,10 @@ qemuFirmwareMappingParse(const char *path, if (qemuFirmwareMappingMemoryParse(path, mapping, &fw->mapping.data.memory) < 0) return -1; break; + case QEMU_FIRMWARE_DEVICE_GENERIC: + if (qemuFirmwareMappingGenericParse(path, mapping, &fw->mapping.data.generic) < 0) + return -1; + break; case QEMU_FIRMWARE_DEVICE_NONE: case QEMU_FIRMWARE_DEVICE_LAST: @@ -740,6 +783,19 @@ qemuFirmwareMappingMemoryFormat(virJSONValue *mapping, } +static int +qemuFirmwareMappingGenericFormat(virJSONValue *mapping, + qemuFirmwareMappingGeneric *generic) +{ + if (virJSONValueObjectAppendString(mapping, + "filename", + generic->filename) < 0) + return -1; + + return 0; +} + + static int qemuFirmwareMappingFormat(virJSONValue *doc, qemuFirmware *fw) @@ -764,6 +820,10 @@ qemuFirmwareMappingFormat(virJSONValue *doc, if (qemuFirmwareMappingMemoryFormat(mapping, &fw->mapping.data.memory) < 0) return -1; break; + case QEMU_FIRMWARE_DEVICE_GENERIC: + if (qemuFirmwareMappingGenericFormat(mapping, &fw->mapping.data.generic) < 0) + return -1; + break; case QEMU_FIRMWARE_DEVICE_NONE: case QEMU_FIRMWARE_DEVICE_LAST: @@ -905,6 +965,7 @@ qemuFirmwareOSInterfaceTypeFromOsDefFirmware(int fw) case VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS: return QEMU_FIRMWARE_OS_INTERFACE_BIOS; case VIR_DOMAIN_OS_DEF_FIRMWARE_EFI: + case VIR_DOMAIN_OS_DEF_FIRMWARE_GENERIC: return QEMU_FIRMWARE_OS_INTERFACE_UEFI; case VIR_DOMAIN_OS_DEF_FIRMWARE_NONE: case VIR_DOMAIN_OS_DEF_FIRMWARE_LAST: @@ -932,6 +993,7 @@ qemuFirmwareMatchDomain(const virDomainDef *def, bool supportsSEVES = false; bool supportsSecureBoot = false; bool hasEnrolledKeys = false; + bool supportsTDX = false; int reqSecureBoot; int reqEnrolledKeys; @@ -995,6 +1057,10 @@ qemuFirmwareMatchDomain(const virDomainDef *def, hasEnrolledKeys = true; break; + case QEMU_FIRMWARE_FEATURE_INTEL_TDX: + supportsTDX = true; + break; + case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC: case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC: case QEMU_FIRMWARE_FEATURE_NONE: @@ -1069,8 +1135,14 @@ qemuFirmwareMatchDomain(const virDomainDef *def, return false; } break; - case VIR_DOMAIN_LAUNCH_SECURITY_PV: case VIR_DOMAIN_LAUNCH_SECURITY_TDX: + if (!supportsTDX) { + VIR_DEBUG("Domain requires TDX, firmware '%s' doesn't support it", + path); + return false; + } + break; + case VIR_DOMAIN_LAUNCH_SECURITY_PV: case VIR_DOMAIN_LAUNCH_SECURITY_NONE: break; case VIR_DOMAIN_LAUNCH_SECURITY_LAST: @@ -1093,6 +1165,7 @@ qemuFirmwareEnableFeatures(virQEMUDriver *driver, const qemuFirmwareMappingFlash *flash = &fw->mapping.data.flash; const qemuFirmwareMappingKernel *kernel = &fw->mapping.data.kernel; const qemuFirmwareMappingMemory *memory = &fw->mapping.data.memory; + const qemuFirmwareMappingGeneric *generic = &fw->mapping.data.generic; size_t i; switch (fw->mapping.device) { @@ -1149,6 +1222,17 @@ qemuFirmwareEnableFeatures(virQEMUDriver *driver, def->os.loader->path); break; + case QEMU_FIRMWARE_DEVICE_GENERIC: + if (!def->os.loader) + def->os.loader = g_new0(virDomainLoaderDef, 1); + + def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_GENERIC; + def->os.loader->path = g_strdup(generic->filename); + + VIR_DEBUG("decided on loader '%s'", + def->os.loader->path); + break; + case QEMU_FIRMWARE_DEVICE_NONE: case QEMU_FIRMWARE_DEVICE_LAST: break; @@ -1183,6 +1267,7 @@ qemuFirmwareEnableFeatures(virQEMUDriver *driver, case QEMU_FIRMWARE_FEATURE_SECURE_BOOT: case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC: case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC: + case QEMU_FIRMWARE_FEATURE_INTEL_TDX: case QEMU_FIRMWARE_FEATURE_LAST: break; } @@ -1216,6 +1301,7 @@ qemuFirmwareSanityCheck(const qemuFirmware *fw, case QEMU_FIRMWARE_FEATURE_ENROLLED_KEYS: case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC: case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC: + case QEMU_FIRMWARE_FEATURE_INTEL_TDX: case QEMU_FIRMWARE_FEATURE_LAST: break; } @@ -1411,6 +1497,7 @@ qemuFirmwareGetSupported(const char *machine, qemuFirmware *fw = firmwares[i]; const qemuFirmwareMappingFlash *flash = &fw->mapping.data.flash; const qemuFirmwareMappingMemory *memory = &fw->mapping.data.memory; + const qemuFirmwareMappingGeneric *generic = &fw->mapping.data.generic; const char *fwpath = NULL; const char *nvrampath = NULL; size_t j; @@ -1421,7 +1508,10 @@ qemuFirmwareGetSupported(const char *machine, for (j = 0; j < fw->ninterfaces; j++) { switch (fw->interfaces[j]) { case QEMU_FIRMWARE_OS_INTERFACE_UEFI: - *supported |= 1ULL << VIR_DOMAIN_OS_DEF_FIRMWARE_EFI; + if (fw->mapping.device == QEMU_FIRMWARE_DEVICE_GENERIC) + *supported |= 1ULL << VIR_DOMAIN_OS_DEF_FIRMWARE_GENERIC; + else + *supported |= 1ULL << VIR_DOMAIN_OS_DEF_FIRMWARE_EFI; break; case QEMU_FIRMWARE_OS_INTERFACE_BIOS: *supported |= 1ULL << VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS; @@ -1449,6 +1539,7 @@ qemuFirmwareGetSupported(const char *machine, case QEMU_FIRMWARE_FEATURE_SECURE_BOOT: case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC: case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC: + case QEMU_FIRMWARE_FEATURE_INTEL_TDX: case QEMU_FIRMWARE_FEATURE_LAST: break; } @@ -1464,6 +1555,10 @@ qemuFirmwareGetSupported(const char *machine, fwpath = memory->filename; break; + case QEMU_FIRMWARE_DEVICE_GENERIC: + fwpath = generic->filename; + break; + case QEMU_FIRMWARE_DEVICE_KERNEL: case QEMU_FIRMWARE_DEVICE_NONE: case QEMU_FIRMWARE_DEVICE_LAST: diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 2cb05dc5b2..ca507868ad 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -1254,6 +1254,13 @@ qemuValidateDomainDef(const virDomainDef *def, _("INTEL TDX launch security needs split kernel irqchip")); return -1; } + if ((!def->os.loader || + def->os.loader->type != VIR_DOMAIN_LOADER_TYPE_GENERIC) && + def->os.firmware != VIR_DOMAIN_OS_DEF_FIRMWARE_GENERIC) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("INTEL TDX launch security needs generic loader type")); + return -1; + } break; case VIR_DOMAIN_LAUNCH_SECURITY_NONE: break; -- 2.25.1