edecca
From fb28fc398e318509452a50f59d78d90584ca0c27 Mon Sep 17 00:00:00 2001
edecca
Message-Id: <fb28fc398e318509452a50f59d78d90584ca0c27@dist-git>
edecca
From: Erik Skultety <eskultet@redhat.com>
edecca
Date: Mon, 20 Aug 2018 17:18:52 +0200
edecca
Subject: [PATCH] qemu: Fix probing of AMD SEV support
edecca
MIME-Version: 1.0
edecca
Content-Type: text/plain; charset=UTF-8
edecca
Content-Transfer-Encoding: 8bit
edecca
edecca
So the procedure to detect SEV support works like this:
edecca
1) we detect that sev-guest is among the QOM types and set the cap flag
edecca
2) we probe the monitor for SEV support
edecca
    - this is tricky, because QEMU with compiled SEV support will always
edecca
    report -object sev-guest and query-sev-capabilities command, that
edecca
    however doesn't mean SEV is supported
edecca
3) depending on what the monitor returned, we either keep or clear the
edecca
capability flag for SEV
edecca
edecca
Commit a349c6c21c6 added an explicit check for "GenericError" in the
edecca
monitor reply to prevent libvirtd to spam logs about missing
edecca
'query-sev-capabilities' command. At the same time though, it returned
edecca
success in this case which means that we didn't clear the capability
edecca
flag afterwards and happily formatted SEV into qemuCaps. Therefore,
edecca
adjust all the relevant callers to handle -1 on errors, 0 on SEV being
edecca
unsupported and 1 on SEV being supported.
edecca
edecca
Signed-off-by: Erik Skultety <eskultet@redhat.com>
edecca
Acked-by: Peter Krempa <pkrempa@redhat.com>
edecca
(cherry picked from commit 764491c9dddf063292adf1433769ccccb1a50db6)
edecca
edecca
https://bugzilla.redhat.com/show_bug.cgi?id=1612009
edecca
https://bugzilla.redhat.com/show_bug.cgi?id=1619150
edecca
edecca
Signed-off-by: Erik Skultety <eskultet@redhat.com>
edecca
Reviewed-by: Ján Tomko <jtomko@redhat.com>
edecca
---
edecca
 src/qemu/qemu_capabilities.c                  | 15 ++++++++++----
edecca
 src/qemu/qemu_monitor_json.c                  | 20 +++++++++++++++----
edecca
 .../caps_3.0.0.x86_64.xml                     |  1 -
edecca
 3 files changed, 27 insertions(+), 9 deletions(-)
edecca
edecca
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
edecca
index 0fb800589a..55024ad735 100644
edecca
--- a/src/qemu/qemu_capabilities.c
edecca
+++ b/src/qemu/qemu_capabilities.c
edecca
@@ -2695,18 +2695,20 @@ virQEMUCapsProbeQMPGICCapabilities(virQEMUCapsPtr qemuCaps,
edecca
 }
edecca
 
edecca
 
edecca
+/* Returns -1 on error, 0 if SEV is not supported, 1 if SEV is supported */
edecca
 static int
edecca
 virQEMUCapsProbeQMPSEVCapabilities(virQEMUCapsPtr qemuCaps,
edecca
                                    qemuMonitorPtr mon)
edecca
 {
edecca
+    int rc = -1;
edecca
     virSEVCapability *caps = NULL;
edecca
 
edecca
-    if (qemuMonitorGetSEVCapabilities(mon, &caps) < 0)
edecca
-        return -1;
edecca
+    if ((rc = qemuMonitorGetSEVCapabilities(mon, &caps)) <= 0)
edecca
+        return rc;
edecca
 
edecca
     virSEVCapabilitiesFree(qemuCaps->sevCapabilities);
edecca
     qemuCaps->sevCapabilities = caps;
edecca
-    return 0;
edecca
+    return rc;
edecca
 }
edecca
 
edecca
 
edecca
@@ -4116,7 +4118,12 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
edecca
 
edecca
     /* Probe for SEV capabilities */
edecca
     if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
edecca
-        if (virQEMUCapsProbeQMPSEVCapabilities(qemuCaps, mon) < 0)
edecca
+        int rc = virQEMUCapsProbeQMPSEVCapabilities(qemuCaps, mon);
edecca
+
edecca
+        if (rc < 0)
edecca
+            goto cleanup;
edecca
+
edecca
+        if (rc == 0)
edecca
             virQEMUCapsClear(qemuCaps, QEMU_CAPS_SEV_GUEST);
edecca
     }
edecca
 
edecca
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
edecca
index 66c525ed0c..8199556166 100644
edecca
--- a/src/qemu/qemu_monitor_json.c
edecca
+++ b/src/qemu/qemu_monitor_json.c
edecca
@@ -6425,6 +6425,20 @@ qemuMonitorJSONGetGICCapabilities(qemuMonitorPtr mon,
edecca
 }
edecca
 
edecca
 
edecca
+/**
edecca
+ * qemuMonitorJSONGetSEVCapabilities:
edecca
+ * @mon: qemu monitor object
edecca
+ * @capabilities: pointer to pointer to a SEV capability structure to be filled
edecca
+ *
edecca
+ * This function queries and fills in AMD's SEV platform-specific data.
edecca
+ * Note that from QEMU's POV both -object sev-guest and query-sev-capabilities
edecca
+ * can be present even if SEV is not available, which basically leaves us with
edecca
+ * checking for JSON "GenericError" in order to differentiate between
edecca
+ * compiled-in support and actual SEV support on the platform.
edecca
+ *
edecca
+ * Returns -1 on error, 0 if SEV is not supported, and 1 if SEV is supported on
edecca
+ * the platform.
edecca
+ */
edecca
 int
edecca
 qemuMonitorJSONGetSEVCapabilities(qemuMonitorPtr mon,
edecca
                                   virSEVCapability **capabilities)
edecca
@@ -6446,8 +6460,7 @@ qemuMonitorJSONGetSEVCapabilities(qemuMonitorPtr mon,
edecca
     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
edecca
         goto cleanup;
edecca
 
edecca
-    /* Both -object sev-guest and query-sev-capabilities can be present
edecca
-     * even if SEV is not available */
edecca
+    /* QEMU has only compiled-in support of SEV */
edecca
     if (qemuMonitorJSONHasError(reply, "GenericError")) {
edecca
         ret = 0;
edecca
         goto cleanup;
edecca
@@ -6499,8 +6512,7 @@ qemuMonitorJSONGetSEVCapabilities(qemuMonitorPtr mon,
edecca
     capability->cbitpos = cbitpos;
edecca
     capability->reduced_phys_bits = reduced_phys_bits;
edecca
     VIR_STEAL_PTR(*capabilities, capability);
edecca
-    ret = 0;
edecca
-
edecca
+    ret = 1;
edecca
  cleanup:
edecca
     virSEVCapabilitiesFree(capability);
edecca
     virJSONValueFree(cmd);
edecca
diff --git a/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml
edecca
index 4bc7cfeebc..8992d645e7 100644
edecca
--- a/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml
edecca
+++ b/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml
edecca
@@ -212,7 +212,6 @@
edecca
   <flag name='tpm-emulator'/>
edecca
   <flag name='mch'/>
edecca
   <flag name='mch.extended-tseg-mbytes'/>
edecca
-  <flag name='sev-guest'/>
edecca
   <flag name='usb-storage.werror'/>
edecca
   <flag name='egl-headless'/>
edecca
   <flag name='vfio-pci.display'/>
edecca
-- 
edecca
2.18.0
edecca