mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
qemu_monitor: Allow querying SEV-SNP state in 'query-sev'
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>
This commit is contained in:
parent
7d16c296e3
commit
914b986275
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user