]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu_monitor: Allow querying SEV-SNP state in 'query-sev'
authorMichal Privoznik <mprivozn@redhat.com>
Mon, 10 Jun 2024 14:17:26 +0000 (16:17 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Fri, 21 Jun 2024 07:35:32 +0000 (09:35 +0200)
In QEMU commit v9.0.0-1155-g59d3740cb4 the return type of
'query-sev' monitor command changed to accommodate SEV-SNP. Even
though we currently support launching plain SNP guests, this will
soon change.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
src/qemu/qemu_driver.c
src/qemu/qemu_monitor.c
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c
src/qemu/qemu_monitor_json.h
tests/qemumonitorjsontest.c

index eb1612b9d76fd406e5f2a17efcceca69522cc6ff..068c721d9f147d38b423a93b644826bd07a18fd3 100644 (file)
@@ -19036,10 +19036,7 @@ qemuDomainGetSEVInfo(virDomainObj *vm,
     int ret = -1;
     int rv;
     g_autofree char *tmp = NULL;
-    unsigned int apiMajor = 0;
-    unsigned int apiMinor = 0;
-    unsigned int buildID = 0;
-    unsigned int policy = 0;
+    qemuMonitorSEVInfo info = { };
     int maxpar = 0;
 
     virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
@@ -19054,14 +19051,12 @@ qemuDomainGetSEVInfo(virDomainObj *vm,
     qemuDomainObjEnterMonitor(vm);
     tmp = qemuMonitorGetSEVMeasurement(QEMU_DOMAIN_PRIVATE(vm)->mon);
 
-
     if (!tmp) {
         qemuDomainObjExitMonitor(vm);
         goto endjob;
     }
 
-    rv = qemuMonitorGetSEVInfo(QEMU_DOMAIN_PRIVATE(vm)->mon,
-                               &apiMajor, &apiMinor, &buildID, &policy);
+    rv = qemuMonitorGetSEVInfo(QEMU_DOMAIN_PRIVATE(vm)->mon, &info);
     qemuDomainObjExitMonitor(vm);
 
     if (rv < 0)
@@ -19073,21 +19068,30 @@ qemuDomainGetSEVInfo(virDomainObj *vm,
         goto endjob;
     if (virTypedParamsAddUInt(params, nparams, &maxpar,
                               VIR_DOMAIN_LAUNCH_SECURITY_SEV_API_MAJOR,
-                              apiMajor) < 0)
+                              info.apiMajor) < 0)
         goto endjob;
     if (virTypedParamsAddUInt(params, nparams, &maxpar,
                               VIR_DOMAIN_LAUNCH_SECURITY_SEV_API_MINOR,
-                              apiMinor) < 0)
+                              info.apiMinor) < 0)
         goto endjob;
     if (virTypedParamsAddUInt(params, nparams, &maxpar,
                               VIR_DOMAIN_LAUNCH_SECURITY_SEV_BUILD_ID,
-                              buildID) < 0)
-        goto endjob;
-    if (virTypedParamsAddUInt(params, nparams, &maxpar,
-                              VIR_DOMAIN_LAUNCH_SECURITY_SEV_POLICY,
-                              policy) < 0)
+                              info.buildID) < 0)
         goto endjob;
 
+    switch (info.type) {
+    case QEMU_MONITOR_SEV_GUEST_TYPE_SEV:
+        if (virTypedParamsAddUInt(params, nparams, &maxpar,
+                                  VIR_DOMAIN_LAUNCH_SECURITY_SEV_POLICY,
+                                  info.data.sev.policy) < 0)
+            goto endjob;
+        break;
+
+    case QEMU_MONITOR_SEV_GUEST_TYPE_SEV_SNP:
+    case QEMU_MONITOR_SEV_GUEST_TYPE_LAST:
+        break;
+    }
+
     ret = 0;
 
  endjob:
index 34e2ccab9725afe0eea79563e97ead60b48784f5..b1c0c6a0647e6692d33f506757950d807f25ae7d 100644 (file)
@@ -4043,14 +4043,11 @@ qemuMonitorGetSEVMeasurement(qemuMonitor *mon)
 
 int
 qemuMonitorGetSEVInfo(qemuMonitor *mon,
-                      unsigned int *apiMajor,
-                      unsigned int *apiMinor,
-                      unsigned int *buildID,
-                      unsigned int *policy)
+                      qemuMonitorSEVInfo *info)
 {
     QEMU_CHECK_MONITOR(mon);
 
-    return qemuMonitorJSONGetSEVInfo(mon, apiMajor, apiMinor, buildID, policy);
+    return qemuMonitorJSONGetSEVInfo(mon, info);
 }
 
 
index b78f539c8503bf3decdcf6fcbcefe5f97cf63b01..8dde3f9fff1e471bd5e7ef49541202fe74457b73 100644 (file)
@@ -1334,14 +1334,43 @@ int qemuMonitorBlockdevMediumInsert(qemuMonitor *mon,
 char *
 qemuMonitorGetSEVMeasurement(qemuMonitor *mon);
 
+typedef struct _qemuMonitorSEVGuestInfo qemuMonitorSEVGuestInfo;
+struct _qemuMonitorSEVGuestInfo {
+    unsigned int policy;
+    unsigned int handle;
+};
+
+typedef struct _qemuMonitorSEVSNPGuestInfo qemuMonitorSEVSNPGuestInfo;
+struct _qemuMonitorSEVSNPGuestInfo {
+    unsigned long long snp_policy;
+};
+
+
+typedef enum {
+    QEMU_MONITOR_SEV_GUEST_TYPE_SEV,
+    QEMU_MONITOR_SEV_GUEST_TYPE_SEV_SNP,
+
+    QEMU_MONITOR_SEV_GUEST_TYPE_LAST
+} qemuMonitorSEVGuestType;
+
+VIR_ENUM_DECL(qemuMonitorSEVGuest);
+
+typedef struct _qemuMonitorSEVInfo qemuMonitorSEVInfo;
+struct _qemuMonitorSEVInfo {
+    unsigned int apiMajor;
+    unsigned int apiMinor;
+    unsigned int buildID;
+    qemuMonitorSEVGuestType type;
+    union {
+        qemuMonitorSEVGuestInfo sev;
+        qemuMonitorSEVSNPGuestInfo sev_snp;
+    } data;
+};
+
 int
 qemuMonitorGetSEVInfo(qemuMonitor *mon,
-                      unsigned int *apiMajor,
-                      unsigned int *apiMinor,
-                      unsigned int *buildID,
-                      unsigned int *policy)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
-    ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5);
+                      qemuMonitorSEVInfo *info)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
 
 int
 qemuMonitorSetLaunchSecurityState(qemuMonitor *mon,
index 8f8f3c95f0862279ea5461fde2c7f8893c4dbd06..89ea33a3ab9d301ea89e04f35bb5ad51b1e62383 100644 (file)
@@ -7971,6 +7971,10 @@ qemuMonitorJSONGetSEVMeasurement(qemuMonitor *mon)
 }
 
 
+VIR_ENUM_IMPL(qemuMonitorSEVGuest,
+              QEMU_MONITOR_SEV_GUEST_TYPE_LAST,
+              "sev", "sev-snp");
+
 /**
  * Retrieve info about the SEV setup, returning those fields that
  * are required to do a launch attestation, as per
@@ -7984,13 +7988,15 @@ qemuMonitorJSONGetSEVMeasurement(qemuMonitor *mon)
  *  { "return": { "enabled": true, "api-major" : 0, "api-minor" : 0,
  *                "build-id" : 0, "policy" : 0, "state" : "running",
  *                "handle" : 1 } }
+ *
+ *  Or newer (as of QEMU v9.0.0-1155-g59d3740cb4):
+ *
+ *  {"return": {"enabled": true, "api-minor": 55, "handle": 1, "state": "launch-secret",
+ *              "api-major": 1, "sev-type": "sev", "build-id": 21, "policy": 1}}
  */
 int
 qemuMonitorJSONGetSEVInfo(qemuMonitor *mon,
-                          unsigned int *apiMajor,
-                          unsigned int *apiMinor,
-                          unsigned int *buildID,
-                          unsigned int *policy)
+                          qemuMonitorSEVInfo *info)
 {
     g_autoptr(virJSONValue) cmd = NULL;
     g_autoptr(virJSONValue) reply = NULL;
@@ -8005,16 +8011,51 @@ qemuMonitorJSONGetSEVInfo(qemuMonitor *mon,
     if (!(data = qemuMonitorJSONGetReply(cmd, reply, VIR_JSON_TYPE_OBJECT)))
         return -1;
 
-    if (virJSONValueObjectGetNumberUint(data, "api-major", apiMajor) < 0 ||
-        virJSONValueObjectGetNumberUint(data, "api-minor", apiMinor) < 0 ||
-        virJSONValueObjectGetNumberUint(data, "build-id", buildID) < 0 ||
-        virJSONValueObjectGetNumberUint(data, "policy", policy) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                       _("query-sev reply was missing some data"));
-        return -1;
+    if (virJSONValueObjectGetNumberUint(data, "api-major", &info->apiMajor) < 0 ||
+        virJSONValueObjectGetNumberUint(data, "api-minor", &info->apiMinor) < 0 ||
+        virJSONValueObjectGetNumberUint(data, "build-id", &info->buildID) < 0) {
+        goto error;
+    }
+
+    if (virJSONValueObjectHasKey(data, "sev-type")) {
+        const char *sevTypeStr = virJSONValueObjectGetString(data, "sev-type");
+        int sevType;
+
+        if ((sevType = qemuMonitorSEVGuestTypeFromString(sevTypeStr)) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("unknown SEV type '%1$s'"),
+                           sevTypeStr);
+            return -1;
+        }
+
+        info->type = sevType;
+    } else {
+        info->type = QEMU_MONITOR_SEV_GUEST_TYPE_SEV;
+    }
+
+    switch (info->type) {
+    case QEMU_MONITOR_SEV_GUEST_TYPE_SEV:
+        if (virJSONValueObjectGetNumberUint(data, "policy", &info->data.sev.policy) < 0 ||
+            virJSONValueObjectGetNumberUint(data, "handle", &info->data.sev.handle) < 0) {
+            goto error;
+        }
+        break;
+
+    case QEMU_MONITOR_SEV_GUEST_TYPE_SEV_SNP:
+        if (virJSONValueObjectGetNumberUlong(data, "snp-policy", &info->data.sev_snp.snp_policy) < 0)
+            goto error;
+        break;
+
+    case QEMU_MONITOR_SEV_GUEST_TYPE_LAST:
+        break;
     }
 
     return 0;
+
+ error:
+    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                   _("query-sev reply was missing some data"));
+    return -1;
 }
 
 
index 9684660d86f7e396af25f62d5c89d0f3205a6ad6..921dd34ed227dac33d7b67687443e979b9f8f487 100644 (file)
@@ -417,12 +417,8 @@ qemuMonitorJSONGetSEVMeasurement(qemuMonitor *mon);
 
 int
 qemuMonitorJSONGetSEVInfo(qemuMonitor *mon,
-                          unsigned int *apiMajor,
-                          unsigned int *apiMinor,
-                          unsigned int *buildID,
-                          unsigned int *policy)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
-    ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5);
+                          qemuMonitorSEVInfo *info)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
 
 int
 qemuMonitorJSONGetVersion(qemuMonitor *mon,
index 45cee237981973379361e1d6b6f49a03fe1da3a0..66d0c127ca3cda07e97cf6050c80d8d3605b7101 100644 (file)
@@ -2730,10 +2730,7 @@ testQemuMonitorJSONGetSEVInfo(const void *opaque)
     const testGenericData *data = opaque;
     virDomainXMLOption *xmlopt = data->xmlopt;
     g_autoptr(qemuMonitorTest) test = NULL;
-    unsigned int apiMajor = 0;
-    unsigned int apiMinor = 0;
-    unsigned int buildID = 0;
-    unsigned int policy = 0;
+    qemuMonitorSEVInfo info = { };
 
     if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
         return -1;
@@ -2753,16 +2750,70 @@ testQemuMonitorJSONGetSEVInfo(const void *opaque)
                                "}") < 0)
         return -1;
 
-    if (qemuMonitorGetSEVInfo(qemuMonitorTestGetMonitor(test),
-                              &apiMajor, &apiMinor, &buildID, &policy) < 0)
+    if (qemuMonitorGetSEVInfo(qemuMonitorTestGetMonitor(test), &info) < 0)
         return -1;
 
-    if (apiMajor != 1 || apiMinor != 8 || buildID != 834 || policy != 3) {
+    if (info.apiMajor != 1 || info.apiMinor != 8 || info.buildID != 834 ||
+        info.type != QEMU_MONITOR_SEV_GUEST_TYPE_SEV ||
+        info.data.sev.policy != 3 || info.data.sev.handle != 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        "Unexpected SEV info values");
         return -1;
     }
 
+    if (qemuMonitorTestAddItem(test, "query-sev",
+                               "{"
+                               "    \"return\": {"
+                               "        \"enabled\": true,"
+                               "        \"api-minor\": 55,"
+                               "        \"handle\": 1,"
+                               "        \"state\": \"running\","
+                               "        \"api-major\": 1,"
+                               "        \"sev-type\": \"sev\","
+                               "        \"build-id\": 21,"
+                               "        \"policy\": 1"
+                               "    },"
+                               "    \"id\": \"libvirt-16\""
+                               "}") < 0)
+        return -1;
+
+    if (qemuMonitorGetSEVInfo(qemuMonitorTestGetMonitor(test), &info) < 0)
+        return -1;
+
+    if (info.apiMajor != 1 || info.apiMinor != 55 || info.buildID != 21 ||
+        info.type != QEMU_MONITOR_SEV_GUEST_TYPE_SEV ||
+        info.data.sev.policy != 1 || info.data.sev.handle != 1) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       "Unexpected SEV info values");
+        return -1;
+    }
+
+    if (qemuMonitorTestAddItem(test, "query-sev",
+                               "{"
+                               "    \"return\": {"
+                               "        \"enabled\": true,"
+                               "        \"api-minor\": 55,"
+                               "        \"state\": \"running\","
+                               "        \"api-major\": 1,"
+                               "        \"sev-type\": \"sev-snp\","
+                               "        \"build-id\": 21,"
+                               "        \"snp-policy\": 196608"
+                               "    },"
+                               "    \"id\": \"libvirt-16\""
+                               "}") < 0)
+        return -1;
+
+    if (qemuMonitorGetSEVInfo(qemuMonitorTestGetMonitor(test), &info) < 0)
+        return -1;
+
+    if (info.apiMajor != 1 || info.apiMinor != 55 || info.buildID != 21 ||
+        info.type != QEMU_MONITOR_SEV_GUEST_TYPE_SEV_SNP ||
+        info.data.sev_snp.snp_policy != 0x30000) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       "Unexpected SEV SNP info values");
+        return -1;
+    }
+
     return 0;
 }