[libvirt PATCH v3 00/13] 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. In v3: - Refactor CPUID code so and mock it in test suite Daniel P. Berrangé (13): 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 util: pull CPUID helper function out of CPU driver 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/cpu/cpu_x86.c | 34 +----- src/libvirt_private.syms | 1 + src/qemu/qemu_capabilities.c | 47 ++++++++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 1 + 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 | 7 ++ src/util/virhostcpu.c | 58 ++++++++++ src/util/virhostcpu.h | 7 ++ .../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 + tests/testutilsqemu.c | 21 ++++ tools/virsh-domain.c | 53 +++++++++ tools/virsh-host.c | 45 ++++++++ 53 files changed, 1514 insertions(+), 299 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 e444ad2d45..f28d703512 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -19976,6 +19976,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. Reviewed-by: Peter Krempa <pkrempa@redhat.com> 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

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 f28d703512..ee23e10543 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -19961,14 +19961,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); @@ -19985,15 +19990,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; @@ -20021,7 +20050,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. Reviewed-by: Peter Krempa <pkrempa@redhat.com> 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 2338d6522a..c748fe2ba9 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -9523,6 +9523,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 */ @@ -14542,6 +14589,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

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. Reviewed-by: Peter Krempa <pkrempa@redhat.com> 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

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. Reviewed-by: Peter Krempa <pkrempa@redhat.com> 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

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. Reviewed-by: Peter Krempa <pkrempa@redhat.com> 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

This will be needed directly in the QEMU driver in a later patch. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/cpu/cpu_x86.c | 34 +++++------------------ src/libvirt_private.syms | 1 + src/util/virhostcpu.c | 58 ++++++++++++++++++++++++++++++++++++++++ src/util/virhostcpu.h | 7 +++++ 4 files changed, 72 insertions(+), 28 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 0b2ff82d40..5cb9caef8a 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -2377,34 +2377,12 @@ virCPUx86DataCheckFeature(const virCPUData *data, static inline void cpuidCall(virCPUx86CPUID *cpuid) { -# if __x86_64__ - asm("xor %%ebx, %%ebx;" /* clear the other registers as some cpuid */ - "xor %%edx, %%edx;" /* functions may use them as additional arguments */ - "cpuid;" - : "=a" (cpuid->eax), - "=b" (cpuid->ebx), - "=c" (cpuid->ecx), - "=d" (cpuid->edx) - : "a" (cpuid->eax_in), - "c" (cpuid->ecx_in)); -# else - /* we need to avoid direct use of ebx for CPUID output as it is used - * for global offset table on i386 with -fPIC - */ - asm("push %%ebx;" - "xor %%ebx, %%ebx;" /* clear the other registers as some cpuid */ - "xor %%edx, %%edx;" /* functions may use them as additional arguments */ - "cpuid;" - "mov %%ebx, %1;" - "pop %%ebx;" - : "=a" (cpuid->eax), - "=r" (cpuid->ebx), - "=c" (cpuid->ecx), - "=d" (cpuid->edx) - : "a" (cpuid->eax_in), - "c" (cpuid->ecx_in) - : "cc"); -# endif + virHostCPUX86GetCPUID(cpuid->eax_in, + cpuid->ecx_in, + &cpuid->eax, + &cpuid->ebx, + &cpuid->ecx, + &cpuid->edx); } diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index da27ee7b53..53262e25b7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2417,6 +2417,7 @@ virHostCPUGetThreadsPerSubcore; virHostCPUHasBitmap; virHostCPUReadSignature; virHostCPUStatsAssign; +virHostCPUX86GetCPUID; # util/virhostmem.h diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c index 54e2462a95..a07c00a0e9 100644 --- a/src/util/virhostcpu.c +++ b/src/util/virhostcpu.c @@ -1583,3 +1583,61 @@ virHostCPUGetHaltPollTime(pid_t pid, return 0; } + +void +virHostCPUX86GetCPUID(uint32_t leaf G_GNUC_UNUSED, + uint32_t extended G_GNUC_UNUSED, + uint32_t *eax, + uint32_t *ebx, + uint32_t *ecx, + uint32_t *edx) +{ +#if defined(__i386__) || defined(__x86_64__) + uint32_t out[4]; +# if __x86_64__ + asm("xor %%ebx, %%ebx;" /* clear the other registers as some cpuid */ + "xor %%edx, %%edx;" /* functions may use them as additional arguments */ + "cpuid;" + : "=a" (out[0]), + "=b" (out[1]), + "=c" (out[2]), + "=d" (out[3]) + : "a" (leaf), + "c" (extended)); +# else + /* we need to avoid direct use of ebx for CPUID output as it is used + * for global offset table on i386 with -fPIC + */ + asm("push %%ebx;" + "xor %%ebx, %%ebx;" /* clear the other registers as some cpuid */ + "xor %%edx, %%edx;" /* functions may use them as additional arguments */ + "cpuid;" + "mov %%ebx, %1;" + "pop %%ebx;" + : "=a" (out[0]), + "=r" (out[1]), + "=c" (out[2]), + "=d" (out[3]) + : "a" (leaf), + "c" (extended) + : "cc"); +# endif + if (eax) + *eax = out[0]; + if (ebx) + *ebx = out[1]; + if (ecx) + *ecx = out[2]; + if (edx) + *edx = out[3]; +#else + if (eax) + *eax = 0; + if (ebx) + *ebx = 0; + if (ecx) + *ecx = 0; + if (edx) + *edx = 0; +#endif +} diff --git a/src/util/virhostcpu.h b/src/util/virhostcpu.h index a96dd5afba..86a231daa2 100644 --- a/src/util/virhostcpu.h +++ b/src/util/virhostcpu.h @@ -89,3 +89,10 @@ int virHostCPUGetSignature(char **signature); int virHostCPUGetHaltPollTime(pid_t pid, unsigned long long *haltPollSuccess, unsigned long long *haltPollFail); + +void virHostCPUX86GetCPUID(uint32_t leaf, + uint32_t extended, + uint32_t *eax, + uint32_t *ebx, + uint32_t *ecx, + uint32_t *edx); -- 2.33.1

On Fri, Dec 10, 2021 at 16:47:09 +0000, Daniel P. Berrangé wrote:
This will be needed directly in the QEMU driver in a later patch.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/cpu/cpu_x86.c | 34 +++++------------------ src/libvirt_private.syms | 1 + src/util/virhostcpu.c | 58 ++++++++++++++++++++++++++++++++++++++++ src/util/virhostcpu.h | 7 +++++ 4 files changed, 72 insertions(+), 28 deletions(-)
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 | 39 +++++++++++++++++++ src/qemu/qemu_driver.c | 10 +++++ .../domaincapsdata/qemu_2.12.0-q35.x86_64.xml | 4 +- .../domaincapsdata/qemu_2.12.0-tcg.x86_64.xml | 4 +- tests/domaincapsdata/qemu_2.12.0.x86_64.xml | 4 +- .../domaincapsdata/qemu_6.0.0-q35.x86_64.xml | 4 +- .../domaincapsdata/qemu_6.0.0-tcg.x86_64.xml | 4 +- tests/domaincapsdata/qemu_6.0.0.x86_64.xml | 4 +- tests/testutilsqemu.c | 21 ++++++++++ 9 files changed, 82 insertions(+), 12 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 4ffd0a98a2..ddd61ecfc9 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,31 @@ virQEMUCapsProbeQMPGICCapabilities(virQEMUCaps *qemuCaps, } +static void +virQEMUCapsGetSEVMaxGuests(virSEVCapability *caps) +{ + /* + * From Secure Encrypted Virtualization API v0.24, section 6.19.1 + * + * If the guest is SEV-ES enabled, then the ASID must be at least + * 1h and at most (MIN_SEV_ASID-1). If the guest is not SEV-ES + * enabled, then the ASID must be at least MIN_SEV_ASID and at + * most the maximum SEV ASID available. The MIN_SEV_ASID value + * is discovered by CPUID Fn8000_001F[EDX]. The maximum SEV ASID + * available is discovered by CPUID Fn8000_001F[ECX]. + */ + uint32_t min_asid, max_asid; + virHostCPUX86GetCPUID(0x8000001F, 0, NULL, NULL, + &max_asid, &min_asid); + + if (max_asid != 0 && min_asid != 0) { + caps->max_guests = max_asid - min_asid + 1; + caps->max_es_guests = min_asid - 1; + } else { + caps->max_guests = caps->max_es_guests = 0; + } +} + static int virQEMUCapsProbeQMPSEVCapabilities(virQEMUCaps *qemuCaps, qemuMonitor *mon) @@ -3305,6 +3332,8 @@ virQEMUCapsProbeQMPSEVCapabilities(virQEMUCaps *qemuCaps, return 0; } + virQEMUCapsGetSEVMaxGuests(caps); + virSEVCapabilitiesFree(qemuCaps->sevCapabilities); qemuCaps->sevCapabilities = caps; return 0; @@ -4084,6 +4113,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 +6381,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 ee23e10543..8ee0939295 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -19918,6 +19918,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..0dc5995c09 100644 --- a/tests/domaincapsdata/qemu_2.12.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_2.12.0-q35.x86_64.xml @@ -205,8 +205,8 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> - <maxGuests>0</maxGuests> - <maxESGuests>0</maxESGuests> + <maxGuests>59</maxGuests> + <maxESGuests>450</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 5840a8b921..575506d852 100644 --- a/tests/domaincapsdata/qemu_2.12.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_2.12.0-tcg.x86_64.xml @@ -215,8 +215,8 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> - <maxGuests>0</maxGuests> - <maxESGuests>0</maxESGuests> + <maxGuests>59</maxGuests> + <maxESGuests>450</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 21d1b6946e..c8a5558536 100644 --- a/tests/domaincapsdata/qemu_2.12.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_2.12.0.x86_64.xml @@ -205,8 +205,8 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> - <maxGuests>0</maxGuests> - <maxESGuests>0</maxESGuests> + <maxGuests>59</maxGuests> + <maxESGuests>450</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 3415d44019..4595e70f61 100644 --- a/tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml @@ -227,8 +227,8 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> - <maxGuests>0</maxGuests> - <maxESGuests>0</maxESGuests> + <maxGuests>59</maxGuests> + <maxESGuests>450</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 f58be3af6c..6b85c9c45a 100644 --- a/tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml @@ -233,8 +233,8 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> - <maxGuests>0</maxGuests> - <maxESGuests>0</maxESGuests> + <maxGuests>59</maxGuests> + <maxESGuests>450</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 0a2615c519..a6fa374211 100644 --- a/tests/domaincapsdata/qemu_6.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.0.0.x86_64.xml @@ -227,8 +227,8 @@ <sev supported='yes'> <cbitpos>47</cbitpos> <reducedPhysBits>1</reducedPhysBits> - <maxGuests>0</maxGuests> - <maxESGuests>0</maxESGuests> + <maxGuests>59</maxGuests> + <maxESGuests>450</maxESGuests> </sev> </features> </domainCapabilities> diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c index 5bd1d40ad4..7f848f158e 100644 --- a/tests/testutilsqemu.c +++ b/tests/testutilsqemu.c @@ -143,6 +143,27 @@ virCapabilitiesHostNUMANewHost(void) return virTestCapsBuildNUMATopology(3); } +void +virHostCPUX86GetCPUID(uint32_t leaf, + uint32_t extended, + uint32_t *eax, + uint32_t *ebx, + uint32_t *ecx, + uint32_t *edx) +{ + if (eax) + *eax = 0; + if (ebx) + *ebx = 0; + if (ecx) + *ecx = 0; + if (edx) + *edx = 0; + if (leaf == 0x8000001F && extended == 0) { + *ecx = 509; + *edx = 451; + } +} static int testQemuAddGuest(virCaps *caps, -- 2.33.1

On Fri, Dec 10, 2021 at 16:47:10 +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 | 39 +++++++++++++++++++ src/qemu/qemu_driver.c | 10 +++++ .../domaincapsdata/qemu_2.12.0-q35.x86_64.xml | 4 +- .../domaincapsdata/qemu_2.12.0-tcg.x86_64.xml | 4 +- tests/domaincapsdata/qemu_2.12.0.x86_64.xml | 4 +- .../domaincapsdata/qemu_6.0.0-q35.x86_64.xml | 4 +- .../domaincapsdata/qemu_6.0.0-tcg.x86_64.xml | 4 +- tests/domaincapsdata/qemu_6.0.0.x86_64.xml | 4 +- tests/testutilsqemu.c | 21 ++++++++++ 9 files changed, 82 insertions(+), 12 deletions(-)
[...]
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ee23e10543..8ee0939295 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -19918,6 +19918,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;
Both calls have broken alignment. [...]
diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c index 5bd1d40ad4..7f848f158e 100644 --- a/tests/testutilsqemu.c +++ b/tests/testutilsqemu.c @@ -143,6 +143,27 @@ virCapabilitiesHostNUMANewHost(void) return virTestCapsBuildNUMATopology(3); }
+void
This form of overriding functions looked a bit unorthodox but prior art is right above, so it's okay.
+virHostCPUX86GetCPUID(uint32_t leaf, + uint32_t extended, + uint32_t *eax, + uint32_t *ebx, + uint32_t *ecx, + uint32_t *edx) +{ + if (eax) + *eax = 0; + if (ebx) + *ebx = 0; + if (ecx) + *ecx = 0; + if (edx) + *edx = 0; + if (leaf == 0x8000001F && extended == 0) { + *ecx = 509; + *edx = 451;
ecx/edx are unconditionally dereferenced here. Okay at this point but possibly unextensible. Consider adding pointer checks at least to avoid coverity moaning. Reviewed-by: Peter Krempa <pkrempa@redhat.com>

On Tue, Dec 14, 2021 at 11:44:00AM +0100, Peter Krempa wrote:
On Fri, Dec 10, 2021 at 16:47:10 +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 | 39 +++++++++++++++++++ src/qemu/qemu_driver.c | 10 +++++ .../domaincapsdata/qemu_2.12.0-q35.x86_64.xml | 4 +- .../domaincapsdata/qemu_2.12.0-tcg.x86_64.xml | 4 +- tests/domaincapsdata/qemu_2.12.0.x86_64.xml | 4 +- .../domaincapsdata/qemu_6.0.0-q35.x86_64.xml | 4 +- .../domaincapsdata/qemu_6.0.0-tcg.x86_64.xml | 4 +- tests/domaincapsdata/qemu_6.0.0.x86_64.xml | 4 +- tests/testutilsqemu.c | 21 ++++++++++ 9 files changed, 82 insertions(+), 12 deletions(-)
[...]
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ee23e10543..8ee0939295 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -19918,6 +19918,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;
Both calls have broken alignment.
This is consistent with the alignment of all existing code in this method.
diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c index 5bd1d40ad4..7f848f158e 100644 --- a/tests/testutilsqemu.c +++ b/tests/testutilsqemu.c @@ -143,6 +143,27 @@ virCapabilitiesHostNUMANewHost(void) return virTestCapsBuildNUMATopology(3); }
+void
This form of overriding functions looked a bit unorthodox but prior art is right above, so it's okay.
It is basically relying on the linker method resolution ordering to have same effect as LD_PRELOAD, without having to jump through the hoops of creating a preload .so library.
+virHostCPUX86GetCPUID(uint32_t leaf, + uint32_t extended, + uint32_t *eax, + uint32_t *ebx, + uint32_t *ecx, + uint32_t *edx) +{ + if (eax) + *eax = 0; + if (ebx) + *ebx = 0; + if (ecx) + *ecx = 0; + if (edx) + *edx = 0; + if (leaf == 0x8000001F && extended == 0) { + *ecx = 509; + *edx = 451;
ecx/edx are unconditionally dereferenced here. Okay at this point but possibly unextensible. Consider adding pointer checks at least to avoid coverity moaning.
Hmm, yes will do.
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 :|

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. Reviewed-by: Peter Krempa <pkrempa@redhat.com> 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 c634e7dd41..15e52eeed8 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")); @@ -27052,6 +27056,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

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. Reviewed-by: Peter Krempa <pkrempa@redhat.com> 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 ddd61ecfc9..9553e6e5b8 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..b5f700c119 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>59</maxGuests> + <maxESGuests>450</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..c2c22d5775 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>59</maxGuests> + <maxESGuests>450</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..17207394dd 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>59</maxGuests> + <maxESGuests>450</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 16:47:12 +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.
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Don't forget that due to the hack of adding SEV to the caps output data my R-b applies only after qemu-6.2 is released and libvirt's test data updated.

On Fri, Dec 10, 2021 at 16:47:12 +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.
Reviewed-by: Peter Krempa <pkrempa@redhat.com> 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 ddd61ecfc9..9553e6e5b8 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 },
Actually, when reviewing the last patch I've noticed that 'sev-guest' which you are querying is actually an '-object', so you don't need any of this complicated query machinery which modifies all .replies files but rather it's enough to use the QMP schema query: Once you add to virQEMUCapsQMPSchemaQueries[] the following line: { "object-add/arg-type/+sev-guest/kernel-hashes", QEMU_CAPS_SEV_GUEST_KERNEL_HASHES }, The result is the same information. I actually see you also hacked the schema to add the field because I presume the QAPI schema validation failed if that was not the case. So my R-b applies only on this simpler version as we should not re-query data we already have from the QMP schema.

On Tue, Dec 14, 2021 at 12:04:17PM +0100, Peter Krempa wrote:
On Fri, Dec 10, 2021 at 16:47:12 +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.
Reviewed-by: Peter Krempa <pkrempa@redhat.com> 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 ddd61ecfc9..9553e6e5b8 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 },
Actually, when reviewing the last patch I've noticed that 'sev-guest' which you are querying is actually an '-object', so you don't need any of this complicated query machinery which modifies all .replies files but rather it's enough to use the QMP schema query:
Once you add to virQEMUCapsQMPSchemaQueries[] the following line:
{ "object-add/arg-type/+sev-guest/kernel-hashes", QEMU_CAPS_SEV_GUEST_KERNEL_HASHES },
The result is the same information. I actually see you also hacked the schema to add the field because I presume the QAPI schema validation failed if that was not the case.
Oh right, we don't need to query objects anymore since Kevin's recentish work to map QOM into QAPI. 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 :|

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 | 1 + src/qemu/qemu_validate.c | 7 ++++ ...unch-security-sev-direct.x86_64-6.2.0.args | 40 +++++++++++++++++++ .../launch-security-sev-direct.xml | 39 ++++++++++++++++++ tests/qemuxml2argvtest.c | 1 + 5 files changed, 88 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 613f7a5d2a..dfbf4973f5 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -9894,6 +9894,7 @@ qemuBuildSEVCommandLine(virDomainObj *vm, virCommand *cmd, "u:policy", sev->policy, "S:dh-cert-file", dhpath, "S:session-file", sessionpath, + "T:kernel-hashes", sev->kernel_hashes, NULL) < 0) return -1; diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 29b01495ad..c0dc1f7b53 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -1200,6 +1200,13 @@ 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 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 615f45376c..e1ecb749ed 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -3423,6 +3423,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 16:47:13 +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 | 1 + src/qemu/qemu_validate.c | 7 ++++ ...unch-security-sev-direct.x86_64-6.2.0.args | 40 +++++++++++++++++++ .../launch-security-sev-direct.xml | 39 ++++++++++++++++++ tests/qemuxml2argvtest.c | 1 + 5 files changed, 88 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 613f7a5d2a..dfbf4973f5 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -9894,6 +9894,7 @@ qemuBuildSEVCommandLine(virDomainObj *vm, virCommand *cmd, "u:policy", sev->policy, "S:dh-cert-file", dhpath, "S:session-file", sessionpath, + "T:kernel-hashes", sev->kernel_hashes,
Since this is an '-object' ...
NULL) < 0) return -1;
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 29b01495ad..c0dc1f7b53 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -1200,6 +1200,13 @@ 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)) {
... and this flag means that the 'sev-guest' actually has the 'kernel-hashes' property, the above check should be if (def->sec->data.sev.kernel_hashes != VIR_TRISTATE_BOOL_ABSENT && ... as an explicit disable will also cause a qemu error when the property is not defined inside sev-guest. Other option is to use 'B:kernel-hashes' above and extract the value of sev->kernel_hashes into a temporary bool initialized to false via virTristateBoolToBool which preserves the default. In such case it will be always omitted when not enabled. Reviewed-by: Peter Krempa <pkrempa@redhat.com>

On Tue, Dec 14, 2021 at 12:08:37PM +0100, Peter Krempa wrote:
On Fri, Dec 10, 2021 at 16:47:13 +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 | 1 + src/qemu/qemu_validate.c | 7 ++++ ...unch-security-sev-direct.x86_64-6.2.0.args | 40 +++++++++++++++++++ .../launch-security-sev-direct.xml | 39 ++++++++++++++++++ tests/qemuxml2argvtest.c | 1 + 5 files changed, 88 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 613f7a5d2a..dfbf4973f5 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -9894,6 +9894,7 @@ qemuBuildSEVCommandLine(virDomainObj *vm, virCommand *cmd, "u:policy", sev->policy, "S:dh-cert-file", dhpath, "S:session-file", sessionpath, + "T:kernel-hashes", sev->kernel_hashes,
Since this is an '-object' ...
NULL) < 0) return -1;
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 29b01495ad..c0dc1f7b53 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -1200,6 +1200,13 @@ 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)) {
... and this flag means that the 'sev-guest' actually has the 'kernel-hashes' property, the above check should be
if (def->sec->data.sev.kernel_hashes != VIR_TRISTATE_BOOL_ABSENT && ...
Lets do this, since if the user gave an explicit disable we want to pass that through to the CLI, in case qemu changes the future default for machine types to be enabled
as an explicit disable will also cause a qemu error when the property is not defined inside sev-guest.
Other option is to use 'B:kernel-hashes' above and extract the value of sev->kernel_hashes into a temporary bool initialized to false via virTristateBoolToBool which preserves the default. In such case it will be always omitted when not enabled.
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 :|
participants (2)
-
Daniel P. Berrangé
-
Peter Krempa