commit d4005609f3806f3ee4ad7e39cba0c887baf462a5
Author: Brijesh Singh <brijesh.singh@amd.com>
Date:   Fri Jun 8 09:40:51 2018 -0500

    qemu: Provide support to query the SEV capability
    
    QEMU version >= 2.12 provides support for launching an encrypted VMs on
    AMD x86 platform using Secure Encrypted Virtualization (SEV) feature.
    This patch adds support to query the SEV capability from the qemu.
    
    Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
    Reviewed-by: Erik Skultety <eskultet@redhat.com>

Index: libvirt-4.0.0/src/conf/domain_capabilities.c
===================================================================
--- libvirt-4.0.0.orig/src/conf/domain_capabilities.c
+++ libvirt-4.0.0/src/conf/domain_capabilities.c
@@ -74,6 +74,18 @@ virDomainCapsStringValuesFree(virDomainC
 }
 
 
+void
+virSEVCapabilitiesFree(virSEVCapability *cap)
+{
+    if (!cap)
+        return;
+
+    VIR_FREE(cap->pdh);
+    VIR_FREE(cap->cert_chain);
+    VIR_FREE(cap);
+}
+
+
 static void
 virDomainCapsDispose(void *obj)
 {
Index: libvirt-4.0.0/src/conf/domain_capabilities.h
===================================================================
--- libvirt-4.0.0.orig/src/conf/domain_capabilities.h
+++ libvirt-4.0.0/src/conf/domain_capabilities.h
@@ -137,6 +137,15 @@ struct _virDomainCapsCPU {
     virDomainCapsCPUModelsPtr custom;
 };
 
+typedef struct _virSEVCapability virSEVCapability;
+typedef virSEVCapability *virSEVCapabilityPtr;
+struct _virSEVCapability {
+    char *pdh;
+    char *cert_chain;
+    unsigned int cbitpos;
+    unsigned int reduced_phys_bits;
+};
+
 struct _virDomainCaps {
     virObjectLockable parent;
 
@@ -199,4 +208,7 @@ int virDomainCapsEnumSet(virDomainCapsEn
 void virDomainCapsEnumClear(virDomainCapsEnumPtr capsEnum);
 
 char * virDomainCapsFormat(virDomainCapsPtr const caps);
+
+void
+virSEVCapabilitiesFree(virSEVCapability *capabilities);
 #endif /* __DOMAIN_CAPABILITIES_H__ */
Index: libvirt-4.0.0/src/libvirt_private.syms
===================================================================
--- libvirt-4.0.0.orig/src/libvirt_private.syms
+++ libvirt-4.0.0/src/libvirt_private.syms
@@ -184,6 +184,7 @@ virDomainCapsEnumClear;
 virDomainCapsEnumSet;
 virDomainCapsFormat;
 virDomainCapsNew;
+virSEVCapabilitiesFree;
 
 
 # conf/domain_conf.h
Index: libvirt-4.0.0/src/qemu/qemu_capabilities.c
===================================================================
--- libvirt-4.0.0.orig/src/qemu/qemu_capabilities.c
+++ libvirt-4.0.0/src/qemu/qemu_capabilities.c
@@ -457,6 +457,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAS
               /* 280 */
               "pl011",
               "machine.pseries.max-cpu-compat",
+              "sev-guest",
     );
 
 
@@ -522,6 +523,8 @@ struct _virQEMUCaps {
     size_t ngicCapabilities;
     virGICCapability *gicCapabilities;
 
+    virSEVCapability *sevCapabilities;
+
     virQEMUCapsHostCPUData kvmCPU;
     virQEMUCapsHostCPUData tcgCPU;
 };
@@ -1690,6 +1693,7 @@ struct virQEMUCapsStringFlags virQEMUCap
     { "sclplmconsole", QEMU_CAPS_DEVICE_SCLPLMCONSOLE },
     { "isa-serial", QEMU_CAPS_DEVICE_ISA_SERIAL },
     { "pl011", QEMU_CAPS_DEVICE_PL011 },
+    { "sev-guest", QEMU_CAPS_SEV_GUEST },    
 };
 
 static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBalloon[] = {
@@ -2804,6 +2808,16 @@ virQEMUCapsSetGICCapabilities(virQEMUCap
 }
 
 
+void
+virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
+                              virSEVCapability *capabilities)
+{
+    virSEVCapabilitiesFree(qemuCaps->sevCapabilities);
+
+    qemuCaps->sevCapabilities = capabilities;
+}
+
+
 static int
 virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
                             qemuMonitorPtr mon)
@@ -3311,6 +3325,21 @@ virQEMUCapsProbeQMPGICCapabilities(virQE
 }
 
 
+static int
+virQEMUCapsProbeQMPSEVCapabilities(virQEMUCapsPtr qemuCaps,
+                                   qemuMonitorPtr mon)
+{
+    virSEVCapability *caps = NULL;
+
+    if (qemuMonitorGetSEVCapabilities(mon, &caps) < 0)
+        return -1;
+
+    virQEMUCapsSetSEVCapabilities(qemuCaps, caps);
+
+    return 0;
+}
+
+
 bool
 virQEMUCapsCPUFilterFeatures(const char *name,
                              void *opaque)
@@ -4921,6 +4950,12 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr
         virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION))
         virQEMUCapsSet(qemuCaps, QEMU_CAPS_CPU_CACHE);
 
+    /* Probe for SEV capabilities */
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
+        if (virQEMUCapsProbeQMPSEVCapabilities(qemuCaps, mon) < 0)
+            virQEMUCapsClear(qemuCaps, QEMU_CAPS_SEV_GUEST);
+    }
+
     ret = 0;
  cleanup:
     return ret;
Index: libvirt-4.0.0/src/qemu/qemu_capabilities.h
===================================================================
--- libvirt-4.0.0.orig/src/qemu/qemu_capabilities.h
+++ libvirt-4.0.0/src/qemu/qemu_capabilities.h
@@ -443,6 +443,7 @@ typedef enum {
     /* 280 */
     QEMU_CAPS_DEVICE_PL011, /* -device pl011 (not user-instantiable) */
     QEMU_CAPS_MACHINE_PSERIES_MAX_CPU_COMPAT, /* -machine pseries,max-cpu-compat= */
+    QEMU_CAPS_SEV_GUEST, /* -object sev-guest,... */
 
     QEMU_CAPS_LAST /* this must always be the last item */
 } virQEMUCapsFlags;
@@ -568,5 +569,4 @@ bool virQEMUCapsGuestIsNative(virArch ho
 
 bool virQEMUCapsCPUFilterFeatures(const char *name,
                                   void *opaque);
-
 #endif /* __QEMU_CAPABILITIES_H__*/
Index: libvirt-4.0.0/src/qemu/qemu_capspriv.h
===================================================================
--- libvirt-4.0.0.orig/src/qemu/qemu_capspriv.h
+++ libvirt-4.0.0/src/qemu/qemu_capspriv.h
@@ -85,6 +85,10 @@ virQEMUCapsSetGICCapabilities(virQEMUCap
                               virGICCapability *capabilities,
                               size_t ncapabilities);
 
+void
+virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
+                              virSEVCapability *capabilities);
+
 int
 virQEMUCapsParseHelpStr(const char *qemu,
                         const char *str,
Index: libvirt-4.0.0/src/qemu/qemu_monitor.c
===================================================================
--- libvirt-4.0.0.orig/src/qemu/qemu_monitor.c
+++ libvirt-4.0.0/src/qemu/qemu_monitor.c
@@ -3977,6 +3977,16 @@ qemuMonitorGetGICCapabilities(qemuMonito
 
 
 int
+qemuMonitorGetSEVCapabilities(qemuMonitorPtr mon,
+                              virSEVCapability **capabilities)
+{
+    QEMU_CHECK_MONITOR(mon);
+
+    return qemuMonitorJSONGetSEVCapabilities(mon, capabilities);
+}
+
+
+int
 qemuMonitorNBDServerStart(qemuMonitorPtr mon,
                           const char *host,
                           unsigned int port)
Index: libvirt-4.0.0/src/qemu/qemu_monitor.h
===================================================================
--- libvirt-4.0.0.orig/src/qemu/qemu_monitor.h
+++ libvirt-4.0.0/src/qemu/qemu_monitor.h
@@ -732,6 +732,9 @@ int qemuMonitorSetMigrationCapability(qe
 int qemuMonitorGetGICCapabilities(qemuMonitorPtr mon,
                                   virGICCapability **capabilities);
 
+int qemuMonitorGetSEVCapabilities(qemuMonitorPtr mon,
+                                  virSEVCapability **capabilities);
+
 typedef enum {
   QEMU_MONITOR_MIGRATE_BACKGROUND       = 1 << 0,
   QEMU_MONITOR_MIGRATE_NON_SHARED_DISK  = 1 << 1, /* migration with non-shared storage with full disk copy */
Index: libvirt-4.0.0/src/qemu/qemu_monitor_json.c
===================================================================
--- libvirt-4.0.0.orig/src/qemu/qemu_monitor_json.c
+++ libvirt-4.0.0/src/qemu/qemu_monitor_json.c
@@ -6262,6 +6262,85 @@ qemuMonitorJSONGetGICCapabilities(qemuMo
     return ret;
 }
 
+
+int
+qemuMonitorJSONGetSEVCapabilities(qemuMonitorPtr mon,
+                                  virSEVCapability **capabilities)
+{
+    int ret = -1;
+    virJSONValuePtr cmd;
+    virJSONValuePtr reply = NULL;
+    virJSONValuePtr caps;
+    virSEVCapability *capability = NULL;
+    const char *pdh = NULL, *cert_chain = NULL;
+    unsigned int cbitpos, reduced_phys_bits;
+
+    *capabilities = NULL;
+
+    if (!(cmd = qemuMonitorJSONMakeCommand("query-sev-capabilities",
+                                           NULL)))
+        return -1;
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        goto cleanup;
+
+
+    if (qemuMonitorJSONCheckError(cmd, reply) < 0)
+        goto cleanup;
+
+    caps = virJSONValueObjectGetObject(reply, "return");
+
+    if (virJSONValueObjectGetNumberUint(caps, "cbitpos", &cbitpos) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("query-sev-capabilities reply was missing"
+                         " 'cbitpos' field"));
+        goto cleanup;
+    }
+
+    if (virJSONValueObjectGetNumberUint(caps, "reduced-phys-bits",
+                                       &reduced_phys_bits) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("query-sev-capabilities reply was missing"
+                         " 'reduced-phys-bits' field"));
+        goto cleanup;
+    }
+
+    if (!(pdh = virJSONValueObjectGetString(caps, "pdh"))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("query-sev-capabilities reply was missing"
+                         " 'pdh' field"));
+        goto cleanup;
+    }
+
+    if (!(cert_chain = virJSONValueObjectGetString(caps, "cert-chain"))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("query-sev-capabilities reply was missing"
+                         " 'cert-chain' field"));
+        goto cleanup;
+    }
+
+    if (VIR_ALLOC(capability) < 0)
+        goto cleanup;
+
+    if (VIR_STRDUP(capability->pdh, pdh) < 0)
+        goto cleanup;
+
+    if (VIR_STRDUP(capability->cert_chain, cert_chain) < 0)
+        goto cleanup;
+
+    capability->cbitpos = cbitpos;
+    capability->reduced_phys_bits = reduced_phys_bits;
+    VIR_STEAL_PTR(*capabilities, capability);
+    ret = 0;
+
+ cleanup:
+    virSEVCapabilitiesFree(capability);
+    virJSONValueFree(cmd);
+    virJSONValueFree(reply);
+
+    return ret;
+}
+
 static virJSONValuePtr
 qemuMonitorJSONBuildInetSocketAddress(const char *host,
                                       const char *port)
Index: libvirt-4.0.0/src/qemu/qemu_monitor_json.h
===================================================================
--- libvirt-4.0.0.orig/src/qemu/qemu_monitor_json.h
+++ libvirt-4.0.0/src/qemu/qemu_monitor_json.h
@@ -153,6 +153,9 @@ int qemuMonitorJSONSetMigrationCapabilit
 int qemuMonitorJSONGetGICCapabilities(qemuMonitorPtr mon,
                                       virGICCapability **capabilities);
 
+int qemuMonitorJSONGetSEVCapabilities(qemuMonitorPtr mon,
+                                      virSEVCapability **capabilities);
+
 int qemuMonitorJSONMigrate(qemuMonitorPtr mon,
                            unsigned int flags,
                            const char *uri);
