Hi Roy,
On Thu, Mar 06, 2025 at 11:48:29AM +0000, Roy Hopkins wrote:
On Wed, 2025-03-05 at 16:47 +0100, Stefano Garzarella wrote:
[...]
Thanks for testing this. The problem seems to be down to the fact that I
had to introduce an initial parsing of the IGVM file during initialization
to extract sev_features. I was parsing all directives in the file but it
appears this has some unwanted side effects.
Please could you try the patch below to see if it fixes the issue? If it
does I'll incorporate it into the patch series and resubmit.
Great, it worked, so feel free to add:
Tested-by: Stefano Garzarella <[email protected]>
About the patch, I have some comments below:
From 3590460ec3945b02a679ad79735681a642596d60 Mon Sep 17 00:00:00 2001
From: Roy Hopkins <[email protected]>
Date: Thu, 6 Mar 2025 11:25:07 +0000
Subject: [PATCH 1/1] backends/igvm: Add function to process only VP context
When initializing kvm for SEV, the sev_features need to be
passed to the initialization function. When using IGVM files,
sev_features is provided in the VP context definintions in
the file. Currently this is handled in sev.c by processing
the entire file to extract the VP context, however this has
unwanted side-effects. Therefore this commit adds a new
function that allows only the VP context definitions to
be parsed in the IGVM file.
Signed-off-by: Roy Hopkins <[email protected]>
---
backends/igvm-cfg.c | 1 +
backends/igvm.c | 51 +++++++++++++++++++++++++++++++++++++++
backends/igvm.h | 3 +++
include/system/igvm-cfg.h | 10 ++++++++
target/i386/sev.c | 10 ++++----
5 files changed, 70 insertions(+), 5 deletions(-)
diff --git a/backends/igvm-cfg.c b/backends/igvm-cfg.c
index 38f17dae44..25c4469768 100644
--- a/backends/igvm-cfg.c
+++ b/backends/igvm-cfg.c
@@ -41,6 +41,7 @@ static void igvm_cfg_class_init(ObjectClass *oc, void *data)
"Set the IGVM filename to use");
igvmc->process = qigvm_process_file;
+ igvmc->process_vp_context = qigvm_process_vp_context;
}
static void igvm_cfg_init(Object *obj)
diff --git a/backends/igvm.c b/backends/igvm.c
index 7673e4a882..aae83f8a77 100644
--- a/backends/igvm.c
+++ b/backends/igvm.c
@@ -965,3 +965,54 @@ cleanup:
return retval;
}
+
+int qigvm_process_vp_context(IgvmCfg *cfg, ConfidentialGuestSupport *cgs,
+ Error **errp)
+{
This new function share a lot of code with qigvm_process_file(), can we
avoid that? e.g. adding a parameter to the process callback, or just
factoring out common code?
+ int32_t header_count;
+ int retval = -1;
+ QIgvm ctx;
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.file = qigvm_file_init(cfg->filename, errp);
+ if (ctx.file < 0) {
+ return -1;
+ }
+
+ ctx.cgs = cgs;
+ ctx.cgsc = cgs ? CONFIDENTIAL_GUEST_SUPPORT_GET_CLASS(cgs) : NULL;
+
+ /*
+ * Check that the IGVM file provides configuration for the current
+ * platform
+ */
+ if (qigvm_supported_platform_compat_mask(&ctx, errp) < 0) {
+ goto cleanup;
+ }
+
+ header_count = igvm_header_count(ctx.file, IGVM_HEADER_SECTION_DIRECTIVE);
+ if (header_count <= 0) {
+ error_setg(
+ errp, "Invalid directive header count in IGVM file. Error code:
%X",
+ header_count);
+ goto cleanup;
+ }
+
+ for (ctx.current_header_index = 0;
+ ctx.current_header_index < (unsigned)header_count;
+ ctx.current_header_index++) {
+ IgvmVariableHeaderType type = igvm_get_header_type(
+ ctx.file, IGVM_HEADER_SECTION_DIRECTIVE, ctx.current_header_index);
+ if (type == IGVM_VHT_VP_CONTEXT) {
+ if (qigvm_handler(&ctx, type, errp) < 0) {
Understanding the error I had was a bit tricky, since it didn't mention
IGVM at all.
Can we add an error_prepend() here or ...
+ goto cleanup;
+ }
+ }
+ }
+ retval = 0;
+
+cleanup:
+ igvm_free(ctx.file);
+
+ return retval;
+}
diff --git a/backends/igvm.h b/backends/igvm.h
index 269eb3a10e..a43b029d56 100644
--- a/backends/igvm.h
+++ b/backends/igvm.h
@@ -20,4 +20,7 @@
int qigvm_process_file(IgvmCfg *igvm, ConfidentialGuestSupport *cgs,
Error **errp);
+int qigvm_process_vp_context(IgvmCfg *igvm, ConfidentialGuestSupport *cgs,
+ Error **errp);
+
#endif
diff --git a/include/system/igvm-cfg.h b/include/system/igvm-cfg.h
index 21fadfe5b7..0c1a7ef309 100644
--- a/include/system/igvm-cfg.h
+++ b/include/system/igvm-cfg.h
@@ -38,6 +38,16 @@ typedef struct IgvmCfgClass {
int (*process)(IgvmCfg *cfg, ConfidentialGuestSupport *cgs,
Error **errp);
+ /*
+ * If an IGVM filename has been specified then only process
+ * the VMSA sections in the IGVM file.
+ * Performs a no-op if no filename has been specified.
+ *
+ * Returns 0 for ok and -1 on error.
+ */
+ int (*process_vp_context)(IgvmCfg *cfg, ConfidentialGuestSupport *cgs,
+ Error **errp);
+
} IgvmCfgClass;
#define TYPE_IGVM_CFG "igvm-cfg"
diff --git a/target/i386/sev.c b/target/i386/sev.c
index ef25e64b14..d22e9870ea 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -1893,14 +1893,14 @@ static int sev_common_kvm_init(ConfidentialGuestSupport
*cgs, Error **errp)
* each vcpu.
*
* The IGVM file is normally processed after initialization. Therefore
- * we need to pre-process it here to extract sev_features in order to
- * provide it to KVM_SEV_INIT2. Each cgs_* function that is called by
- * the IGVM processor detects this pre-process by observing the state
- * as SEV_STATE_UNINIT.
+ * we need to pre-process it here, just looking for the vp_context to
+ * extract sev_features in order to provide it to KVM_SEV_INIT2. Each
+ * cgs_* function that is called by the IGVM processor detects this
+ * pre-process by observing the state as SEV_STATE_UNINIT.
*/
if (x86machine->igvm) {
if (IGVM_CFG_GET_CLASS(x86machine->igvm)
- ->process(x86machine->igvm, machine->cgs, errp) == -1) {
+ ->process_vp_context(x86machine->igvm, machine->cgs, errp)
== -1) {
... here?
BTW we can fix it later, but since you have to repost, I pointed it out.
Thanks,
Stefano
return -1;
}
/*
--
2.43.0