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