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(a)redhat.com>
---
src/qemu/qemu_driver.c | 32 ++++++++++--------
src/qemu/qemu_monitor.c | 7 ++--
src/qemu/qemu_monitor.h | 41 +++++++++++++++++++----
src/qemu/qemu_monitor_json.c | 63 ++++++++++++++++++++++++++++------
src/qemu/qemu_monitor_json.h | 8 ++---
tests/qemumonitorjsontest.c | 65 ++++++++++++++++++++++++++++++++----
6 files changed, 167 insertions(+), 49 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index eb1612b9d7..068c721d9f 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -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:
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 34e2ccab97..b1c0c6a064 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -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);
}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index b78f539c85..8dde3f9fff 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -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,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 8f8f3c95f0..5a6af90ac8 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -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_report;
+ }
+
+ 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_report;
+ }
+ break;
+
+ case QEMU_MONITOR_SEV_GUEST_TYPE_SEV_SNP:
+ if (virJSONValueObjectGetNumberUlong(data, "snp-policy",
&info->data.sev_snp.snp_policy) < 0)
+ goto error_report;
+ break;
+
+ case QEMU_MONITOR_SEV_GUEST_TYPE_LAST:
+ break;
}
return 0;
+
+ error_report:
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("query-sev reply was missing some data"));
+ return -1;
}
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 9684660d86..921dd34ed2 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -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,
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
index 45cee23798..66d0c127ca 100644
--- a/tests/qemumonitorjsontest.c
+++ b/tests/qemumonitorjsontest.c
@@ -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;
}
--
2.44.2