[libvirt PATCH v2 00/12] Improve AMD SEV support

This addresses a few issues in the AMD SEV support - Neither host or domain level SEV metadata is exposed in virsh commands - The domain launch security parameters don't expose enough info to validate the measurement - Support verified direct kernel boot - Report max SEV/SEV-ES guest counts The second point was the initial purpose of my work. Per the SEV API guide to calculate the measurement we need measurement = HMAC(0x04 || API_MAJOR || API_MINOR || BUILD || GCTX.POLICY || GCTX.LD || MNONCE; GCTX.TIK) The API_MINOR, API_MAJOR, BUILD values are things that are available from 'query-sev' QMP command and libvirt does not expose this info. This patch series adds them to virDomainGetLaunchSecurityParams alongside the measurement that we already report. So now the client can fetch this info and calculate an expected measurement to compare with the actual measurement they got. They will thus know if the guest is safe to inject secrets into, which is where Jim's recent patches come into play. Daniel P. Berrangé (12): include: add new launch security parameters qemu: report error querying launch params for inactive guest qemu: add monitor APIs for query-sev qemu: report new launch security parameters tools: add 'domlaunchsecinfo' virsh command tools: add 'nodesevinfo' virsh command conf: extend domain capabilities for max SEV guest count include: define parameters for reporting SEV guest limits qemu: report max number of SEV guests conf: add support for setting SEV kernel hashes qemu: probe for sev-guest.kernel-hashes property qemu: format sev-guest.kernel-hashes property docs/formatdomain.rst | 7 +- docs/formatdomaincaps.html.in | 6 + docs/manpages/virsh.rst | 31 +++++ docs/schemas/domaincaps.rng | 6 + docs/schemas/domaincommon.rng | 5 + include/libvirt/libvirt-domain.h | 32 +++++ include/libvirt/libvirt-host.h | 16 +++ src/conf/domain_capabilities.c | 4 + src/conf/domain_capabilities.h | 2 + src/conf/domain_conf.c | 8 ++ src/conf/domain_conf.h | 1 + src/qemu/qemu_capabilities.c | 46 ++++++++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 7 ++ src/qemu/qemu_driver.c | 59 ++++++++-- src/qemu/qemu_monitor.c | 13 +++ src/qemu/qemu_monitor.h | 9 ++ src/qemu/qemu_monitor_json.c | 46 ++++++++ src/qemu/qemu_monitor_json.h | 9 ++ src/qemu/qemu_validate.c | 8 ++ .../domaincapsdata/qemu_2.12.0-q35.x86_64.xml | 2 + .../domaincapsdata/qemu_2.12.0-tcg.x86_64.xml | 2 + tests/domaincapsdata/qemu_2.12.0.x86_64.xml | 2 + .../domaincapsdata/qemu_6.0.0-q35.x86_64.xml | 2 + .../domaincapsdata/qemu_6.0.0-tcg.x86_64.xml | 2 + tests/domaincapsdata/qemu_6.0.0.x86_64.xml | 2 + .../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 7 +- .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 7 +- tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 7 +- .../caps_2.12.0.x86_64.replies | 97 ++++++++++++---- .../caps_3.0.0.x86_64.replies | 97 ++++++++++++---- .../caps_3.1.0.x86_64.replies | 97 ++++++++++++---- .../caps_4.0.0.x86_64.replies | 97 ++++++++++++---- .../caps_4.1.0.x86_64.replies | 89 ++++++++++---- .../caps_4.2.0.x86_64.replies | 89 ++++++++++---- .../caps_5.0.0.x86_64.replies | 89 ++++++++++---- .../caps_5.1.0.x86_64.replies | 89 ++++++++++---- .../caps_5.2.0.x86_64.replies | 89 ++++++++++---- .../caps_6.0.0.x86_64.replies | 89 ++++++++++---- .../caps_6.1.0.x86_64.replies | 89 ++++++++++---- .../caps_6.2.0.x86_64.replies | 109 ++++++++++++++---- .../caps_6.2.0.x86_64.xml | 8 ++ tests/qemumonitorjsontest.c | 43 +++++++ ...unch-security-sev-direct.x86_64-6.2.0.args | 40 +++++++ .../launch-security-sev-direct.xml | 39 +++++++ tests/qemuxml2argvtest.c | 1 + tools/virsh-domain.c | 53 +++++++++ tools/virsh-host.c | 45 ++++++++ 48 files changed, 1427 insertions(+), 271 deletions(-) create mode 100644 tests/qemuxml2argvdata/launch-security-sev-direct.x86_64-6.2.0.args create mode 100644 tests/qemuxml2argvdata/launch-security-sev-direct.xml -- 2.33.1

Three more parameters are required in order that clients can perform a launch attestation on the SEV guest. Reviewed-by: Peter Krempa <pkrempa@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- include/libvirt/libvirt-domain.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index d0dd11ab01..5d3e15766e 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -5101,6 +5101,38 @@ int virDomainSetLifecycleAction(virDomainPtr domain, */ # define VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT "sev-measurement" +/** + * VIR_DOMAIN_LAUNCH_SECURITY_SEV_API_MAJOR: + * + * Macro represents the API major version of the SEV host, + * as VIR_TYPED_PARAM_UINT. + */ +# define VIR_DOMAIN_LAUNCH_SECURITY_SEV_API_MAJOR "sev-api-major" + +/** + * VIR_DOMAIN_LAUNCH_SECURITY_SEV_API_MINOR: + * + * Macro represents the API minor version of the SEV guest, + * as VIR_TYPED_PARAM_UINT. + */ +# define VIR_DOMAIN_LAUNCH_SECURITY_SEV_API_MINOR "sev-api-minor" + +/** + * VIR_DOMAIN_LAUNCH_SECURITY_SEV_BUILD_ID: + * + * Macro represents the build ID of the SEV host, + * as VIR_TYPED_PARAM_UINT. + */ +# define VIR_DOMAIN_LAUNCH_SECURITY_SEV_BUILD_ID "sev-build-id" + +/** + * VIR_DOMAIN_LAUNCH_SECURITY_SEV_POLICY: + * + * Macro represents the policy of the SEV guest, + * as VIR_TYPED_PARAM_UINT. + */ +# define VIR_DOMAIN_LAUNCH_SECURITY_SEV_POLICY "sev-policy" + int virDomainGetLaunchSecurityInfo(virDomainPtr domain, virTypedParameterPtr *params, int *nparams, -- 2.33.1

Querying launch params on a inactive guest currently triggers a warning about the monitor being NULL. https://bugzilla.redhat.com/show_bug.cgi?id=2030437 Reviewed-by: Peter Krempa <pkrempa@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_driver.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 8093b8f69b..5bacf73003 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -19992,6 +19992,12 @@ qemuDomainGetSEVMeasurement(virQEMUDriver *driver, if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0) return -1; + if (!virDomainObjIsActive(vm)) { + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto endjob; + } + qemuDomainObjEnterMonitor(driver, vm); tmp = qemuMonitorGetSEVMeasurement(QEMU_DOMAIN_PRIVATE(vm)->mon); -- 2.33.1

We're only returning the set of fields needed to perform an attestation, per the SEV API docs. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_monitor.c | 13 ++++++++++ src/qemu/qemu_monitor.h | 9 +++++++ src/qemu/qemu_monitor_json.c | 46 ++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 9 +++++++ tests/qemumonitorjsontest.c | 43 +++++++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 75e0e4ed92..dda6ae9796 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -4366,6 +4366,19 @@ qemuMonitorGetSEVMeasurement(qemuMonitor *mon) } +int +qemuMonitorGetSEVInfo(qemuMonitor *mon, + unsigned int *apiMajor, + unsigned int *apiMinor, + unsigned int *buildID, + unsigned int *policy) +{ + QEMU_CHECK_MONITOR(mon); + + return qemuMonitorJSONGetSEVInfo(mon, apiMajor, apiMinor, buildID, policy); +} + + int qemuMonitorGetPRManagerInfo(qemuMonitor *mon, GHashTable **retinfo) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index edc2b01a66..29746f0b8e 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1445,6 +1445,15 @@ int qemuMonitorBlockdevMediumInsert(qemuMonitor *mon, char * qemuMonitorGetSEVMeasurement(qemuMonitor *mon); +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); + typedef struct _qemuMonitorPRManagerInfo qemuMonitorPRManagerInfo; struct _qemuMonitorPRManagerInfo { bool connected; diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index e00d785c20..a3d6eca569 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -8216,6 +8216,52 @@ qemuMonitorJSONGetSEVMeasurement(qemuMonitor *mon) } +/** + * Retrive info about the SEV setup, returning those fields that + * are required to do a launch attestation, as per + * + * HMAC(0x04 || API_MAJOR || API_MINOR || BUILD || GCTX.POLICY || GCTX.LD || MNONCE; GCTX.TIK) + * + * specified in section 6.5.1 of AMD Secure Encrypted + * Virtualization API. + * + * { "execute": "query-sev" } + * { "return": { "enabled": true, "api-major" : 0, "api-minor" : 0, + * "build-id" : 0, "policy" : 0, "state" : "running", + * "handle" : 1 } } + */ +int +qemuMonitorJSONGetSEVInfo(qemuMonitor *mon, + unsigned int *apiMajor, + unsigned int *apiMinor, + unsigned int *buildID, + unsigned int *policy) +{ + g_autoptr(virJSONValue) cmd = NULL; + g_autoptr(virJSONValue) reply = NULL; + virJSONValue *data; + + if (!(cmd = qemuMonitorJSONMakeCommand("query-sev", NULL))) + return -1; + + if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) + return -1; + + if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0) + return -1; + + data = virJSONValueObjectGetObject(reply, "return"); + + if (virJSONValueObjectGetNumberUint(data, "api-major", apiMajor) < 0 || + virJSONValueObjectGetNumberUint(data, "api-minor", apiMinor) < 0 || + virJSONValueObjectGetNumberUint(data, "build-id", buildID) < 0 || + virJSONValueObjectGetNumberUint(data, "policy", policy) < 0) + return -1; + + return 0; +} + + /* * Example return data * diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 64064b0519..e88dfc9d50 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -459,6 +459,15 @@ qemuMonitorJSONSystemWakeup(qemuMonitor *mon); char * 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); + int qemuMonitorJSONGetVersion(qemuMonitor *mon, int *major, diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index 1ad2912b08..1b0bd0870d 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -2884,6 +2884,48 @@ testQemuMonitorJSONqemuMonitorJSONGetCPUModelBaseline(const void *opaque) } +static int +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; + + if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema))) + return -1; + + if (qemuMonitorTestAddItem(test, "query-sev", + "{" + " \"return\": {" + " \"enabled\": false," + " \"api-minor\": 8," + " \"handle\": 0," + " \"state\": \"uninit\"," + " \"api-major\": 1," + " \"build-id\": 834," + " \"policy\": 3" + " }," + " \"id\": \"libvirt-15\"" + "}") < 0) + return -1; + + if (qemuMonitorGetSEVInfo(qemuMonitorTestGetMonitor(test), + &apiMajor, &apiMinor, &buildID, &policy) < 0) + return -1; + + if (apiMajor != 1 || apiMinor != 8 || buildID != 834 || policy != 3) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + "Unexpected SEV info values"); + return -1; + } + + return 0; +} + static int mymain(void) { @@ -2979,6 +3021,7 @@ mymain(void) DO_TEST(CPU); DO_TEST(GetNonExistingCPUData); DO_TEST(GetIOThreads); + DO_TEST(GetSEVInfo); DO_TEST(Transaction); DO_TEST(BlockExportAdd); DO_TEST(BlockdevReopen); -- 2.33.1

On Fri, Dec 10, 2021 at 11:37:26 +0000, Daniel P. Berrangé wrote:
We're only returning the set of fields needed to perform an attestation, per the SEV API docs.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_monitor.c | 13 ++++++++++ src/qemu/qemu_monitor.h | 9 +++++++ src/qemu/qemu_monitor_json.c | 46 ++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 9 +++++++ tests/qemumonitorjsontest.c | 43 +++++++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+)
Reviewed-by: Peter Krempa <pkrempa@redhat.com>

Report extra info about the SEV setup, returning those fields that are required to calculate the expected launch measurement HMAC(0x04 || API_MAJOR || API_MINOR || BUILD || GCTX.POLICY || GCTX.LD || MNONCE; GCTX.TIK) specified in section 6.5.1 of AMD Secure Encrypted Virtualization API. Reviewed-by: Peter Krempa <pkrempa@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_driver.c | 43 +++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5bacf73003..1bf1938634 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -19977,14 +19977,19 @@ qemuNodeGetSEVInfo(virConnectPtr conn, static int -qemuDomainGetSEVMeasurement(virQEMUDriver *driver, - virDomainObj *vm, - virTypedParameterPtr *params, - int *nparams, - unsigned int flags) +qemuDomainGetSEVInfo(virQEMUDriver *driver, + virDomainObj *vm, + virTypedParameterPtr *params, + int *nparams, + unsigned int flags) { 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; int maxpar = 0; virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1); @@ -20001,15 +20006,39 @@ qemuDomainGetSEVMeasurement(virQEMUDriver *driver, qemuDomainObjEnterMonitor(driver, vm); tmp = qemuMonitorGetSEVMeasurement(QEMU_DOMAIN_PRIVATE(vm)->mon); + + if (!tmp) { + qemuDomainObjExitMonitor(driver, vm); + goto endjob; + } + + rv = qemuMonitorGetSEVInfo(QEMU_DOMAIN_PRIVATE(vm)->mon, + &apiMajor, &apiMinor, &buildID, &policy); qemuDomainObjExitMonitor(driver, vm); - if (!tmp) + if (rv < 0) goto endjob; if (virTypedParamsAddString(params, nparams, &maxpar, VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT, tmp) < 0) goto endjob; + if (virTypedParamsAddUInt(params, nparams, &maxpar, + VIR_DOMAIN_LAUNCH_SECURITY_SEV_API_MAJOR, + apiMajor) < 0) + goto endjob; + if (virTypedParamsAddUInt(params, nparams, &maxpar, + VIR_DOMAIN_LAUNCH_SECURITY_SEV_API_MINOR, + 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) + goto endjob; ret = 0; @@ -20037,7 +20066,7 @@ qemuDomainGetLaunchSecurityInfo(virDomainPtr domain, if (vm->def->sec && vm->def->sec->sectype == VIR_DOMAIN_LAUNCH_SECURITY_SEV) { - if (qemuDomainGetSEVMeasurement(driver, vm, params, nparams, flags) < 0) + if (qemuDomainGetSEVInfo(driver, vm, params, nparams, flags) < 0) goto cleanup; } -- 2.33.1

This command reports the launch security parameters for a guest, allowing an external tool to perform a launch attestation. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- docs/manpages/virsh.rst | 17 +++++++++++++ tools/virsh-domain.c | 53 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index 275f416090..1a74217625 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -2057,6 +2057,23 @@ destination hosts have synchronized time (i.e., NTP daemon is running on both of them). +domlaunchsecinfo +---------------- + +**Syntax:** + +:: + + domlaunchsecinfo domain + +Returns information about the launch security parameters associated +with a running domain. + +The set of parameters reported will vary depending on which type of +launch security protection is active. If none is active, no parameters +will be reported. + + dommemstat ---------- diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 8379f9f135..1560a8ea0d 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -9525,6 +9525,53 @@ cmdNumatune(vshControl * ctl, const vshCmd * cmd) goto cleanup; } +/* + * "domlaunchsecinfo" command + */ +static const vshCmdInfo info_domlaunchsecinfo[] = { + {.name = "help", + .data = N_("Get domain launch security info") + }, + {.name = "desc", + .data = N_("Get the launch security parameters for a guest domain") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_domlaunchsecinfo[] = { + VIRSH_COMMON_OPT_DOMAIN_FULL(0), + {.name = NULL} +}; + +static bool +cmdDomLaunchSecInfo(vshControl * ctl, const vshCmd * cmd) +{ + g_autoptr(virshDomain) dom = NULL; + size_t i; + int nparams = 0; + virTypedParameterPtr params = NULL; + bool ret = false; + + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) + return false; + + if (virDomainGetLaunchSecurityInfo(dom, ¶ms, &nparams, 0) != 0) { + vshError(ctl, "%s", _("Unable to get launch security parameters")); + goto cleanup; + } + + for (i = 0; i < nparams; i++) { + g_autofree char *str = vshGetTypedParamValue(ctl, ¶ms[i]); + vshPrint(ctl, "%-15s: %s\n", params[i].field, str); + } + + ret = true; + + cleanup: + virTypedParamsFree(params, nparams); + return ret; +} + /* * "qemu-monitor-command" command */ @@ -14544,6 +14591,12 @@ const vshCmdDef domManagementCmds[] = { .info = info_domjobinfo, .flags = 0 }, + {.name = "domlaunchsecinfo", + .handler = cmdDomLaunchSecInfo, + .opts = opts_domlaunchsecinfo, + .info = info_domlaunchsecinfo, + .flags = 0 + }, {.name = "domname", .handler = cmdDomname, .opts = opts_domname, -- 2.33.1

On Fri, Dec 10, 2021 at 11:37:28 +0000, Daniel P. Berrangé wrote:
This command reports the launch security parameters for a guest, allowing an external tool to perform a launch attestation.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- docs/manpages/virsh.rst | 17 +++++++++++++ tools/virsh-domain.c | 53 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+)
diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index 275f416090..1a74217625 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -2057,6 +2057,23 @@ destination hosts have synchronized time (i.e., NTP daemon is running on both of them).
+domlaunchsecinfo +---------------- + +**Syntax:** + +:: + + domlaunchsecinfo domain + +Returns information about the launch security parameters associated +with a running domain. + +The set of parameters reported will vary depending on which type of +launch security protection is active. If none is active, no parameters +will be reported.
Too bad that https://www.libvirt.org/html/libvirt-libvirt-domain.html#virDomainGetLaunchS... doesn't link to all the fields it returns because in case of commands such as this one it would be beneficial to at least link to the API docs outlining what the values are. Reviewed-by: Peter Krempa <pkrempa@redhat.com>

While some SEV info is reported in the domain capabilities, for reasons of size, this excludes the certificates. The nodesevinfo command provides the full set of information. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- docs/manpages/virsh.rst | 14 +++++++++++++ tools/virsh-host.c | 45 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index 1a74217625..e828f7ef68 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -479,6 +479,20 @@ Returns memory stats of the node. If *cell* is specified, this will print the specified cell statistics only. +nodesevinfo +----------- + +**Syntax:** + +:: + + nodesevinfo + +Reports information about the AMD SEV launch security features for +the node, if any. Some of this information is also reported in the +domain capabilities XML document. + + nodesuspend ----------- diff --git a/tools/virsh-host.c b/tools/virsh-host.c index 5da1346a9c..5ee3834de2 100644 --- a/tools/virsh-host.c +++ b/tools/virsh-host.c @@ -888,6 +888,45 @@ cmdNodeMemStats(vshControl *ctl, const vshCmd *cmd) return true; } +/* + * "nodesevinfo" command + */ +static const vshCmdInfo info_nodesevinfo[] = { + {.name = "help", + .data = N_("node SEV information") + }, + {.name = "desc", + .data = N_("Returns basic SEV information about the node.") + }, + {.name = NULL} +}; + +static bool +cmdNodeSEVInfo(vshControl *ctl, const vshCmd *cmd G_GNUC_UNUSED) +{ + virshControl *priv = ctl->privData; + size_t i; + int nparams = 0; + virTypedParameterPtr params = NULL; + bool ret = false; + + if (virNodeGetSEVInfo(priv->conn, ¶ms, &nparams, 0) != 0) { + vshError(ctl, "%s", _("Unable to get host SEV information")); + goto cleanup; + } + + for (i = 0; i < nparams; i++) { + g_autofree char *str = vshGetTypedParamValue(ctl, ¶ms[i]); + vshPrint(ctl, "%-18s: %s\n", params[i].field, str); + } + + ret = true; + + cleanup: + virTypedParamsFree(params, nparams); + return ret; +} + /* * "nodesuspend" command */ @@ -1828,6 +1867,12 @@ const vshCmdDef hostAndHypervisorCmds[] = { .info = info_nodememstats, .flags = 0 }, + {.name = "nodesevinfo", + .handler = cmdNodeSEVInfo, + .opts = NULL, + .info = info_nodesevinfo, + .flags = 0 + }, {.name = "nodesuspend", .handler = cmdNodeSuspend, .opts = opts_node_suspend, -- 2.33.1

On Fri, Dec 10, 2021 at 11:37:29 +0000, Daniel P. Berrangé wrote:
While some SEV info is reported in the domain capabilities, for reasons of size, this excludes the certificates. The nodesevinfo command provides the full set of information.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- docs/manpages/virsh.rst | 14 +++++++++++++ tools/virsh-host.c | 45 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+)
diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index 1a74217625..e828f7ef68 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -479,6 +479,20 @@ Returns memory stats of the node. If *cell* is specified, this will print the specified cell statistics only.
+nodesevinfo +----------- + +**Syntax:** + +:: + + nodesevinfo + +Reports information about the AMD SEV launch security features for +the node, if any. Some of this information is also reported in the +domain capabilities XML document.
In this instance it wouldbe IMO higly beneficial to mention the individual macros [1] that can be returned in the API docs: https://www.libvirt.org/html/libvirt-libvirt-host.html#virNodeGetSEVInfo And link to the API docs here. Duplicating the docs isn't great but not documenting what you get isn't either. [1]: https://www.libvirt.org/html/libvirt-libvirt-host.html#VIR_NODE_SEV_CBITPOS https://www.libvirt.org/html/libvirt-libvirt-host.html#VIR_NODE_SEV_CERT_CHA... https://www.libvirt.org/html/libvirt-libvirt-host.html#VIR_NODE_SEV_PDH https://www.libvirt.org/html/libvirt-libvirt-host.html#VIR_NODE_SEV_REDUCED_... (It's unfortunate that these don't have a common anchor to link to) Reviewed-by: Peter Krempa <pkrempa@redhat.com>

On Fri, Dec 10, 2021 at 02:52:55PM +0100, Peter Krempa wrote:
On Fri, Dec 10, 2021 at 11:37:29 +0000, Daniel P. Berrangé wrote:
While some SEV info is reported in the domain capabilities, for reasons of size, this excludes the certificates. The nodesevinfo command provides the full set of information.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- docs/manpages/virsh.rst | 14 +++++++++++++ tools/virsh-host.c | 45 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+)
diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index 1a74217625..e828f7ef68 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -479,6 +479,20 @@ Returns memory stats of the node. If *cell* is specified, this will print the specified cell statistics only.
+nodesevinfo +----------- + +**Syntax:** + +:: + + nodesevinfo + +Reports information about the AMD SEV launch security features for +the node, if any. Some of this information is also reported in the +domain capabilities XML document.
In this instance it wouldbe IMO higly beneficial to mention the individual macros [1] that can be returned in the API docs:
https://www.libvirt.org/html/libvirt-libvirt-host.html#virNodeGetSEVInfo
And link to the API docs here. Duplicating the docs isn't great but not documenting what you get isn't either.
I didn't do any of this in the v3, but I'll look at doing a separate series to improve the docs here.
[1]: https://www.libvirt.org/html/libvirt-libvirt-host.html#VIR_NODE_SEV_CBITPOS https://www.libvirt.org/html/libvirt-libvirt-host.html#VIR_NODE_SEV_CERT_CHA... https://www.libvirt.org/html/libvirt-libvirt-host.html#VIR_NODE_SEV_PDH https://www.libvirt.org/html/libvirt-libvirt-host.html#VIR_NODE_SEV_REDUCED_...
(It's unfortunate that these don't have a common anchor to link to)
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

There are limits on the number of SEV/SEV-ES guests that can be run on machines, which may be influenced by firmware settings. This is important to expose to users. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- docs/formatdomaincaps.html.in | 6 ++++++ docs/schemas/domaincaps.rng | 6 ++++++ src/conf/domain_capabilities.c | 4 ++++ src/conf/domain_capabilities.h | 2 ++ tests/domaincapsdata/qemu_2.12.0-q35.x86_64.xml | 2 ++ tests/domaincapsdata/qemu_2.12.0-tcg.x86_64.xml | 2 ++ tests/domaincapsdata/qemu_2.12.0.x86_64.xml | 2 ++ tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml | 2 ++ tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml | 2 ++ tests/domaincapsdata/qemu_6.0.0.x86_64.xml | 2 ++ 10 files changed, 30 insertions(+) diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in index 915ece8e3e..35b8bf3def 100644 --- a/docs/formatdomaincaps.html.in +++ b/docs/formatdomaincaps.html.in @@ -681,6 +681,12 @@ <dt><code>reducedPhysBits</code></dt> <dd>When memory encryption is enabled, we lose certain bits in physical address space. The number of bits we lose is hypervisor dependent.</dd> + <dt><code>maxGuests</code></dt> + <dd>The maximum number of SEV guests that can be launched on the host. + This value may be configurable in the firmware for some hosts.</dd> + <dt><code>maxESGuests</code></dt> + <dd>The maximum number of SEV-ES guests that can be launched on the host. + This value may be configurable in the firmware for some hosts.</dd> </dl> </body> diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng index 1b6122507f..b40ee0f35a 100644 --- a/docs/schemas/domaincaps.rng +++ b/docs/schemas/domaincaps.rng @@ -323,6 +323,12 @@ <element name="reducedPhysBits"> <data type="unsignedInt"/> </element> + <element name="maxGuests"> + <data type="unsignedInt"/> + </element> + <element name="maxESGuests"> + <data type="unsignedInt"/> + </element> </optional> </element> </define> diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index fef1326190..c394a7a390 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -597,6 +597,10 @@ virDomainCapsFeatureSEVFormat(virBuffer *buf, virBufferAsprintf(buf, "<cbitpos>%d</cbitpos>\n", sev->cbitpos); virBufferAsprintf(buf, "<reducedPhysBits>%d</reducedPhysBits>\n", sev->reduced_phys_bits); + virBufferAsprintf(buf, "<maxGuests>%d</maxGuests>\n", + sev->max_guests); + virBufferAsprintf(buf, "<maxESGuests>%d</maxESGuests>\n", + sev->max_es_guests); virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</sev>\n"); } diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index 2fcad87fd8..1d2f4ac7a5 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -187,6 +187,8 @@ struct _virSEVCapability { char *cert_chain; unsigned int cbitpos; unsigned int reduced_phys_bits; + unsigned int max_guests; + unsigned int max_es_guests; }; typedef enum { diff --git a/tests/domaincapsdata/qemu_2.12.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_2.12.0-q35.x86_64.xml index 9f41dfaf2b..26816ff066 100644 --- a/tests/domaincapsdata/qemu_2.12.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_2.12.0-q35.x86_64.xml @@ -205,6 +205,8 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> + <maxGuests>0</maxGuests> + <maxESGuests>0</maxESGuests> </sev> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_2.12.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_2.12.0-tcg.x86_64.xml index d5f9d8ebe3..5840a8b921 100644 --- a/tests/domaincapsdata/qemu_2.12.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_2.12.0-tcg.x86_64.xml @@ -215,6 +215,8 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> + <maxGuests>0</maxGuests> + <maxESGuests>0</maxESGuests> </sev> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_2.12.0.x86_64.xml b/tests/domaincapsdata/qemu_2.12.0.x86_64.xml index dc2c3ec4dd..21d1b6946e 100644 --- a/tests/domaincapsdata/qemu_2.12.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_2.12.0.x86_64.xml @@ -205,6 +205,8 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> + <maxGuests>0</maxGuests> + <maxESGuests>0</maxESGuests> </sev> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml index 90acb29775..3415d44019 100644 --- a/tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml @@ -227,6 +227,8 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> + <maxGuests>0</maxGuests> + <maxESGuests>0</maxESGuests> </sev> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml index 768cba5a41..f58be3af6c 100644 --- a/tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml @@ -233,6 +233,8 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> + <maxGuests>0</maxGuests> + <maxESGuests>0</maxESGuests> </sev> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.0.0.x86_64.xml b/tests/domaincapsdata/qemu_6.0.0.x86_64.xml index 7a95c530f9..0a2615c519 100644 --- a/tests/domaincapsdata/qemu_6.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.0.0.x86_64.xml @@ -227,6 +227,8 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> + <maxGuests>0</maxGuests> + <maxESGuests>0</maxESGuests> </sev> </features> </domainCapabilities> -- 2.33.1

On Fri, Dec 10, 2021 at 11:37:30 +0000, Daniel P. Berrangé wrote:
There are limits on the number of SEV/SEV-ES guests that can be run on machines, which may be influenced by firmware settings. This is important to expose to users.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- docs/formatdomaincaps.html.in | 6 ++++++ docs/schemas/domaincaps.rng | 6 ++++++ src/conf/domain_capabilities.c | 4 ++++ src/conf/domain_capabilities.h | 2 ++ tests/domaincapsdata/qemu_2.12.0-q35.x86_64.xml | 2 ++ tests/domaincapsdata/qemu_2.12.0-tcg.x86_64.xml | 2 ++ tests/domaincapsdata/qemu_2.12.0.x86_64.xml | 2 ++ tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml | 2 ++ tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml | 2 ++ tests/domaincapsdata/qemu_6.0.0.x86_64.xml | 2 ++ 10 files changed, 30 insertions(+)
Reviewed-by: Peter Krempa <pkrempa@redhat.com>

There are limits on the number of SEV/SEV-ES guests that can be run on machines, which may be influenced by firmware settings. This is important to expose to users. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- include/libvirt/libvirt-host.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/libvirt/libvirt-host.h b/include/libvirt/libvirt-host.h index 4caed94a77..1dc4b8a147 100644 --- a/include/libvirt/libvirt-host.h +++ b/include/libvirt/libvirt-host.h @@ -472,6 +472,22 @@ typedef virNodeMemoryStats *virNodeMemoryStatsPtr; */ # define VIR_NODE_SEV_REDUCED_PHYS_BITS "reduced-phys-bits" +/** + * VIR_NODE_SEV_MAX_GUESTS: + * + * Macro represents the number of SEV guests that can + * be run on the host, as a VIR_TYPED_PARAM_UINT. + */ +# define VIR_NODE_SEV_MAX_GUESTS "max-guests" + +/** + * VIR_NODE_SEV_MAX_ES_GUESTS: + * + * Macro represents the number of SEV-ES guests that can + * be run on the host, as a VIR_TYPED_PARAM_UINT. + */ +# define VIR_NODE_SEV_MAX_ES_GUESTS "max-es-guests" + int virNodeGetSEVInfo (virConnectPtr conn, virTypedParameterPtr *params, int *nparams, -- 2.33.1

On Fri, Dec 10, 2021 at 11:37:31 +0000, Daniel P. Berrangé wrote:
There are limits on the number of SEV/SEV-ES guests that can be run on machines, which may be influenced by firmware settings. This is important to expose to users.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- include/libvirt/libvirt-host.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
As noted before, it's a shame that we don't cross-link these macros with the API function in any autmatic way. Reviewed-by: Peter Krempa <pkrempa@redhat.com>

Different CPU generations have different limits on the number of SEV/SEV-ES guests that can be run. Since both limits come from the same overall set, there is typically also BIOS config to set the tradeoff betweeen SEV and SEV-ES guest limits. This is important information to expose for a mgmt application scheduling guests to hosts. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_capabilities.c | 38 +++++++++++++++++++ src/qemu/qemu_driver.c | 10 +++++ .../domaincapsdata/qemu_2.12.0-q35.x86_64.xml | 2 +- .../domaincapsdata/qemu_2.12.0-tcg.x86_64.xml | 2 +- tests/domaincapsdata/qemu_2.12.0.x86_64.xml | 2 +- .../domaincapsdata/qemu_6.0.0-q35.x86_64.xml | 2 +- .../domaincapsdata/qemu_6.0.0-tcg.x86_64.xml | 2 +- tests/domaincapsdata/qemu_6.0.0.x86_64.xml | 2 +- 8 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 4ffd0a98a2..456ce1b72e 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -1897,6 +1897,8 @@ virQEMUCapsSEVInfoCopy(virSEVCapability **dst, tmp->cbitpos = src->cbitpos; tmp->reduced_phys_bits = src->reduced_phys_bits; + tmp->max_guests = src->max_guests; + tmp->max_es_guests = src->max_es_guests; *dst = g_steal_pointer(&tmp); return 0; @@ -3286,6 +3288,30 @@ virQEMUCapsProbeQMPGICCapabilities(virQEMUCaps *qemuCaps, } +static void +virQEMUCapsGetSEVMaxGuests(virSEVCapability *caps) +{ +# if __x86_64__ + uint32_t eax, ebx, ecx, edx; + asm("xor %%ebx, %%ebx;" /* clear the other registers as some cpuid */ + "xor %%edx, %%edx;" /* functions may use them as additional arguments */ + "cpuid;" + : "=a" (eax), + "=b" (ebx), + "=c" (ecx), + "=d" (edx) + : "0" (0x8000001F), + "c" (0) + : "cc"); + + caps->max_guests = ecx - edx + 1; + caps->max_es_guests = edx - 1; +# else + VIR_WARN("Unexpectedly asked for SEV guest count on non-x86_64 arch"); + caps->max_guests = caps->max_es_guests = 0; +# endif +} + static int virQEMUCapsProbeQMPSEVCapabilities(virQEMUCaps *qemuCaps, qemuMonitor *mon) @@ -3305,6 +3331,8 @@ virQEMUCapsProbeQMPSEVCapabilities(virQEMUCaps *qemuCaps, return 0; } + virQEMUCapsGetSEVMaxGuests(caps); + virSEVCapabilitiesFree(qemuCaps->sevCapabilities); qemuCaps->sevCapabilities = caps; return 0; @@ -4084,6 +4112,14 @@ virQEMUCapsParseSEVInfo(virQEMUCaps *qemuCaps, xmlXPathContextPtr ctxt) return -1; } + + /* We probe this every time because the values + * can change on every reboot via firmware + * config tunables. It is cheap to query so + * lack of caching is a non-issue + */ + virQEMUCapsGetSEVMaxGuests(sev); + qemuCaps->sevCapabilities = g_steal_pointer(&sev); return 0; } @@ -6344,6 +6380,8 @@ virQEMUCapsFillDomainFeatureSEVCaps(virQEMUCaps *qemuCaps, domCaps->sev->cert_chain = g_strdup(cap->cert_chain); domCaps->sev->cbitpos = cap->cbitpos; domCaps->sev->reduced_phys_bits = cap->reduced_phys_bits; + domCaps->sev->max_guests = cap->max_guests; + domCaps->sev->max_es_guests = cap->max_es_guests; } diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 1bf1938634..572e09be9f 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -19934,6 +19934,16 @@ qemuGetSEVInfoToParams(virQEMUCaps *qemuCaps, sev->reduced_phys_bits) < 0) goto cleanup; + if (virTypedParamsAddUInt(&sevParams, &n, &maxpar, + VIR_NODE_SEV_MAX_GUESTS, + sev->max_guests) < 0) + goto cleanup; + + if (virTypedParamsAddUInt(&sevParams, &n, &maxpar, + VIR_NODE_SEV_MAX_ES_GUESTS, + sev->max_es_guests) < 0) + goto cleanup; + *params = g_steal_pointer(&sevParams); *nparams = n; return 0; diff --git a/tests/domaincapsdata/qemu_2.12.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_2.12.0-q35.x86_64.xml index 26816ff066..6956f9af07 100644 --- a/tests/domaincapsdata/qemu_2.12.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_2.12.0-q35.x86_64.xml @@ -205,7 +205,7 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> - <maxGuests>0</maxGuests> + <maxGuests>15</maxGuests> <maxESGuests>0</maxESGuests> </sev> </features> diff --git a/tests/domaincapsdata/qemu_2.12.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_2.12.0-tcg.x86_64.xml index 5840a8b921..c6408d154c 100644 --- a/tests/domaincapsdata/qemu_2.12.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_2.12.0-tcg.x86_64.xml @@ -215,7 +215,7 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> - <maxGuests>0</maxGuests> + <maxGuests>15</maxGuests> <maxESGuests>0</maxESGuests> </sev> </features> diff --git a/tests/domaincapsdata/qemu_2.12.0.x86_64.xml b/tests/domaincapsdata/qemu_2.12.0.x86_64.xml index 21d1b6946e..918439e4a0 100644 --- a/tests/domaincapsdata/qemu_2.12.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_2.12.0.x86_64.xml @@ -205,7 +205,7 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> - <maxGuests>0</maxGuests> + <maxGuests>15</maxGuests> <maxESGuests>0</maxESGuests> </sev> </features> diff --git a/tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml index 3415d44019..8733b79a31 100644 --- a/tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml @@ -227,7 +227,7 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> - <maxGuests>0</maxGuests> + <maxGuests>15</maxGuests> <maxESGuests>0</maxESGuests> </sev> </features> diff --git a/tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml index f58be3af6c..0382bdaf5a 100644 --- a/tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml @@ -233,7 +233,7 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> - <maxGuests>0</maxGuests> + <maxGuests>15</maxGuests> <maxESGuests>0</maxESGuests> </sev> </features> diff --git a/tests/domaincapsdata/qemu_6.0.0.x86_64.xml b/tests/domaincapsdata/qemu_6.0.0.x86_64.xml index 0a2615c519..30ea787a75 100644 --- a/tests/domaincapsdata/qemu_6.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.0.0.x86_64.xml @@ -227,7 +227,7 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> - <maxGuests>0</maxGuests> + <maxGuests>15</maxGuests> <maxESGuests>0</maxESGuests> </sev> </features> -- 2.33.1

On Fri, Dec 10, 2021 at 11:37:32 +0000, Daniel P. Berrangé wrote:
Different CPU generations have different limits on the number of SEV/SEV-ES guests that can be run. Since both limits come from the same overall set, there is typically also BIOS config to set the tradeoff betweeen SEV and SEV-ES guest limits.
This is important information to expose for a mgmt application scheduling guests to hosts.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_capabilities.c | 38 +++++++++++++++++++ src/qemu/qemu_driver.c | 10 +++++ .../domaincapsdata/qemu_2.12.0-q35.x86_64.xml | 2 +- .../domaincapsdata/qemu_2.12.0-tcg.x86_64.xml | 2 +- tests/domaincapsdata/qemu_2.12.0.x86_64.xml | 2 +- .../domaincapsdata/qemu_6.0.0-q35.x86_64.xml | 2 +- .../domaincapsdata/qemu_6.0.0-tcg.x86_64.xml | 2 +- tests/domaincapsdata/qemu_6.0.0.x86_64.xml | 2 +- 8 files changed, 54 insertions(+), 6 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 4ffd0a98a2..456ce1b72e 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -1897,6 +1897,8 @@ virQEMUCapsSEVInfoCopy(virSEVCapability **dst,
tmp->cbitpos = src->cbitpos; tmp->reduced_phys_bits = src->reduced_phys_bits; + tmp->max_guests = src->max_guests; + tmp->max_es_guests = src->max_es_guests;
*dst = g_steal_pointer(&tmp); return 0; @@ -3286,6 +3288,30 @@ virQEMUCapsProbeQMPGICCapabilities(virQEMUCaps *qemuCaps, }
+static void +virQEMUCapsGetSEVMaxGuests(virSEVCapability *caps) +{ +# if __x86_64__
cppi: /home/pipo/libvirt/src/qemu/qemu_capabilities.c: line 3294: not properly indented
+ uint32_t eax, ebx, ecx, edx; + asm("xor %%ebx, %%ebx;" /* clear the other registers as some cpuid */ + "xor %%edx, %%edx;" /* functions may use them as additional arguments */ + "cpuid;" + : "=a" (eax), + "=b" (ebx),
Since the code doesn't use 'eax' and 'ebx' you can remove it and add it to the clobbers section along with "cc".
+ "=c" (ecx), + "=d" (edx) + : "0" (0x8000001F), + "c" (0) + : "cc"); +
A comment what the data in 'ecx' and 'edx' is would be helpful even when it's obvious on a second look
+ caps->max_guests = ecx - edx + 1; + caps->max_es_guests = edx - 1; +# else + VIR_WARN("Unexpectedly asked for SEV guest count on non-x86_64 arch"); + caps->max_guests = caps->max_es_guests = 0; +# endif +} + static int virQEMUCapsProbeQMPSEVCapabilities(virQEMUCaps *qemuCaps, qemuMonitor *mon) @@ -3305,6 +3331,8 @@ virQEMUCapsProbeQMPSEVCapabilities(virQEMUCaps *qemuCaps, return 0; }
+ virQEMUCapsGetSEVMaxGuests(caps);
This code ...
+ virSEVCapabilitiesFree(qemuCaps->sevCapabilities); qemuCaps->sevCapabilities = caps; return 0; @@ -4084,6 +4112,14 @@ virQEMUCapsParseSEVInfo(virQEMUCaps *qemuCaps, xmlXPathContextPtr ctxt) return -1; }
+ + /* We probe this every time because the values + * can change on every reboot via firmware + * config tunables. It is cheap to query so + * lack of caching is a non-issue + */ + virQEMUCapsGetSEVMaxGuests(sev);
... and this code is executed also in context of e.g. qemudomaincapstest, so the results are changing based on where you run it, e.g. as on my box: - <maxGuests>15</maxGuests> + <maxGuests>509</maxGuests> So this method definitely is not suitable for implementation as in this patch. Since we already have code digging trhough 'cpuid' it feels that it should be a better place to do so.

Normally the SEV measurement only covers the firmware loader contents. When doing a direct kernel boot, however, with new enough OVMF it is possible to ask for the measurement to cover the kernel, ramdisk and command line. It can't be done automatically as that would break existing guests using direct kernel boot with old firmware, so there is a new XML setting allowing this behaviour to be toggled. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- docs/formatdomain.rst | 7 ++++++- docs/schemas/domaincommon.rng | 5 +++++ src/conf/domain_conf.c | 8 ++++++++ src/conf/domain_conf.h | 1 + 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index eb8c973cf1..c6e1f2226a 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -8191,7 +8191,7 @@ spec <https://support.amd.com/TechDocs/55766_SEV-KM_API_Specification.pdf>`__ <domain> ... - <launchSecurity type='sev'> + <launchSecurity type='sev' kernelHashes='yes'> <policy>0x0001</policy> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> @@ -8201,6 +8201,11 @@ spec <https://support.amd.com/TechDocs/55766_SEV-KM_API_Specification.pdf>`__ ... </domain> +``kernelHashes`` + The optional ``kernelHashes`` attribute indicates whether the + hashes of the kernel, ramdisk and command line should be included + in the measurement done by the firmware. This is only valid if + using direct kernel boot. :since:`Since 8.0.0` ``cbitpos`` The required ``cbitpos`` element provides the C-bit (aka encryption bit) location in guest page table entry. The value of ``cbitpos`` is hypervisor diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index f01b7a6470..8fe6134935 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -499,6 +499,11 @@ <attribute name="type"> <value>sev</value> </attribute> + <optional> + <attribute name="kernelHashes"> + <ref name="virYesNo"/> + </attribute> + </optional> <interleave> <optional> <element name="cbitpos"> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 107d2a4f5d..86cd124c4a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -14793,6 +14793,10 @@ virDomainSEVDefParseXML(virDomainSEVDef *def, unsigned long policy; int rc; + if (virXMLPropTristateBool(ctxt->node, "kernelHashes", VIR_XML_PROP_NONE, + &def->kernel_hashes) < 0) + return -1; + if (virXPathULongHex("string(./policy)", ctxt, &policy) < 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("failed to get launch security policy")); @@ -27056,6 +27060,10 @@ virDomainSecDefFormat(virBuffer *buf, virDomainSecDef *sec) case VIR_DOMAIN_LAUNCH_SECURITY_SEV: { virDomainSEVDef *sev = &sec->data.sev; + if (sev->kernel_hashes != VIR_TRISTATE_BOOL_ABSENT) + virBufferAsprintf(&attrBuf, " kernelHashes='%s'", + virTristateBoolTypeToString(sev->kernel_hashes)); + if (sev->haveCbitpos) virBufferAsprintf(&childBuf, "<cbitpos>%d</cbitpos>\n", sev->cbitpos); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index c0c07ea6ba..8e576c00f8 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2692,6 +2692,7 @@ struct _virDomainSEVDef { unsigned int cbitpos; bool haveReducedPhysBits; unsigned int reduced_phys_bits; + virTristateBool kernel_hashes; }; struct _virDomainSecDef { -- 2.33.1

On Fri, Dec 10, 2021 at 11:37:33 +0000, Daniel P. Berrangé wrote:
Normally the SEV measurement only covers the firmware loader contents. When doing a direct kernel boot, however, with new enough OVMF it is possible to ask for the measurement to cover the kernel, ramdisk and command line.
It can't be done automatically as that would break existing guests using direct kernel boot with old firmware, so there is a new XML setting allowing this behaviour to be toggled.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- docs/formatdomain.rst | 7 ++++++- docs/schemas/domaincommon.rng | 5 +++++ src/conf/domain_conf.c | 8 ++++++++ src/conf/domain_conf.h | 1 + 4 files changed, 20 insertions(+), 1 deletion(-)
Reviewed-by: Peter Krempa <pkrempa@redhat.com>

This sev-guest object property indicates whether QEMU should expose the kernel, ramdisk, cmdline hashes to the firmware for measurement. The 6.2.0 capabilities are hacked to look as if they were generated with sev-guest support. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_capabilities.c | 8 ++ src/qemu/qemu_capabilities.h | 1 + .../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 7 +- .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 7 +- tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 7 +- .../caps_2.12.0.x86_64.replies | 97 ++++++++++++---- .../caps_3.0.0.x86_64.replies | 97 ++++++++++++---- .../caps_3.1.0.x86_64.replies | 97 ++++++++++++---- .../caps_4.0.0.x86_64.replies | 97 ++++++++++++---- .../caps_4.1.0.x86_64.replies | 89 ++++++++++---- .../caps_4.2.0.x86_64.replies | 89 ++++++++++---- .../caps_5.0.0.x86_64.replies | 89 ++++++++++---- .../caps_5.1.0.x86_64.replies | 89 ++++++++++---- .../caps_5.2.0.x86_64.replies | 89 ++++++++++---- .../caps_6.0.0.x86_64.replies | 89 ++++++++++---- .../caps_6.1.0.x86_64.replies | 89 ++++++++++---- .../caps_6.2.0.x86_64.replies | 109 ++++++++++++++---- .../caps_6.2.0.x86_64.xml | 8 ++ 18 files changed, 895 insertions(+), 263 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 456ce1b72e..fbcb67713e 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -652,6 +652,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "device.json", /* QEMU_CAPS_DEVICE_JSON */ "query-dirty-rate", /* QEMU_CAPS_QUERY_DIRTY_RATE */ "rbd-encryption", /* QEMU_CAPS_RBD_ENCRYPTION */ + "sev-guest-kernel-hashes", /* QEMU_CAPS_SEV_GUEST_KERNEL_HASHES */ ); @@ -1718,6 +1719,10 @@ static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsMaxCPU[] = { { "migratable", QEMU_CAPS_CPU_MIGRATABLE }, }; +static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsSEVGuest[] = { + { "kernel-hashes", QEMU_CAPS_SEV_GUEST_KERNEL_HASHES }, +}; + static virQEMUCapsObjectTypeProps virQEMUCapsObjectProps[] = { { "memory-backend-file", virQEMUCapsObjectPropsMemoryBackendFile, G_N_ELEMENTS(virQEMUCapsObjectPropsMemoryBackendFile), @@ -1731,6 +1736,9 @@ static virQEMUCapsObjectTypeProps virQEMUCapsObjectProps[] = { { "max-arm-cpu", virQEMUCapsObjectPropsMaxCPU, G_N_ELEMENTS(virQEMUCapsObjectPropsMaxCPU), QEMU_CAPS_ARM_MAX_CPU }, + { "sev-guest", virQEMUCapsObjectPropsSEVGuest, + G_N_ELEMENTS(virQEMUCapsObjectPropsSEVGuest), + QEMU_CAPS_SEV_GUEST }, }; static struct virQEMUCapsStringFlags virQEMUCapsMachinePropsPSeries[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 716e09123c..aaac20a834 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -631,6 +631,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_DEVICE_JSON, /* -device accepts JSON */ QEMU_CAPS_QUERY_DIRTY_RATE, /* accepts query-dirty-rate */ QEMU_CAPS_RBD_ENCRYPTION, /* Ceph RBD encryption support */ + QEMU_CAPS_SEV_GUEST_KERNEL_HASHES, /* sev-guest.kernel-hashes= */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml index 9d68c0a404..28d4f38fef 100644 --- a/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml @@ -225,6 +225,11 @@ <genid supported='yes'/> <backingStoreInput supported='yes'/> <backup supported='yes'/> - <sev supported='no'/> + <sev supported='yes'> + <cbitpos>47</cbitpos> + <reducedPhysBits>1</reducedPhysBits> + <maxGuests>15</maxGuests> + <maxESGuests>0</maxESGuests> + </sev> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml index 8db840faac..711a77ccd1 100644 --- a/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml @@ -231,6 +231,11 @@ <genid supported='yes'/> <backingStoreInput supported='yes'/> <backup supported='yes'/> - <sev supported='no'/> + <sev supported='yes'> + <cbitpos>47</cbitpos> + <reducedPhysBits>1</reducedPhysBits> + <maxGuests>15</maxGuests> + <maxESGuests>0</maxESGuests> + </sev> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.2.0.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0.x86_64.xml index 0f89790b60..b0fb1e11cd 100644 --- a/tests/domaincapsdata/qemu_6.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0.x86_64.xml @@ -225,6 +225,11 @@ <genid supported='yes'/> <backingStoreInput supported='yes'/> <backup supported='yes'/> - <sev supported='no'/> + <sev supported='yes'> + <cbitpos>47</cbitpos> + <reducedPhysBits>1</reducedPhysBits> + <maxGuests>15</maxGuests> + <maxESGuests>0</maxESGuests> + </sev> </features> </domainCapabilities> diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies index 5fefbc64ab..c5bdd5398b 100644 --- a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies @@ -17361,10 +17361,59 @@ } { - "execute": "query-machines", + "execute": "qom-list-properties", + "arguments": { + "typename": "sev-guest" + }, "id": "libvirt-40" } +{ + "return": [ + { + "name": "type", + "type": "string" + }, + { + "name": "dh-cert-file", + "description": "guest owners DH certificate (encoded with base64)", + "type": "string" + }, + { + "name": "sev-device", + "description": "SEV device to use", + "type": "string" + }, + { + "name": "session-file", + "description": "guest owners session parameters (encoded with base64)", + "type": "string" + }, + { + "name": "handle", + "type": "uint32" + }, + { + "name": "policy", + "type": "uint32" + }, + { + "name": "reduced-phys-bits", + "type": "uint32" + }, + { + "name": "cbitpos", + "type": "uint32" + } + ], + "id": "libvirt-40" +} + +{ + "execute": "query-machines", + "id": "libvirt-41" +} + { "return": [ { @@ -17561,7 +17610,7 @@ "cpu-max": 255 } ], - "id": "libvirt-40" + "id": "libvirt-41" } { @@ -17569,7 +17618,7 @@ "arguments": { "typename": "none-machine" }, - "id": "libvirt-41" + "id": "libvirt-42" } { @@ -17674,12 +17723,12 @@ "type": "string" } ], - "id": "libvirt-41" + "id": "libvirt-42" } { "execute": "query-cpu-definitions", - "id": "libvirt-42" + "id": "libvirt-43" } { @@ -18193,12 +18242,12 @@ "migration-safe": true } ], - "id": "libvirt-42" + "id": "libvirt-43" } { "execute": "query-tpm-models", - "id": "libvirt-43" + "id": "libvirt-44" } { @@ -18206,12 +18255,12 @@ "tpm-crb", "tpm-tis" ], - "id": "libvirt-43" + "id": "libvirt-44" } { "execute": "query-tpm-types", - "id": "libvirt-44" + "id": "libvirt-45" } { @@ -18219,12 +18268,12 @@ "passthrough", "emulator" ], - "id": "libvirt-44" + "id": "libvirt-45" } { "execute": "query-command-line-options", - "id": "libvirt-45" + "id": "libvirt-46" } { @@ -19511,12 +19560,12 @@ "option": "drive" } ], - "id": "libvirt-45" + "id": "libvirt-46" } { "execute": "query-migrate-capabilities", - "id": "libvirt-46" + "id": "libvirt-47" } { @@ -19578,12 +19627,12 @@ "capability": "dirty-bitmaps" } ], - "id": "libvirt-46" + "id": "libvirt-47" } { "execute": "query-sev-capabilities", - "id": "libvirt-47" + "id": "libvirt-48" } { @@ -19593,7 +19642,7 @@ "cert-chain": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA", "pdh": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA" }, - "id": "libvirt-47" + "id": "libvirt-48" } { @@ -19604,7 +19653,7 @@ "name": "host" } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -19794,7 +19843,7 @@ } } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -19986,7 +20035,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -20241,7 +20290,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -20255,7 +20304,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { @@ -20445,7 +20494,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { @@ -20637,7 +20686,7 @@ } } }, - "id": "libvirt-51" + "id": "libvirt-52" } { @@ -20892,7 +20941,7 @@ } } }, - "id": "libvirt-51" + "id": "libvirt-52" } { diff --git a/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.replies index a63d1d8118..bc1ff6527d 100644 --- a/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.replies @@ -18035,10 +18035,59 @@ } { - "execute": "query-machines", + "execute": "qom-list-properties", + "arguments": { + "typename": "sev-guest" + }, + "id": "libvirt-40" +} + +{ + "return": [ + { + "name": "type", + "type": "string" + }, + { + "name": "dh-cert-file", + "description": "guest owners DH certificate (encoded with base64)", + "type": "string" + }, + { + "name": "sev-device", + "description": "SEV device to use", + "type": "string" + }, + { + "name": "session-file", + "description": "guest owners session parameters (encoded with base64)", + "type": "string" + }, + { + "name": "handle", + "type": "uint32" + }, + { + "name": "policy", + "type": "uint32" + }, + { + "name": "reduced-phys-bits", + "type": "uint32" + }, + { + "name": "cbitpos", + "type": "uint32" + } + ], "id": "libvirt-40" } +{ + "execute": "query-machines", + "id": "libvirt-41" +} + { "return": [ { @@ -18245,7 +18294,7 @@ "cpu-max": 255 } ], - "id": "libvirt-40" + "id": "libvirt-41" } { @@ -18253,7 +18302,7 @@ "arguments": { "typename": "none-machine" }, - "id": "libvirt-41" + "id": "libvirt-42" } { @@ -18358,12 +18407,12 @@ "type": "string" } ], - "id": "libvirt-41" + "id": "libvirt-42" } { "execute": "query-cpu-definitions", - "id": "libvirt-42" + "id": "libvirt-43" } { @@ -18800,12 +18849,12 @@ "migration-safe": true } ], - "id": "libvirt-42" + "id": "libvirt-43" } { "execute": "query-tpm-models", - "id": "libvirt-43" + "id": "libvirt-44" } { @@ -18813,12 +18862,12 @@ "tpm-crb", "tpm-tis" ], - "id": "libvirt-43" + "id": "libvirt-44" } { "execute": "query-tpm-types", - "id": "libvirt-44" + "id": "libvirt-45" } { @@ -18826,12 +18875,12 @@ "passthrough", "emulator" ], - "id": "libvirt-44" + "id": "libvirt-45" } { "execute": "query-command-line-options", - "id": "libvirt-45" + "id": "libvirt-46" } { @@ -20130,12 +20179,12 @@ "option": "drive" } ], - "id": "libvirt-45" + "id": "libvirt-46" } { "execute": "query-migrate-capabilities", - "id": "libvirt-46" + "id": "libvirt-47" } { @@ -20205,16 +20254,16 @@ "capability": "late-block-activate" } ], - "id": "libvirt-46" + "id": "libvirt-47" } { "execute": "query-sev-capabilities", - "id": "libvirt-47" + "id": "libvirt-48" } { - "id": "libvirt-47", + "id": "libvirt-48", "error": { "class": "GenericError", "desc": "SEV feature is not available" @@ -20229,7 +20278,7 @@ "name": "host" } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -20422,7 +20471,7 @@ } } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -20617,7 +20666,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -20880,7 +20929,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -20894,7 +20943,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { @@ -21087,7 +21136,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { @@ -21282,7 +21331,7 @@ } } }, - "id": "libvirt-51" + "id": "libvirt-52" } { @@ -21545,7 +21594,7 @@ } } }, - "id": "libvirt-51" + "id": "libvirt-52" } { diff --git a/tests/qemucapabilitiesdata/caps_3.1.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_3.1.0.x86_64.replies index d021745a06..8bec154b10 100644 --- a/tests/qemucapabilitiesdata/caps_3.1.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_3.1.0.x86_64.replies @@ -18452,10 +18452,59 @@ } { - "execute": "query-machines", + "execute": "qom-list-properties", + "arguments": { + "typename": "sev-guest" + }, + "id": "libvirt-40" +} + +{ + "return": [ + { + "name": "type", + "type": "string" + }, + { + "name": "dh-cert-file", + "description": "guest owners DH certificate (encoded with base64)", + "type": "string" + }, + { + "name": "sev-device", + "description": "SEV device to use", + "type": "string" + }, + { + "name": "session-file", + "description": "guest owners session parameters (encoded with base64)", + "type": "string" + }, + { + "name": "handle", + "type": "uint32" + }, + { + "name": "policy", + "type": "uint32" + }, + { + "name": "reduced-phys-bits", + "type": "uint32" + }, + { + "name": "cbitpos", + "type": "uint32" + } + ], "id": "libvirt-40" } +{ + "execute": "query-machines", + "id": "libvirt-41" +} + { "return": [ { @@ -18672,7 +18721,7 @@ "cpu-max": 255 } ], - "id": "libvirt-40" + "id": "libvirt-41" } { @@ -18680,7 +18729,7 @@ "arguments": { "typename": "none-machine" }, - "id": "libvirt-41" + "id": "libvirt-42" } { @@ -18785,12 +18834,12 @@ "type": "int" } ], - "id": "libvirt-41" + "id": "libvirt-42" } { "execute": "query-cpu-definitions", - "id": "libvirt-42" + "id": "libvirt-43" } { @@ -19309,12 +19358,12 @@ "migration-safe": true } ], - "id": "libvirt-42" + "id": "libvirt-43" } { "execute": "query-tpm-models", - "id": "libvirt-43" + "id": "libvirt-44" } { @@ -19322,12 +19371,12 @@ "tpm-crb", "tpm-tis" ], - "id": "libvirt-43" + "id": "libvirt-44" } { "execute": "query-tpm-types", - "id": "libvirt-44" + "id": "libvirt-45" } { @@ -19335,12 +19384,12 @@ "passthrough", "emulator" ], - "id": "libvirt-44" + "id": "libvirt-45" } { "execute": "query-command-line-options", - "id": "libvirt-45" + "id": "libvirt-46" } { @@ -20614,12 +20663,12 @@ "option": "drive" } ], - "id": "libvirt-45" + "id": "libvirt-46" } { "execute": "query-migrate-capabilities", - "id": "libvirt-46" + "id": "libvirt-47" } { @@ -20689,16 +20738,16 @@ "capability": "late-block-activate" } ], - "id": "libvirt-46" + "id": "libvirt-47" } { "execute": "query-sev-capabilities", - "id": "libvirt-47" + "id": "libvirt-48" } { - "id": "libvirt-47", + "id": "libvirt-48", "error": { "class": "GenericError", "desc": "SEV feature is not available" @@ -20713,7 +20762,7 @@ "name": "host" } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -20915,7 +20964,7 @@ } } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -21119,7 +21168,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -21394,7 +21443,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -21408,7 +21457,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { @@ -21610,7 +21659,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { @@ -21814,7 +21863,7 @@ } } }, - "id": "libvirt-51" + "id": "libvirt-52" } { @@ -22089,7 +22138,7 @@ } } }, - "id": "libvirt-51" + "id": "libvirt-52" } { diff --git a/tests/qemucapabilitiesdata/caps_4.0.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_4.0.0.x86_64.replies index 5de9457eed..8a44f5e24a 100644 --- a/tests/qemucapabilitiesdata/caps_4.0.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_4.0.0.x86_64.replies @@ -18981,10 +18981,59 @@ } { - "execute": "query-machines", + "execute": "qom-list-properties", + "arguments": { + "typename": "sev-guest" + }, + "id": "libvirt-40" +} + +{ + "return": [ + { + "name": "type", + "type": "string" + }, + { + "name": "dh-cert-file", + "description": "guest owners DH certificate (encoded with base64)", + "type": "string" + }, + { + "name": "sev-device", + "description": "SEV device to use", + "type": "string" + }, + { + "name": "session-file", + "description": "guest owners session parameters (encoded with base64)", + "type": "string" + }, + { + "name": "handle", + "type": "uint32" + }, + { + "name": "policy", + "type": "uint32" + }, + { + "name": "reduced-phys-bits", + "type": "uint32" + }, + { + "name": "cbitpos", + "type": "uint32" + } + ], "id": "libvirt-40" } +{ + "execute": "query-machines", + "id": "libvirt-41" +} + { "return": [ { @@ -19201,7 +19250,7 @@ "alias": "q35" } ], - "id": "libvirt-40" + "id": "libvirt-41" } { @@ -19209,7 +19258,7 @@ "arguments": { "typename": "none-machine" }, - "id": "libvirt-41" + "id": "libvirt-42" } { @@ -19314,12 +19363,12 @@ "type": "bool" } ], - "id": "libvirt-41" + "id": "libvirt-42" } { "execute": "query-cpu-definitions", - "id": "libvirt-42" + "id": "libvirt-43" } { @@ -19836,12 +19885,12 @@ "migration-safe": true } ], - "id": "libvirt-42" + "id": "libvirt-43" } { "execute": "query-tpm-models", - "id": "libvirt-43" + "id": "libvirt-44" } { @@ -19849,12 +19898,12 @@ "tpm-crb", "tpm-tis" ], - "id": "libvirt-43" + "id": "libvirt-44" } { "execute": "query-tpm-types", - "id": "libvirt-44" + "id": "libvirt-45" } { @@ -19862,12 +19911,12 @@ "passthrough", "emulator" ], - "id": "libvirt-44" + "id": "libvirt-45" } { "execute": "query-command-line-options", - "id": "libvirt-45" + "id": "libvirt-46" } { @@ -21149,12 +21198,12 @@ "option": "drive" } ], - "id": "libvirt-45" + "id": "libvirt-46" } { "execute": "query-migrate-capabilities", - "id": "libvirt-46" + "id": "libvirt-47" } { @@ -21228,16 +21277,16 @@ "capability": "x-ignore-shared" } ], - "id": "libvirt-46" + "id": "libvirt-47" } { "execute": "query-sev-capabilities", - "id": "libvirt-47" + "id": "libvirt-48" } { - "id": "libvirt-47", + "id": "libvirt-48", "error": { "class": "GenericError", "desc": "SEV feature is not available" @@ -21252,7 +21301,7 @@ "name": "host" } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -21456,7 +21505,7 @@ } } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -21662,7 +21711,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -21941,7 +21990,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -21955,7 +22004,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { @@ -22159,7 +22208,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { @@ -22365,7 +22414,7 @@ } } }, - "id": "libvirt-51" + "id": "libvirt-52" } { @@ -22644,7 +22693,7 @@ } } }, - "id": "libvirt-51" + "id": "libvirt-52" } { diff --git a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies index 0dadabf948..7d5ef93f16 100644 --- a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies @@ -19441,10 +19441,59 @@ } { - "execute": "query-machines", + "execute": "qom-list-properties", + "arguments": { + "typename": "sev-guest" + }, "id": "libvirt-40" } +{ + "return": [ + { + "name": "type", + "type": "string" + }, + { + "name": "dh-cert-file", + "description": "guest owners DH certificate (encoded with base64)", + "type": "string" + }, + { + "name": "sev-device", + "description": "SEV device to use", + "type": "string" + }, + { + "name": "session-file", + "description": "guest owners session parameters (encoded with base64)", + "type": "string" + }, + { + "name": "handle", + "type": "uint32" + }, + { + "name": "policy", + "type": "uint32" + }, + { + "name": "reduced-phys-bits", + "type": "uint32" + }, + { + "name": "cbitpos", + "type": "uint32" + } + ], + "id": "libvirt-40" +} + +{ + "execute": "query-machines", + "id": "libvirt-41" +} + { "return": [ { @@ -19766,7 +19815,7 @@ "deprecated": false } ], - "id": "libvirt-40" + "id": "libvirt-41" } { @@ -19774,7 +19823,7 @@ "arguments": { "typename": "none-machine" }, - "id": "libvirt-41" + "id": "libvirt-42" } { @@ -19879,12 +19928,12 @@ "type": "bool" } ], - "id": "libvirt-41" + "id": "libvirt-42" } { "execute": "query-cpu-definitions", - "id": "libvirt-42" + "id": "libvirt-43" } { @@ -21029,12 +21078,12 @@ "migration-safe": true } ], - "id": "libvirt-42" + "id": "libvirt-43" } { "execute": "query-tpm-models", - "id": "libvirt-43" + "id": "libvirt-44" } { @@ -21042,12 +21091,12 @@ "tpm-crb", "tpm-tis" ], - "id": "libvirt-43" + "id": "libvirt-44" } { "execute": "query-tpm-types", - "id": "libvirt-44" + "id": "libvirt-45" } { @@ -21055,12 +21104,12 @@ "passthrough", "emulator" ], - "id": "libvirt-44" + "id": "libvirt-45" } { "execute": "query-command-line-options", - "id": "libvirt-45" + "id": "libvirt-46" } { @@ -22334,12 +22383,12 @@ "option": "drive" } ], - "id": "libvirt-45" + "id": "libvirt-46" } { "execute": "query-migrate-capabilities", - "id": "libvirt-46" + "id": "libvirt-47" } { @@ -22413,16 +22462,16 @@ "capability": "x-ignore-shared" } ], - "id": "libvirt-46" + "id": "libvirt-47" } { "execute": "query-sev-capabilities", - "id": "libvirt-47" + "id": "libvirt-48" } { - "id": "libvirt-47", + "id": "libvirt-48", "error": { "class": "GenericError", "desc": "SEV feature is not available" @@ -22437,7 +22486,7 @@ "name": "host" } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -22645,7 +22694,7 @@ } } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -22659,7 +22708,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -22867,7 +22916,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { diff --git a/tests/qemucapabilitiesdata/caps_4.2.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_4.2.0.x86_64.replies index cd7a5c345c..e7aae333ec 100644 --- a/tests/qemucapabilitiesdata/caps_4.2.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_4.2.0.x86_64.replies @@ -20483,10 +20483,59 @@ } { - "execute": "query-machines", + "execute": "qom-list-properties", + "arguments": { + "typename": "sev-guest" + }, "id": "libvirt-41" } +{ + "return": [ + { + "name": "type", + "type": "string" + }, + { + "name": "dh-cert-file", + "description": "guest owners DH certificate (encoded with base64)", + "type": "string" + }, + { + "name": "sev-device", + "description": "SEV device to use", + "type": "string" + }, + { + "name": "session-file", + "description": "guest owners session parameters (encoded with base64)", + "type": "string" + }, + { + "name": "handle", + "type": "uint32" + }, + { + "name": "policy", + "type": "uint32" + }, + { + "name": "reduced-phys-bits", + "type": "uint32" + }, + { + "name": "cbitpos", + "type": "uint32" + } + ], + "id": "libvirt-41" +} + +{ + "execute": "query-machines", + "id": "libvirt-42" +} + { "return": [ { @@ -20876,7 +20925,7 @@ "deprecated": false } ], - "id": "libvirt-41" + "id": "libvirt-42" } { @@ -20884,7 +20933,7 @@ "arguments": { "typename": "none-machine" }, - "id": "libvirt-42" + "id": "libvirt-43" } { @@ -20989,12 +21038,12 @@ "type": "bool" } ], - "id": "libvirt-42" + "id": "libvirt-43" } { "execute": "query-cpu-definitions", - "id": "libvirt-43" + "id": "libvirt-44" } { @@ -22377,12 +22426,12 @@ "migration-safe": true } ], - "id": "libvirt-43" + "id": "libvirt-44" } { "execute": "query-tpm-models", - "id": "libvirt-44" + "id": "libvirt-45" } { @@ -22390,12 +22439,12 @@ "tpm-crb", "tpm-tis" ], - "id": "libvirt-44" + "id": "libvirt-45" } { "execute": "query-tpm-types", - "id": "libvirt-45" + "id": "libvirt-46" } { @@ -22403,12 +22452,12 @@ "passthrough", "emulator" ], - "id": "libvirt-45" + "id": "libvirt-46" } { "execute": "query-command-line-options", - "id": "libvirt-46" + "id": "libvirt-47" } { @@ -23694,12 +23743,12 @@ "option": "drive" } ], - "id": "libvirt-46" + "id": "libvirt-47" } { "execute": "query-migrate-capabilities", - "id": "libvirt-47" + "id": "libvirt-48" } { @@ -23777,16 +23826,16 @@ "capability": "validate-uuid" } ], - "id": "libvirt-47" + "id": "libvirt-48" } { "execute": "query-sev-capabilities", - "id": "libvirt-48" + "id": "libvirt-49" } { - "id": "libvirt-48", + "id": "libvirt-49", "error": { "class": "GenericError", "desc": "SEV feature is not available" @@ -23801,7 +23850,7 @@ "name": "host" } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -24103,7 +24152,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -24117,7 +24166,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { @@ -24419,7 +24468,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { diff --git a/tests/qemucapabilitiesdata/caps_5.0.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_5.0.0.x86_64.replies index ad6ee05ba6..7657e7047d 100644 --- a/tests/qemucapabilitiesdata/caps_5.0.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_5.0.0.x86_64.replies @@ -21808,10 +21808,59 @@ } { - "execute": "query-machines", + "execute": "qom-list-properties", + "arguments": { + "typename": "sev-guest" + }, "id": "libvirt-41" } +{ + "return": [ + { + "name": "type", + "type": "string" + }, + { + "name": "dh-cert-file", + "description": "guest owners DH certificate (encoded with base64)", + "type": "string" + }, + { + "name": "sev-device", + "description": "SEV device to use", + "type": "string" + }, + { + "name": "session-file", + "description": "guest owners session parameters (encoded with base64)", + "type": "string" + }, + { + "name": "handle", + "type": "uint32" + }, + { + "name": "policy", + "type": "uint32" + }, + { + "name": "reduced-phys-bits", + "type": "uint32" + }, + { + "name": "cbitpos", + "type": "uint32" + } + ], + "id": "libvirt-41" +} + +{ + "execute": "query-machines", + "id": "libvirt-42" +} + { "return": [ { @@ -22185,7 +22234,7 @@ "deprecated": false } ], - "id": "libvirt-41" + "id": "libvirt-42" } { @@ -22193,7 +22242,7 @@ "arguments": { "typename": "none-machine" }, - "id": "libvirt-42" + "id": "libvirt-43" } { @@ -22283,12 +22332,12 @@ "type": "string" } ], - "id": "libvirt-42" + "id": "libvirt-43" } { "execute": "query-cpu-definitions", - "id": "libvirt-43" + "id": "libvirt-44" } { @@ -23833,12 +23882,12 @@ "migration-safe": true } ], - "id": "libvirt-43" + "id": "libvirt-44" } { "execute": "query-tpm-models", - "id": "libvirt-44" + "id": "libvirt-45" } { @@ -23846,12 +23895,12 @@ "tpm-crb", "tpm-tis" ], - "id": "libvirt-44" + "id": "libvirt-45" } { "execute": "query-tpm-types", - "id": "libvirt-45" + "id": "libvirt-46" } { @@ -23859,12 +23908,12 @@ "passthrough", "emulator" ], - "id": "libvirt-45" + "id": "libvirt-46" } { "execute": "query-command-line-options", - "id": "libvirt-46" + "id": "libvirt-47" } { @@ -25140,12 +25189,12 @@ "option": "drive" } ], - "id": "libvirt-46" + "id": "libvirt-47" } { "execute": "query-migrate-capabilities", - "id": "libvirt-47" + "id": "libvirt-48" } { @@ -25223,16 +25272,16 @@ "capability": "validate-uuid" } ], - "id": "libvirt-47" + "id": "libvirt-48" } { "execute": "query-sev-capabilities", - "id": "libvirt-48" + "id": "libvirt-49" } { - "id": "libvirt-48", + "id": "libvirt-49", "error": { "class": "GenericError", "desc": "SEV feature is not available" @@ -25247,7 +25296,7 @@ "name": "host" } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -25550,7 +25599,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -25564,7 +25613,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { @@ -25867,7 +25916,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { diff --git a/tests/qemucapabilitiesdata/caps_5.1.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_5.1.0.x86_64.replies index b8f3c79026..82f6de7e7e 100644 --- a/tests/qemucapabilitiesdata/caps_5.1.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_5.1.0.x86_64.replies @@ -22375,10 +22375,59 @@ } { - "execute": "query-machines", + "execute": "qom-list-properties", + "arguments": { + "typename": "sev-guest" + }, "id": "libvirt-41" } +{ + "return": [ + { + "name": "type", + "type": "string" + }, + { + "name": "dh-cert-file", + "description": "guest owners DH certificate (encoded with base64)", + "type": "string" + }, + { + "name": "sev-device", + "description": "SEV device to use", + "type": "string" + }, + { + "name": "session-file", + "description": "guest owners session parameters (encoded with base64)", + "type": "string" + }, + { + "name": "handle", + "type": "uint32" + }, + { + "name": "policy", + "type": "uint32" + }, + { + "name": "reduced-phys-bits", + "type": "uint32" + }, + { + "name": "cbitpos", + "type": "uint32" + } + ], + "id": "libvirt-41" +} + +{ + "execute": "query-machines", + "id": "libvirt-42" +} + { "return": [ { @@ -22768,7 +22817,7 @@ "deprecated": false } ], - "id": "libvirt-41" + "id": "libvirt-42" } { @@ -22776,7 +22825,7 @@ "arguments": { "typename": "none-machine" }, - "id": "libvirt-42" + "id": "libvirt-43" } { @@ -22866,12 +22915,12 @@ "type": "string" } ], - "id": "libvirt-42" + "id": "libvirt-43" } { "execute": "query-cpu-definitions", - "id": "libvirt-43" + "id": "libvirt-44" } { @@ -24573,12 +24622,12 @@ "migration-safe": true } ], - "id": "libvirt-43" + "id": "libvirt-44" } { "execute": "query-tpm-models", - "id": "libvirt-44" + "id": "libvirt-45" } { @@ -24586,12 +24635,12 @@ "tpm-crb", "tpm-tis" ], - "id": "libvirt-44" + "id": "libvirt-45" } { "execute": "query-tpm-types", - "id": "libvirt-45" + "id": "libvirt-46" } { @@ -24599,12 +24648,12 @@ "passthrough", "emulator" ], - "id": "libvirt-45" + "id": "libvirt-46" } { "execute": "query-command-line-options", - "id": "libvirt-46" + "id": "libvirt-47" } { @@ -25899,12 +25948,12 @@ "option": "drive" } ], - "id": "libvirt-46" + "id": "libvirt-47" } { "execute": "query-migrate-capabilities", - "id": "libvirt-47" + "id": "libvirt-48" } { @@ -25982,16 +26031,16 @@ "capability": "validate-uuid" } ], - "id": "libvirt-47" + "id": "libvirt-48" } { "execute": "query-sev-capabilities", - "id": "libvirt-48" + "id": "libvirt-49" } { - "id": "libvirt-48", + "id": "libvirt-49", "error": { "class": "GenericError", "desc": "SEV is not enabled in KVM" @@ -26006,7 +26055,7 @@ "name": "host" } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -26314,7 +26363,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -26328,7 +26377,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { @@ -26636,7 +26685,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { diff --git a/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.replies index 54d8db5904..89f0270e27 100644 --- a/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.replies @@ -22982,10 +22982,59 @@ } { - "execute": "query-machines", + "execute": "qom-list-properties", + "arguments": { + "typename": "sev-guest" + }, "id": "libvirt-41" } +{ + "return": [ + { + "name": "type", + "type": "string" + }, + { + "name": "dh-cert-file", + "description": "guest owners DH certificate (encoded with base64)", + "type": "string" + }, + { + "name": "sev-device", + "description": "SEV device to use", + "type": "string" + }, + { + "name": "session-file", + "description": "guest owners session parameters (encoded with base64)", + "type": "string" + }, + { + "name": "handle", + "type": "uint32" + }, + { + "name": "policy", + "type": "uint32" + }, + { + "name": "reduced-phys-bits", + "type": "uint32" + }, + { + "name": "cbitpos", + "type": "uint32" + } + ], + "id": "libvirt-41" +} + +{ + "execute": "query-machines", + "id": "libvirt-42" +} + { "return": [ { @@ -23441,7 +23490,7 @@ "default-ram-id": "pc.ram" } ], - "id": "libvirt-41" + "id": "libvirt-42" } { @@ -23449,7 +23498,7 @@ "arguments": { "typename": "none-machine" }, - "id": "libvirt-42" + "id": "libvirt-43" } { @@ -23534,12 +23583,12 @@ "type": "string" } ], - "id": "libvirt-42" + "id": "libvirt-43" } { "execute": "query-cpu-definitions", - "id": "libvirt-43" + "id": "libvirt-44" } { @@ -25364,12 +25413,12 @@ "deprecated": false } ], - "id": "libvirt-43" + "id": "libvirt-44" } { "execute": "query-tpm-models", - "id": "libvirt-44" + "id": "libvirt-45" } { @@ -25377,12 +25426,12 @@ "tpm-crb", "tpm-tis" ], - "id": "libvirt-44" + "id": "libvirt-45" } { "execute": "query-tpm-types", - "id": "libvirt-45" + "id": "libvirt-46" } { @@ -25390,12 +25439,12 @@ "passthrough", "emulator" ], - "id": "libvirt-45" + "id": "libvirt-46" } { "execute": "query-command-line-options", - "id": "libvirt-46" + "id": "libvirt-47" } { @@ -26690,12 +26739,12 @@ "option": "drive" } ], - "id": "libvirt-46" + "id": "libvirt-47" } { "execute": "query-migrate-capabilities", - "id": "libvirt-47" + "id": "libvirt-48" } { @@ -26773,16 +26822,16 @@ "capability": "validate-uuid" } ], - "id": "libvirt-47" + "id": "libvirt-48" } { "execute": "query-sev-capabilities", - "id": "libvirt-48" + "id": "libvirt-49" } { - "id": "libvirt-48", + "id": "libvirt-49", "error": { "class": "GenericError", "desc": "SEV is not enabled in KVM" @@ -26797,7 +26846,7 @@ "name": "host" } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -27106,7 +27155,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -27120,7 +27169,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { @@ -27429,7 +27478,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { diff --git a/tests/qemucapabilitiesdata/caps_6.0.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_6.0.0.x86_64.replies index 986bb56630..6cda5538a5 100644 --- a/tests/qemucapabilitiesdata/caps_6.0.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_6.0.0.x86_64.replies @@ -24796,10 +24796,59 @@ } { - "execute": "query-machines", + "execute": "qom-list-properties", + "arguments": { + "typename": "sev-guest" + }, "id": "libvirt-41" } +{ + "return": [ + { + "name": "type", + "type": "string" + }, + { + "name": "dh-cert-file", + "description": "guest owners DH certificate (encoded with base64)", + "type": "string" + }, + { + "name": "sev-device", + "description": "SEV device to use", + "type": "string" + }, + { + "name": "session-file", + "description": "guest owners session parameters (encoded with base64)", + "type": "string" + }, + { + "name": "handle", + "type": "uint32" + }, + { + "name": "policy", + "type": "uint32" + }, + { + "name": "reduced-phys-bits", + "type": "uint32" + }, + { + "name": "cbitpos", + "type": "uint32" + } + ], + "id": "libvirt-41" +} + +{ + "execute": "query-machines", + "id": "libvirt-42" +} + { "return": [ { @@ -25244,7 +25293,7 @@ "default-ram-id": "pc.ram" } ], - "id": "libvirt-41" + "id": "libvirt-42" } { @@ -25252,7 +25301,7 @@ "arguments": { "typename": "none-machine" }, - "id": "libvirt-42" + "id": "libvirt-43" } { @@ -25350,12 +25399,12 @@ "type": "child<container>" } ], - "id": "libvirt-42" + "id": "libvirt-43" } { "execute": "query-cpu-definitions", - "id": "libvirt-43" + "id": "libvirt-44" } { @@ -27223,12 +27272,12 @@ "deprecated": false } ], - "id": "libvirt-43" + "id": "libvirt-44" } { "execute": "query-tpm-models", - "id": "libvirt-44" + "id": "libvirt-45" } { @@ -27236,12 +27285,12 @@ "tpm-crb", "tpm-tis" ], - "id": "libvirt-44" + "id": "libvirt-45" } { "execute": "query-tpm-types", - "id": "libvirt-45" + "id": "libvirt-46" } { @@ -27249,12 +27298,12 @@ "passthrough", "emulator" ], - "id": "libvirt-45" + "id": "libvirt-46" } { "execute": "query-command-line-options", - "id": "libvirt-46" + "id": "libvirt-47" } { @@ -28573,12 +28622,12 @@ "option": "drive" } ], - "id": "libvirt-46" + "id": "libvirt-47" } { "execute": "query-migrate-capabilities", - "id": "libvirt-47" + "id": "libvirt-48" } { @@ -28660,12 +28709,12 @@ "capability": "background-snapshot" } ], - "id": "libvirt-47" + "id": "libvirt-48" } { "execute": "query-sev-capabilities", - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -28675,7 +28724,7 @@ "cert-chain": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA", "pdh": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA" }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -28686,7 +28735,7 @@ "name": "host" } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -29007,7 +29056,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -29021,7 +29070,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { @@ -29342,7 +29391,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { diff --git a/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.replies index 92feb723e6..694f0c64b2 100644 --- a/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.replies @@ -25060,10 +25060,59 @@ } { - "execute": "query-machines", + "execute": "qom-list-properties", + "arguments": { + "typename": "sev-guest" + }, "id": "libvirt-41" } +{ + "return": [ + { + "name": "type", + "type": "string" + }, + { + "name": "dh-cert-file", + "description": "guest owners DH certificate (encoded with base64)", + "type": "string" + }, + { + "name": "sev-device", + "description": "SEV device to use", + "type": "string" + }, + { + "name": "session-file", + "description": "guest owners session parameters (encoded with base64)", + "type": "string" + }, + { + "name": "handle", + "type": "uint32" + }, + { + "name": "policy", + "type": "uint32" + }, + { + "name": "reduced-phys-bits", + "type": "uint32" + }, + { + "name": "cbitpos", + "type": "uint32" + } + ], + "id": "libvirt-41" +} + +{ + "execute": "query-machines", + "id": "libvirt-42" +} + { "return": [ { @@ -25526,7 +25575,7 @@ "default-ram-id": "pc.ram" } ], - "id": "libvirt-41" + "id": "libvirt-42" } { @@ -25534,7 +25583,7 @@ "arguments": { "typename": "none-machine" }, - "id": "libvirt-42" + "id": "libvirt-43" } { @@ -25637,12 +25686,12 @@ "type": "child<container>" } ], - "id": "libvirt-42" + "id": "libvirt-43" } { "execute": "query-cpu-definitions", - "id": "libvirt-43" + "id": "libvirt-44" } { @@ -27699,12 +27748,12 @@ "deprecated": false } ], - "id": "libvirt-43" + "id": "libvirt-44" } { "execute": "query-tpm-models", - "id": "libvirt-44" + "id": "libvirt-45" } { @@ -27712,12 +27761,12 @@ "tpm-crb", "tpm-tis" ], - "id": "libvirt-44" + "id": "libvirt-45" } { "execute": "query-tpm-types", - "id": "libvirt-45" + "id": "libvirt-46" } { @@ -27725,12 +27774,12 @@ "passthrough", "emulator" ], - "id": "libvirt-45" + "id": "libvirt-46" } { "execute": "query-command-line-options", - "id": "libvirt-46" + "id": "libvirt-47" } { @@ -29062,12 +29111,12 @@ "option": "drive" } ], - "id": "libvirt-46" + "id": "libvirt-47" } { "execute": "query-migrate-capabilities", - "id": "libvirt-47" + "id": "libvirt-48" } { @@ -29149,16 +29198,16 @@ "capability": "background-snapshot" } ], - "id": "libvirt-47" + "id": "libvirt-48" } { "execute": "query-sev-capabilities", - "id": "libvirt-48" + "id": "libvirt-49" } { - "id": "libvirt-48", + "id": "libvirt-49", "error": { "class": "GenericError", "desc": "Failed to open /dev/sev: No such file or directory" @@ -29173,7 +29222,7 @@ "name": "host" } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -29496,7 +29545,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -29510,7 +29559,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { @@ -29833,7 +29882,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { diff --git a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies index 69d3b1b12a..71f325f921 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies @@ -13315,6 +13315,11 @@ { "name": "reduced-phys-bits", "type": "int" + }, + { + "name": "kernel-hashes", + "default": null, + "type": "bool" } ], "meta-type": "object" @@ -28022,10 +28027,64 @@ } { - "execute": "query-machines", + "execute": "qom-list-properties", + "arguments": { + "typename": "sev-guest" + }, "id": "libvirt-41" } +{ + "return": [ + { + "name": "type", + "type": "string" + }, + { + "name": "dh-cert-file", + "description": "guest owners DH certificate (encoded with base64)", + "type": "string" + }, + { + "name": "sev-device", + "description": "SEV device to use", + "type": "string" + }, + { + "name": "session-file", + "description": "guest owners session parameters (encoded with base64)", + "type": "string" + }, + { + "name": "kernel-hashes", + "description": "add kernel hashes to guest firmware for measured Linux boot", + "type": "bool" + }, + { + "name": "handle", + "type": "uint32" + }, + { + "name": "policy", + "type": "uint32" + }, + { + "name": "reduced-phys-bits", + "type": "uint32" + }, + { + "name": "cbitpos", + "type": "uint32" + } + ], + "id": "libvirt-41" +} + +{ + "execute": "query-machines", + "id": "libvirt-42" +} + { "return": [ { @@ -28506,7 +28565,7 @@ "default-ram-id": "pc.ram" } ], - "id": "libvirt-41" + "id": "libvirt-42" } { @@ -28514,7 +28573,7 @@ "arguments": { "typename": "none-machine" }, - "id": "libvirt-42" + "id": "libvirt-43" } { @@ -28617,12 +28676,12 @@ "type": "child<container>" } ], - "id": "libvirt-42" + "id": "libvirt-43" } { "execute": "query-cpu-definitions", - "id": "libvirt-43" + "id": "libvirt-44" } { @@ -30692,12 +30751,12 @@ "deprecated": false } ], - "id": "libvirt-43" + "id": "libvirt-44" } { "execute": "query-tpm-models", - "id": "libvirt-44" + "id": "libvirt-45" } { @@ -30705,12 +30764,12 @@ "tpm-crb", "tpm-tis" ], - "id": "libvirt-44" + "id": "libvirt-45" } { "execute": "query-tpm-types", - "id": "libvirt-45" + "id": "libvirt-46" } { @@ -30718,12 +30777,12 @@ "passthrough", "emulator" ], - "id": "libvirt-45" + "id": "libvirt-46" } { "execute": "query-command-line-options", - "id": "libvirt-46" + "id": "libvirt-47" } { @@ -32055,12 +32114,12 @@ "option": "drive" } ], - "id": "libvirt-46" + "id": "libvirt-47" } { "execute": "query-migrate-capabilities", - "id": "libvirt-47" + "id": "libvirt-48" } { @@ -32142,20 +32201,22 @@ "capability": "background-snapshot" } ], - "id": "libvirt-47" + "id": "libvirt-48" } { "execute": "query-sev-capabilities", - "id": "libvirt-48" + "id": "libvirt-49" } { - "id": "libvirt-48", - "error": { - "class": "GenericError", - "desc": "SEV: Failed to open /dev/sev: No such file or directory" - } + "return": { + "reduced-phys-bits": 1, + "cbitpos": 47, + "cert-chain": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA", + "pdh": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA" + }, + "id": "libvirt-49" } { @@ -32166,7 +32227,7 @@ "name": "host" } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -32499,7 +32560,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -32513,7 +32574,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { @@ -32846,7 +32907,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { diff --git a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml index 39179916c5..73ab031931 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml @@ -154,6 +154,7 @@ <flag name='tpm-emulator'/> <flag name='mch'/> <flag name='mch.extended-tseg-mbytes'/> + <flag name='sev-guest'/> <flag name='usb-storage.werror'/> <flag name='egl-headless'/> <flag name='vfio-pci.display'/> @@ -240,6 +241,7 @@ <flag name='device.json'/> <flag name='query-dirty-rate'/> <flag name='rbd-encryption'/> + <flag name='sev-guest-kernel-hashes'/> <version>6001050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100244</microcodeVersion> @@ -3710,4 +3712,10 @@ <machine type='tcg' name='pc-q35-2.5' hotplugCpus='yes' maxCpus='255' defaultCPU='qemu64-x86_64-cpu' numaMemSupported='yes' defaultRAMid='pc.ram'/> <machine type='tcg' name='pc-i440fx-3.0' hotplugCpus='yes' maxCpus='255' defaultCPU='qemu64-x86_64-cpu' numaMemSupported='yes' defaultRAMid='pc.ram'/> <machine type='tcg' name='pc-q35-2.11' hotplugCpus='yes' maxCpus='288' defaultCPU='qemu64-x86_64-cpu' numaMemSupported='yes' defaultRAMid='pc.ram'/> + <sev> + <cbitpos>47</cbitpos> + <reducedPhysBits>1</reducedPhysBits> + <pdh>AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA</pdh> + <certChain>AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA</certChain> + </sev> </qemuCaps> -- 2.33.1

On Fri, Dec 10, 2021 at 11:37:34 +0000, Daniel P. Berrangé wrote:
This sev-guest object property indicates whether QEMU should expose the kernel, ramdisk, cmdline hashes to the firmware for measurement.
The 6.2.0 capabilities are hacked to look as if they were generated with sev-guest support.
The qemu-6.2 lifecycle is not ended yet, so I'll be re-generating the caps, thus your hack will get lost. Given that qemu is at rc4 now you can either wait until the final release is out and I update the caps or pick a different older version to hack.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_capabilities.c | 8 ++ src/qemu/qemu_capabilities.h | 1 + .../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 7 +- .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 7 +- tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 7 +- .../caps_2.12.0.x86_64.replies | 97 ++++++++++++---- .../caps_3.0.0.x86_64.replies | 97 ++++++++++++---- .../caps_3.1.0.x86_64.replies | 97 ++++++++++++---- .../caps_4.0.0.x86_64.replies | 97 ++++++++++++---- .../caps_4.1.0.x86_64.replies | 89 ++++++++++---- .../caps_4.2.0.x86_64.replies | 89 ++++++++++---- .../caps_5.0.0.x86_64.replies | 89 ++++++++++---- .../caps_5.1.0.x86_64.replies | 89 ++++++++++---- .../caps_5.2.0.x86_64.replies | 89 ++++++++++---- .../caps_6.0.0.x86_64.replies | 89 ++++++++++---- .../caps_6.1.0.x86_64.replies | 89 ++++++++++---- .../caps_6.2.0.x86_64.replies | 109 ++++++++++++++---- .../caps_6.2.0.x86_64.xml | 8 ++ 18 files changed, 895 insertions(+), 263 deletions(-)
Under the above conditions: Reviewed-by: Peter Krempa <pkrempa@redhat.com>

On Fri, Dec 10, 2021 at 03:53:46PM +0100, Peter Krempa wrote:
On Fri, Dec 10, 2021 at 11:37:34 +0000, Daniel P. Berrangé wrote:
This sev-guest object property indicates whether QEMU should expose the kernel, ramdisk, cmdline hashes to the firmware for measurement.
The 6.2.0 capabilities are hacked to look as if they were generated with sev-guest support.
The qemu-6.2 lifecycle is not ended yet, so I'll be re-generating the caps, thus your hack will get lost.
Given that qemu is at rc4 now you can either wait until the final release is out and I update the caps or pick a different older version to hack.
This is a new feature in 6.2.0, so it has to be done in the 6.2.0 caps to make any sense. As long as you can re-generate the 6.2.0 caps on a SEV capable machine, I'll just wait for you.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_capabilities.c | 8 ++ src/qemu/qemu_capabilities.h | 1 + .../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 7 +- .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 7 +- tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 7 +- .../caps_2.12.0.x86_64.replies | 97 ++++++++++++---- .../caps_3.0.0.x86_64.replies | 97 ++++++++++++---- .../caps_3.1.0.x86_64.replies | 97 ++++++++++++---- .../caps_4.0.0.x86_64.replies | 97 ++++++++++++---- .../caps_4.1.0.x86_64.replies | 89 ++++++++++---- .../caps_4.2.0.x86_64.replies | 89 ++++++++++---- .../caps_5.0.0.x86_64.replies | 89 ++++++++++---- .../caps_5.1.0.x86_64.replies | 89 ++++++++++---- .../caps_5.2.0.x86_64.replies | 89 ++++++++++---- .../caps_6.0.0.x86_64.replies | 89 ++++++++++---- .../caps_6.1.0.x86_64.replies | 89 ++++++++++---- .../caps_6.2.0.x86_64.replies | 109 ++++++++++++++---- .../caps_6.2.0.x86_64.xml | 8 ++ 18 files changed, 895 insertions(+), 263 deletions(-)
Under the above conditions:
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On Fri, Dec 10, 2021 at 14:56:05 +0000, Daniel P. Berrangé wrote:
On Fri, Dec 10, 2021 at 03:53:46PM +0100, Peter Krempa wrote:
On Fri, Dec 10, 2021 at 11:37:34 +0000, Daniel P. Berrangé wrote:
This sev-guest object property indicates whether QEMU should expose the kernel, ramdisk, cmdline hashes to the firmware for measurement.
The 6.2.0 capabilities are hacked to look as if they were generated with sev-guest support.
The qemu-6.2 lifecycle is not ended yet, so I'll be re-generating the caps, thus your hack will get lost.
Given that qemu is at rc4 now you can either wait until the final release is out and I update the caps or pick a different older version to hack.
This is a new feature in 6.2.0, so it has to be done in the 6.2.0 caps to make any sense.
As long as you can re-generate the 6.2.0 caps on a SEV capable machine, I'll just wait for you.
I don't have a sev-capable box, but I kept generating the caps for all of the 6.2.0 lifecycle so it will have the least of diff.

Set the kernel-hashes property on the sev-guest object if the config asked for it explicitly. While QEMU machine types currently default to having this setting off, it is not guaranteed to remain this way. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_command.c | 7 ++++ src/qemu/qemu_validate.c | 8 ++++ ...unch-security-sev-direct.x86_64-6.2.0.args | 40 +++++++++++++++++++ .../launch-security-sev-direct.xml | 39 ++++++++++++++++++ tests/qemuxml2argvtest.c | 1 + 5 files changed, 95 insertions(+) create mode 100644 tests/qemuxml2argvdata/launch-security-sev-direct.x86_64-6.2.0.args create mode 100644 tests/qemuxml2argvdata/launch-security-sev-direct.xml diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index c47998aabd..6999afe5aa 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -10112,6 +10112,13 @@ qemuBuildSEVCommandLine(virDomainObj *vm, virCommand *cmd, NULL) < 0) return -1; + if (sev->kernel_hashes != VIR_TRISTATE_BOOL_ABSENT) { + bool val; + virTristateBoolToBool(sev->kernel_hashes, &val); + if (virJSONValueObjectAppendBoolean(props, "kernel-hashes", val) < 0) + return -1; + } + if (qemuBuildObjectCommandlineFromJSON(cmd, props, priv->qemuCaps) < 0) return -1; diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 29b01495ad..0150b0f082 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -1200,6 +1200,14 @@ qemuValidateDomainDef(const virDomainDef *def, "this QEMU binary")); return -1; } + + if (def->sec->data.sev.kernel_hashes == VIR_TRISTATE_BOOL_YES && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST_KERNEL_HASHES)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("SEV launch security measured direct kernel " + "boot is not supported with this QEMU binary")); + return -1; + } break; case VIR_DOMAIN_LAUNCH_SECURITY_PV: if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_CONFIDENTAL_GUEST_SUPPORT) || diff --git a/tests/qemuxml2argvdata/launch-security-sev-direct.x86_64-6.2.0.args b/tests/qemuxml2argvdata/launch-security-sev-direct.x86_64-6.2.0.args new file mode 100644 index 0000000000..0062faa06c --- /dev/null +++ b/tests/qemuxml2argvdata/launch-security-sev-direct.x86_64-6.2.0.args @@ -0,0 +1,40 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc-i440fx-6.2,usb=off,dump-guest-core=off,confidential-guest-support=lsec0,memory-backend=pc.ram \ +-accel kvm \ +-cpu qemu64 \ +-m 214 \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-boot strict=on \ +-kernel /vmlinuz \ +-initrd /initrd \ +-append runme \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}' \ +-device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-format","id":"ide0-0-0","bootindex":1}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-object '{"qom-type":"sev-guest","id":"lsec0","cbitpos":47,"reduced-phys-bits":1,"policy":1,"dh-cert-file":"/tmp/lib/domain--1-QEMUGuest1/dh_cert.base64","session-file":"/tmp/lib/domain--1-QEMUGuest1/session.base64","kernel-hashes":true}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/launch-security-sev-direct.xml b/tests/qemuxml2argvdata/launch-security-sev-direct.xml new file mode 100644 index 0000000000..80ce6412dd --- /dev/null +++ b/tests/qemuxml2argvdata/launch-security-sev-direct.xml @@ -0,0 +1,39 @@ +<domain type='kvm'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <kernel>/vmlinuz</kernel> + <initrd>/initrd</initrd> + <cmdline>runme</cmdline> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='none'/> + </devices> + <launchSecurity type='sev' kernelHashes='yes'> + <cbitpos>47</cbitpos> + <reducedPhysBits>1</reducedPhysBits> + <policy>0x0001</policy> + <dhCert>AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA</dhCert> + <session>IHAVENOIDEABUTJUSTPROVIDINGASTRING</session> + </launchSecurity> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 5e4cd7389c..d407a6d03d 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -3309,6 +3309,7 @@ mymain(void) DO_TEST_CAPS_VER("launch-security-sev", "2.12.0"); DO_TEST_CAPS_VER("launch-security-sev", "6.0.0"); DO_TEST_CAPS_VER("launch-security-sev-missing-platform-info", "2.12.0"); + DO_TEST_CAPS_VER("launch-security-sev-direct", "6.2.0"); DO_TEST_CAPS_ARCH_LATEST("launch-security-s390-pv", "s390x"); -- 2.33.1

On Fri, Dec 10, 2021 at 11:37:35 +0000, Daniel P. Berrangé wrote:
Set the kernel-hashes property on the sev-guest object if the config asked for it explicitly. While QEMU machine types currently default to having this setting off, it is not guaranteed to remain this way.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_command.c | 7 ++++ src/qemu/qemu_validate.c | 8 ++++ ...unch-security-sev-direct.x86_64-6.2.0.args | 40 +++++++++++++++++++ .../launch-security-sev-direct.xml | 39 ++++++++++++++++++ tests/qemuxml2argvtest.c | 1 + 5 files changed, 95 insertions(+) create mode 100644 tests/qemuxml2argvdata/launch-security-sev-direct.x86_64-6.2.0.args create mode 100644 tests/qemuxml2argvdata/launch-security-sev-direct.xml
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index c47998aabd..6999afe5aa 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -10112,6 +10112,13 @@ qemuBuildSEVCommandLine(virDomainObj *vm, virCommand *cmd, NULL) < 0) return -1;
Replace all of this hunk with "T:kernel-hashes", sev->kernel_hashes, put into the call to qemuMonitorCreateObjectProps just above the NULL sentinel.
+ if (sev->kernel_hashes != VIR_TRISTATE_BOOL_ABSENT) { + bool val; + virTristateBoolToBool(sev->kernel_hashes, &val); + if (virJSONValueObjectAppendBoolean(props, "kernel-hashes", val) < 0) + return -1; + } + if (qemuBuildObjectCommandlineFromJSON(cmd, props, priv->qemuCaps) < 0) return -1;
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 29b01495ad..0150b0f082 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -1200,6 +1200,14 @@ qemuValidateDomainDef(const virDomainDef *def, "this QEMU binary")); return -1; } + + if (def->sec->data.sev.kernel_hashes == VIR_TRISTATE_BOOL_YES && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST_KERNEL_HASHES)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("SEV launch security measured direct kernel " + "boot is not supported with this QEMU binary"));
Error message on a single line please.
+ return -1; + } break; case VIR_DOMAIN_LAUNCH_SECURITY_PV: if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_CONFIDENTAL_GUEST_SUPPORT) ||
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
participants (2)
-
Daniel P. Berrangé
-
Peter Krempa