[RFC PATCH v2 8/8] qemu: Add firmware descriptor support for TDX

Zhenzhong Duan zhenzhong.duan at intel.com
Fri Jul 16 03:10:36 UTC 2021


Add a firmware descriptor support for TDVF, then libvirt can
auto match TDVF fimware with td-guest.

Signed-off-by: Zhenzhong Duan <zhenzhong.duan at intel.com>
---
 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




More information about the libvir-list mailing list