* [PATCH v3 0/6] igvm: Supply MADT via IGVM parameter
@ 2026-01-09 14:34 Oliver Steffen
2026-01-09 14:34 ` [PATCH v3 1/6] hw/acpi: Make BIOS linker optional Oliver Steffen
` (6 more replies)
0 siblings, 7 replies; 19+ messages in thread
From: Oliver Steffen @ 2026-01-09 14:34 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Igor Mammedov, Paolo Bonzini, Marcelo Tosatti,
Ani Sinha, Stefano Garzarella, Luigi Leonardi, Zhao Liu,
Joerg Roedel, Gerd Hoffmann, kvm, Eduardo Habkost,
Michael S. Tsirkin, Marcel Apfelbaum, Oliver Steffen
When launching using an IGVM file, supply a copy of the MADT (part of the ACPI
tables) via an IGVM parameter (IGVM_VHY_MADT) to the guest, in addition to the
regular fw_cfg mechanism.
The IGVM parameter can be consumed by Coconut SVSM [1], instead of relying on
the fw_cfg interface, which has caused problems before due to unexpected access
[2,3]. Using IGVM parameters is the default way for Coconut SVSM; switching
over would allow removing specialized code paths for QEMU in Coconut.
In any case OVMF, which runs after SVSM has already been initialized, will
continue reading all ACPI tables via fw_cfg and provide fixed up ACPI data to
the OS as before.
This series makes ACPI table building more generic by making the BIOS linker
optional. This allows the MADT to be generated outside of the ACPI build
context. A new function (acpi_build_madt_standalone()) is added for that. With
that, the IGVM MADT parameter field can be filled with the MADT data during
processing of the IGVM file.
Generating the MADT twice (IGVM processing and ACPI table building) seems
acceptable, since there is no infrastructure to obtain the MADT out of the ACPI
table memory area during IGVM processing.
[1] https://github.com/coconut-svsm/svsm/pull/858
[2] https://gitlab.com/qemu-project/qemu/-/issues/2882
[3] https://github.com/coconut-svsm/svsm/issues/646
v3:
- Pass the machine state into IGVM file processing context instead of MADT data
- Generate MADT from inside the IGVM backend
- Refactor: Extract common code for finding IGVM parameter from IGVM parameter handlers
- Add NULL pointer check for igvm_get_buffer()
v2:
- Provide more context in the message of the main commit
- Document the madt parameter of IgvmCfgClass::process()
- Document why no MADT data is provided the process call in sev.c
Based-on: <20251118122133.1695767-1-kraxel@redhat.com>
Signed-off-by: Oliver Steffen <osteffen@redhat.com>
Oliver Steffen (6):
hw/acpi: Make BIOS linker optional
hw/acpi: Add standalone function to build MADT
igvm: Add missing NULL check
igvm: Add common function for finding parameter entries
igvm: Pass machine state to IGVM file processing
igvm: Fill MADT IGVM parameter field
backends/igvm-cfg.c | 2 +-
backends/igvm.c | 169 +++++++++++++++++++++++++-------------
hw/acpi/aml-build.c | 7 +-
hw/i386/acpi-build.c | 8 ++
hw/i386/acpi-build.h | 2 +
include/system/igvm-cfg.h | 3 +-
include/system/igvm.h | 3 +-
target/i386/sev.c | 2 +-
8 files changed, 132 insertions(+), 64 deletions(-)
--
2.52.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 1/6] hw/acpi: Make BIOS linker optional
2026-01-09 14:34 [PATCH v3 0/6] igvm: Supply MADT via IGVM parameter Oliver Steffen
@ 2026-01-09 14:34 ` Oliver Steffen
2026-01-12 9:47 ` Gerd Hoffmann
2026-01-09 14:34 ` [PATCH v3 2/6] hw/acpi: Add standalone function to build MADT Oliver Steffen
` (5 subsequent siblings)
6 siblings, 1 reply; 19+ messages in thread
From: Oliver Steffen @ 2026-01-09 14:34 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Igor Mammedov, Paolo Bonzini, Marcelo Tosatti,
Ani Sinha, Stefano Garzarella, Luigi Leonardi, Zhao Liu,
Joerg Roedel, Gerd Hoffmann, kvm, Eduardo Habkost,
Michael S. Tsirkin, Marcel Apfelbaum, Oliver Steffen
Make the BIOS linker optional in acpi_table_end().
This makes it possible to call for example
acpi_build_madt() from outside the ACPI table builder context.
Signed-off-by: Oliver Steffen <osteffen@redhat.com>
---
hw/acpi/aml-build.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 2d5826a8f1..ed86867ae3 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1748,8 +1748,11 @@ void acpi_table_end(BIOSLinker *linker, AcpiTable *desc)
*/
memcpy(len_ptr, &table_len_le, sizeof table_len_le);
- bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
- desc->table_offset, table_len, desc->table_offset + checksum_offset);
+ if (linker != NULL) {
+ bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
+ desc->table_offset, table_len,
+ desc->table_offset + checksum_offset);
+ }
}
void *acpi_data_push(GArray *table_data, unsigned size)
--
2.52.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 2/6] hw/acpi: Add standalone function to build MADT
2026-01-09 14:34 [PATCH v3 0/6] igvm: Supply MADT via IGVM parameter Oliver Steffen
2026-01-09 14:34 ` [PATCH v3 1/6] hw/acpi: Make BIOS linker optional Oliver Steffen
@ 2026-01-09 14:34 ` Oliver Steffen
2026-01-09 14:34 ` [PATCH v3 3/6] igvm: Add missing NULL check Oliver Steffen
` (4 subsequent siblings)
6 siblings, 0 replies; 19+ messages in thread
From: Oliver Steffen @ 2026-01-09 14:34 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Igor Mammedov, Paolo Bonzini, Marcelo Tosatti,
Ani Sinha, Stefano Garzarella, Luigi Leonardi, Zhao Liu,
Joerg Roedel, Gerd Hoffmann, kvm, Eduardo Habkost,
Michael S. Tsirkin, Marcel Apfelbaum, Oliver Steffen
Add a fuction called `acpi_build_madt_standalone()` that builds a MADT
without the rest of the ACPI table structure.
Signed-off-by: Oliver Steffen <osteffen@redhat.com>
---
hw/i386/acpi-build.c | 8 ++++++++
hw/i386/acpi-build.h | 2 ++
2 files changed, 10 insertions(+)
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 9446a9f862..e472876567 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -2249,3 +2249,11 @@ void acpi_setup(void)
*/
acpi_build_tables_cleanup(&tables, false);
}
+
+GArray *acpi_build_madt_standalone(MachineState *machine) {
+ X86MachineState *x86ms = X86_MACHINE(machine);
+ GArray *table = g_array_new(false, true, 1);
+ acpi_build_madt(table, NULL, x86ms, x86ms->oem_id,
+ x86ms->oem_table_id);
+ return table;
+}
diff --git a/hw/i386/acpi-build.h b/hw/i386/acpi-build.h
index 8ba3c33e48..00e19bbe5e 100644
--- a/hw/i386/acpi-build.h
+++ b/hw/i386/acpi-build.h
@@ -8,4 +8,6 @@ extern const struct AcpiGenericAddress x86_nvdimm_acpi_dsmio;
void acpi_setup(void);
Object *acpi_get_i386_pci_host(void);
+GArray *acpi_build_madt_standalone(MachineState *machine);
+
#endif
--
2.52.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 3/6] igvm: Add missing NULL check
2026-01-09 14:34 [PATCH v3 0/6] igvm: Supply MADT via IGVM parameter Oliver Steffen
2026-01-09 14:34 ` [PATCH v3 1/6] hw/acpi: Make BIOS linker optional Oliver Steffen
2026-01-09 14:34 ` [PATCH v3 2/6] hw/acpi: Add standalone function to build MADT Oliver Steffen
@ 2026-01-09 14:34 ` Oliver Steffen
2026-01-09 17:37 ` Luigi Leonardi
2026-01-13 7:21 ` Ani Sinha
2026-01-09 14:34 ` [PATCH v3 4/6] igvm: Add common function for finding parameter entries Oliver Steffen
` (3 subsequent siblings)
6 siblings, 2 replies; 19+ messages in thread
From: Oliver Steffen @ 2026-01-09 14:34 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Igor Mammedov, Paolo Bonzini, Marcelo Tosatti,
Ani Sinha, Stefano Garzarella, Luigi Leonardi, Zhao Liu,
Joerg Roedel, Gerd Hoffmann, kvm, Eduardo Habkost,
Michael S. Tsirkin, Marcel Apfelbaum, Oliver Steffen
Check for NULL pointer returned from igvm_get_buffer().
Documentation for that function calls for that unconditionally.
Signed-off-by: Oliver Steffen <osteffen@redhat.com>
---
backends/igvm.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/backends/igvm.c b/backends/igvm.c
index a350c890cc..dc1fd026cb 100644
--- a/backends/igvm.c
+++ b/backends/igvm.c
@@ -170,9 +170,16 @@ static int qigvm_handler(QIgvm *ctx, uint32_t type, Error **errp)
(int)header_handle);
return -1;
}
- header_data = igvm_get_buffer(ctx->file, header_handle) +
- sizeof(IGVM_VHS_VARIABLE_HEADER);
- result = handlers[handler].handler(ctx, header_data, errp);
+ header_data = igvm_get_buffer(ctx->file, header_handle);
+ if (header_data == NULL) {
+ error_setg(
+ errp,
+ "IGVM: Failed to get directive header data (code: %d)",
+ (int)header_handle);
+ result = -1;
+ } else {
+ result = handlers[handler].handler(ctx, header_data + sizeof(IGVM_VHS_VARIABLE_HEADER), errp);
+ }
igvm_free_buffer(ctx->file, header_handle);
return result;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 4/6] igvm: Add common function for finding parameter entries
2026-01-09 14:34 [PATCH v3 0/6] igvm: Supply MADT via IGVM parameter Oliver Steffen
` (2 preceding siblings ...)
2026-01-09 14:34 ` [PATCH v3 3/6] igvm: Add missing NULL check Oliver Steffen
@ 2026-01-09 14:34 ` Oliver Steffen
2026-01-12 9:43 ` Gerd Hoffmann
2026-01-09 14:34 ` [PATCH v3 5/6] igvm: Pass machine state to IGVM file processing Oliver Steffen
` (2 subsequent siblings)
6 siblings, 1 reply; 19+ messages in thread
From: Oliver Steffen @ 2026-01-09 14:34 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Igor Mammedov, Paolo Bonzini, Marcelo Tosatti,
Ani Sinha, Stefano Garzarella, Luigi Leonardi, Zhao Liu,
Joerg Roedel, Gerd Hoffmann, kvm, Eduardo Habkost,
Michael S. Tsirkin, Marcel Apfelbaum, Oliver Steffen
Move repeating code for finding the parameter entries in the IGVM
backend out of the parameter handlers into a common function.
---
backends/igvm.c | 115 +++++++++++++++++++++++++-----------------------
1 file changed, 61 insertions(+), 54 deletions(-)
diff --git a/backends/igvm.c b/backends/igvm.c
index dc1fd026cb..a797bd741c 100644
--- a/backends/igvm.c
+++ b/backends/igvm.c
@@ -95,6 +95,18 @@ typedef struct QIgvm {
unsigned region_page_count;
} QIgvm;
+static QIgvmParameterData *qigvm_find_param_entry(QIgvm *igvm, const IGVM_VHS_PARAMETER *param) {
+
+ QIgvmParameterData *param_entry;
+ QTAILQ_FOREACH(param_entry, &igvm->parameter_data, next)
+ {
+ if (param_entry->index == param->parameter_area_index) {
+ return param_entry;
+ }
+ }
+ return NULL;
+}
+
static int qigvm_directive_page_data(QIgvm *ctx, const uint8_t *header_data,
Error **errp);
static int qigvm_directive_vp_context(QIgvm *ctx, const uint8_t *header_data,
@@ -576,57 +588,54 @@ static int qigvm_directive_memory_map(QIgvm *ctx, const uint8_t *header_data,
}
/* Find the parameter area that should hold the memory map */
- QTAILQ_FOREACH(param_entry, &ctx->parameter_data, next)
+ param_entry = qigvm_find_param_entry(ctx, param);
+ if (param_entry != NULL)
{
- if (param_entry->index == param->parameter_area_index) {
- max_entry_count =
- param_entry->size / sizeof(IGVM_VHS_MEMORY_MAP_ENTRY);
- mm_entry = (IGVM_VHS_MEMORY_MAP_ENTRY *)param_entry->data;
-
- retval = get_mem_map_entry(entry, &cgmm_entry, errp);
- while (retval == 0) {
- if (entry >= max_entry_count) {
- error_setg(
- errp,
- "IGVM: guest memory map size exceeds parameter area defined in IGVM file");
- return -1;
- }
- mm_entry[entry].starting_gpa_page_number = cgmm_entry.gpa >> 12;
- mm_entry[entry].number_of_pages = cgmm_entry.size >> 12;
-
- switch (cgmm_entry.type) {
- case CGS_MEM_RAM:
- mm_entry[entry].entry_type =
- IGVM_MEMORY_MAP_ENTRY_TYPE_MEMORY;
- break;
- case CGS_MEM_RESERVED:
- mm_entry[entry].entry_type =
- IGVM_MEMORY_MAP_ENTRY_TYPE_PLATFORM_RESERVED;
- break;
- case CGS_MEM_ACPI:
- mm_entry[entry].entry_type =
- IGVM_MEMORY_MAP_ENTRY_TYPE_PLATFORM_RESERVED;
- break;
- case CGS_MEM_NVS:
- mm_entry[entry].entry_type =
- IGVM_MEMORY_MAP_ENTRY_TYPE_PERSISTENT;
- break;
- case CGS_MEM_UNUSABLE:
- mm_entry[entry].entry_type =
- IGVM_MEMORY_MAP_ENTRY_TYPE_PLATFORM_RESERVED;
- break;
- }
- retval = get_mem_map_entry(++entry, &cgmm_entry, errp);
+ max_entry_count =
+ param_entry->size / sizeof(IGVM_VHS_MEMORY_MAP_ENTRY);
+ mm_entry = (IGVM_VHS_MEMORY_MAP_ENTRY *)param_entry->data;
+
+ retval = get_mem_map_entry(entry, &cgmm_entry, errp);
+ while (retval == 0) {
+ if (entry >= max_entry_count) {
+ error_setg(
+ errp,
+ "IGVM: guest memory map size exceeds parameter area defined in IGVM file");
+ return -1;
}
- if (retval < 0) {
- return retval;
+ mm_entry[entry].starting_gpa_page_number = cgmm_entry.gpa >> 12;
+ mm_entry[entry].number_of_pages = cgmm_entry.size >> 12;
+
+ switch (cgmm_entry.type) {
+ case CGS_MEM_RAM:
+ mm_entry[entry].entry_type =
+ IGVM_MEMORY_MAP_ENTRY_TYPE_MEMORY;
+ break;
+ case CGS_MEM_RESERVED:
+ mm_entry[entry].entry_type =
+ IGVM_MEMORY_MAP_ENTRY_TYPE_PLATFORM_RESERVED;
+ break;
+ case CGS_MEM_ACPI:
+ mm_entry[entry].entry_type =
+ IGVM_MEMORY_MAP_ENTRY_TYPE_PLATFORM_RESERVED;
+ break;
+ case CGS_MEM_NVS:
+ mm_entry[entry].entry_type =
+ IGVM_MEMORY_MAP_ENTRY_TYPE_PERSISTENT;
+ break;
+ case CGS_MEM_UNUSABLE:
+ mm_entry[entry].entry_type =
+ IGVM_MEMORY_MAP_ENTRY_TYPE_PLATFORM_RESERVED;
+ break;
}
- /* The entries need to be sorted */
- qsort(mm_entry, entry, sizeof(IGVM_VHS_MEMORY_MAP_ENTRY),
- qigvm_cmp_mm_entry);
-
- break;
+ retval = get_mem_map_entry(++entry, &cgmm_entry, errp);
}
+ if (retval < 0) {
+ return retval;
+ }
+ /* The entries need to be sorted */
+ qsort(mm_entry, entry, sizeof(IGVM_VHS_MEMORY_MAP_ENTRY),
+ qigvm_cmp_mm_entry);
}
return 0;
}
@@ -662,14 +671,12 @@ static int qigvm_directive_environment_info(QIgvm *ctx,
QIgvmParameterData *param_entry;
IgvmEnvironmentInfo *environmental_state;
- QTAILQ_FOREACH(param_entry, &ctx->parameter_data, next)
+ param_entry = qigvm_find_param_entry(ctx, param);
+ if (param_entry != NULL)
{
- if (param_entry->index == param->parameter_area_index) {
- environmental_state =
- (IgvmEnvironmentInfo *)(param_entry->data + param->byte_offset);
- environmental_state->memory_is_shared = 1;
- break;
- }
+ environmental_state =
+ (IgvmEnvironmentInfo *)(param_entry->data + param->byte_offset);
+ environmental_state->memory_is_shared = 1;
}
return 0;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 5/6] igvm: Pass machine state to IGVM file processing
2026-01-09 14:34 [PATCH v3 0/6] igvm: Supply MADT via IGVM parameter Oliver Steffen
` (3 preceding siblings ...)
2026-01-09 14:34 ` [PATCH v3 4/6] igvm: Add common function for finding parameter entries Oliver Steffen
@ 2026-01-09 14:34 ` Oliver Steffen
2026-01-12 9:09 ` Luigi Leonardi
2026-01-09 14:34 ` [PATCH v3 6/6] igvm: Fill MADT IGVM parameter field Oliver Steffen
2026-01-12 12:34 ` [PATCH v3 0/6] igvm: Supply MADT via IGVM parameter Igor Mammedov
6 siblings, 1 reply; 19+ messages in thread
From: Oliver Steffen @ 2026-01-09 14:34 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Igor Mammedov, Paolo Bonzini, Marcelo Tosatti,
Ani Sinha, Stefano Garzarella, Luigi Leonardi, Zhao Liu,
Joerg Roedel, Gerd Hoffmann, kvm, Eduardo Habkost,
Michael S. Tsirkin, Marcel Apfelbaum, Oliver Steffen
Add a new MachineState* parameter to qigvm_process_file()
to make the machine state available in the IGVM processing
context. We will use it later to generate MADT data there
to pass to the guest as IGVM parameter.
Signed-off-by: Oliver Steffen <osteffen@redhat.com>
---
backends/igvm-cfg.c | 2 +-
backends/igvm.c | 6 +++++-
include/system/igvm-cfg.h | 3 ++-
include/system/igvm.h | 3 ++-
target/i386/sev.c | 2 +-
5 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/backends/igvm-cfg.c b/backends/igvm-cfg.c
index c1b45401f4..d79bdecab1 100644
--- a/backends/igvm-cfg.c
+++ b/backends/igvm-cfg.c
@@ -51,7 +51,7 @@ static void igvm_reset_hold(Object *obj, ResetType type)
trace_igvm_reset_hold(type);
- qigvm_process_file(igvm, ms->cgs, false, &error_fatal);
+ qigvm_process_file(igvm, ms->cgs, false, ms, &error_fatal);
}
static void igvm_reset_exit(Object *obj, ResetType type)
diff --git a/backends/igvm.c b/backends/igvm.c
index a797bd741c..7390dee734 100644
--- a/backends/igvm.c
+++ b/backends/igvm.c
@@ -11,6 +11,7 @@
#include "qemu/osdep.h"
+#include "hw/boards.h"
#include "qapi/error.h"
#include "qemu/target-info-qapi.h"
#include "system/igvm.h"
@@ -93,6 +94,7 @@ typedef struct QIgvm {
unsigned region_start_index;
unsigned region_last_index;
unsigned region_page_count;
+ MachineState *machine_state;
} QIgvm;
static QIgvmParameterData *qigvm_find_param_entry(QIgvm *igvm, const IGVM_VHS_PARAMETER *param) {
@@ -906,7 +908,7 @@ IgvmHandle qigvm_file_init(char *filename, Error **errp)
}
int qigvm_process_file(IgvmCfg *cfg, ConfidentialGuestSupport *cgs,
- bool onlyVpContext, Error **errp)
+ bool onlyVpContext, MachineState *machine_state, Error **errp)
{
int32_t header_count;
QIgvmParameterData *parameter;
@@ -929,6 +931,8 @@ int qigvm_process_file(IgvmCfg *cfg, ConfidentialGuestSupport *cgs,
ctx.cgs = cgs;
ctx.cgsc = cgs ? CONFIDENTIAL_GUEST_SUPPORT_GET_CLASS(cgs) : NULL;
+ ctx.machine_state = machine_state;
+
/*
* Check that the IGVM file provides configuration for the current
* platform
diff --git a/include/system/igvm-cfg.h b/include/system/igvm-cfg.h
index 7dc48677fd..2783fc542e 100644
--- a/include/system/igvm-cfg.h
+++ b/include/system/igvm-cfg.h
@@ -12,6 +12,7 @@
#ifndef QEMU_IGVM_CFG_H
#define QEMU_IGVM_CFG_H
+#include "hw/boards.h"
#include "qom/object.h"
#include "hw/resettable.h"
@@ -43,7 +44,7 @@ typedef struct IgvmCfgClass {
* Returns 0 for ok and -1 on error.
*/
int (*process)(IgvmCfg *cfg, ConfidentialGuestSupport *cgs,
- bool onlyVpContext, Error **errp);
+ bool onlyVpContext, MachineState *machine_state, Error **errp);
} IgvmCfgClass;
diff --git a/include/system/igvm.h b/include/system/igvm.h
index ec2538daa0..0afe784a17 100644
--- a/include/system/igvm.h
+++ b/include/system/igvm.h
@@ -14,11 +14,12 @@
#include "system/confidential-guest-support.h"
#include "system/igvm-cfg.h"
+#include "hw/boards.h"
#include "qapi/error.h"
IgvmHandle qigvm_file_init(char *filename, Error **errp);
int qigvm_process_file(IgvmCfg *igvm, ConfidentialGuestSupport *cgs,
- bool onlyVpContext, Error **errp);
+ bool onlyVpContext, MachineState *machine_state, Error **errp);
/* x86 native */
int qigvm_x86_get_mem_map_entry(int index,
diff --git a/target/i386/sev.c b/target/i386/sev.c
index fd2dada013..a733868043 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -1892,7 +1892,7 @@ static int sev_common_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
*/
if (x86machine->igvm) {
if (IGVM_CFG_GET_CLASS(x86machine->igvm)
- ->process(x86machine->igvm, machine->cgs, true, errp) ==
+ ->process(x86machine->igvm, machine->cgs, true, machine, errp) ==
-1) {
return -1;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 6/6] igvm: Fill MADT IGVM parameter field
2026-01-09 14:34 [PATCH v3 0/6] igvm: Supply MADT via IGVM parameter Oliver Steffen
` (4 preceding siblings ...)
2026-01-09 14:34 ` [PATCH v3 5/6] igvm: Pass machine state to IGVM file processing Oliver Steffen
@ 2026-01-09 14:34 ` Oliver Steffen
2026-01-12 9:57 ` Luigi Leonardi
2026-01-12 12:34 ` [PATCH v3 0/6] igvm: Supply MADT via IGVM parameter Igor Mammedov
6 siblings, 1 reply; 19+ messages in thread
From: Oliver Steffen @ 2026-01-09 14:34 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Igor Mammedov, Paolo Bonzini, Marcelo Tosatti,
Ani Sinha, Stefano Garzarella, Luigi Leonardi, Zhao Liu,
Joerg Roedel, Gerd Hoffmann, kvm, Eduardo Habkost,
Michael S. Tsirkin, Marcel Apfelbaum, Oliver Steffen
Use the new acpi_build_madt_standalone() function to fill the MADT
parameter field.
The IGVM parameter can be consumed by Coconut SVSM [1], instead of
relying on the fw_cfg interface, which has caused problems before due to
unexpected access [2,3]. Using IGVM parameters is the default way for
Coconut SVSM; switching over would allow removing specialized code paths
for QEMU in Coconut.
In any case OVMF, which runs after SVSM has already been initialized,
will continue reading all ACPI tables via fw_cfg and provide fixed up
ACPI data to the OS as before.
Generating the MADT twice (during ACPI table building and IGVM processing)
seems acceptable, since there is no infrastructure to obtain the MADT
out of the ACPI table memory area.
[1] https://github.com/coconut-svsm/svsm/pull/858
[2] https://gitlab.com/qemu-project/qemu/-/issues/2882
[3] https://github.com/coconut-svsm/svsm/issues/646
Signed-off-by: Oliver Steffen <osteffen@redhat.com>
SQUASH: Rename madt parameter handler
---
backends/igvm.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/backends/igvm.c b/backends/igvm.c
index 7390dee734..90ea2c22fd 100644
--- a/backends/igvm.c
+++ b/backends/igvm.c
@@ -15,9 +15,11 @@
#include "qapi/error.h"
#include "qemu/target-info-qapi.h"
#include "system/igvm.h"
+#include "glib.h"
#include "system/memory.h"
#include "system/address-spaces.h"
#include "hw/core/cpu.h"
+#include "hw/i386/acpi-build.h"
#include "trace.h"
@@ -134,6 +136,8 @@ static int qigvm_directive_snp_id_block(QIgvm *ctx, const uint8_t *header_data,
static int qigvm_initialization_guest_policy(QIgvm *ctx,
const uint8_t *header_data,
Error **errp);
+static int qigvm_directive_madt(QIgvm *ctx,
+ const uint8_t *header_data, Error **errp);
struct QIGVMHandler {
uint32_t type;
@@ -162,6 +166,8 @@ static struct QIGVMHandler handlers[] = {
qigvm_directive_snp_id_block },
{ IGVM_VHT_GUEST_POLICY, IGVM_HEADER_SECTION_INITIALIZATION,
qigvm_initialization_guest_policy },
+ { IGVM_VHT_MADT, IGVM_HEADER_SECTION_DIRECTIVE,
+ qigvm_directive_madt },
};
static int qigvm_handler(QIgvm *ctx, uint32_t type, Error **errp)
@@ -780,6 +786,35 @@ static int qigvm_initialization_guest_policy(QIgvm *ctx,
return 0;
}
+static int qigvm_directive_madt(QIgvm *ctx,
+ const uint8_t *header_data, Error **errp)
+{
+ const IGVM_VHS_PARAMETER *param = (const IGVM_VHS_PARAMETER *)header_data;
+ QIgvmParameterData *param_entry;
+
+ if (ctx->machine_state == NULL) {
+ return 0;
+ }
+
+ /* Find the parameter area that should hold the MADT data */
+ param_entry = qigvm_find_param_entry(ctx, param);
+ if (param_entry != NULL) {
+
+ GArray *madt = acpi_build_madt_standalone(ctx->machine_state);
+
+ if (madt->len > param_entry->size) {
+ error_setg(
+ errp,
+ "IGVM: MADT size exceeds parameter area defined in IGVM file");
+ return -1;
+ }
+ memcpy(param_entry->data, madt->data, madt->len);
+
+ g_array_free(madt, true);
+ }
+ return 0;
+}
+
static int qigvm_supported_platform_compat_mask(QIgvm *ctx, Error **errp)
{
int32_t header_count;
--
2.52.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v3 3/6] igvm: Add missing NULL check
2026-01-09 14:34 ` [PATCH v3 3/6] igvm: Add missing NULL check Oliver Steffen
@ 2026-01-09 17:37 ` Luigi Leonardi
2026-01-12 9:41 ` Gerd Hoffmann
2026-01-13 7:21 ` Ani Sinha
1 sibling, 1 reply; 19+ messages in thread
From: Luigi Leonardi @ 2026-01-09 17:37 UTC (permalink / raw)
To: Oliver Steffen
Cc: qemu-devel, Richard Henderson, Igor Mammedov, Paolo Bonzini,
Marcelo Tosatti, Ani Sinha, Stefano Garzarella, Zhao Liu,
Joerg Roedel, Gerd Hoffmann, kvm, Eduardo Habkost,
Michael S. Tsirkin, Marcel Apfelbaum
On Fri, Jan 09, 2026 at 03:34:10PM +0100, Oliver Steffen wrote:
>Check for NULL pointer returned from igvm_get_buffer().
>Documentation for that function calls for that unconditionally.
>
>Signed-off-by: Oliver Steffen <osteffen@redhat.com>
>---
> backends/igvm.c | 13 ++++++++++---
> 1 file changed, 10 insertions(+), 3 deletions(-)
>
>diff --git a/backends/igvm.c b/backends/igvm.c
>index a350c890cc..dc1fd026cb 100644
>--- a/backends/igvm.c
>+++ b/backends/igvm.c
>@@ -170,9 +170,16 @@ static int qigvm_handler(QIgvm *ctx, uint32_t type, Error **errp)
> (int)header_handle);
> return -1;
> }
>- header_data = igvm_get_buffer(ctx->file, header_handle) +
>- sizeof(IGVM_VHS_VARIABLE_HEADER);
>- result = handlers[handler].handler(ctx, header_data, errp);
>+ header_data = igvm_get_buffer(ctx->file, header_handle);
>+ if (header_data == NULL) {
>+ error_setg(
>+ errp,
>+ "IGVM: Failed to get directive header data (code: %d)",
>+ (int)header_handle);
>+ result = -1;
>+ } else {
>+ result = handlers[handler].handler(ctx, header_data + sizeof(IGVM_VHS_VARIABLE_HEADER), errp);
>+ }
> igvm_free_buffer(ctx->file, header_handle);
> return result;
> }
>-- 2.52.0
>
IMHO this should be sent a separate patch with the Fixes tag as you are
fixing a bug.
Luigi
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 5/6] igvm: Pass machine state to IGVM file processing
2026-01-09 14:34 ` [PATCH v3 5/6] igvm: Pass machine state to IGVM file processing Oliver Steffen
@ 2026-01-12 9:09 ` Luigi Leonardi
0 siblings, 0 replies; 19+ messages in thread
From: Luigi Leonardi @ 2026-01-12 9:09 UTC (permalink / raw)
To: Oliver Steffen
Cc: qemu-devel, Richard Henderson, Igor Mammedov, Paolo Bonzini,
Marcelo Tosatti, Ani Sinha, Stefano Garzarella, Zhao Liu,
Joerg Roedel, Gerd Hoffmann, kvm, Eduardo Habkost,
Michael S. Tsirkin, Marcel Apfelbaum
On Fri, Jan 09, 2026 at 03:34:12PM +0100, Oliver Steffen wrote:
>Add a new MachineState* parameter to qigvm_process_file()
>to make the machine state available in the IGVM processing
>context. We will use it later to generate MADT data there
>to pass to the guest as IGVM parameter.
>
>Signed-off-by: Oliver Steffen <osteffen@redhat.com>
>---
> backends/igvm-cfg.c | 2 +-
> backends/igvm.c | 6 +++++-
> include/system/igvm-cfg.h | 3 ++-
> include/system/igvm.h | 3 ++-
> target/i386/sev.c | 2 +-
> 5 files changed, 11 insertions(+), 5 deletions(-)
>
>diff --git a/backends/igvm-cfg.c b/backends/igvm-cfg.c
>index c1b45401f4..d79bdecab1 100644
>--- a/backends/igvm-cfg.c
>+++ b/backends/igvm-cfg.c
>@@ -51,7 +51,7 @@ static void igvm_reset_hold(Object *obj, ResetType type)
>
> trace_igvm_reset_hold(type);
>
>- qigvm_process_file(igvm, ms->cgs, false, &error_fatal);
>+ qigvm_process_file(igvm, ms->cgs, false, ms, &error_fatal);
> }
>
> static void igvm_reset_exit(Object *obj, ResetType type)
>diff --git a/backends/igvm.c b/backends/igvm.c
>index a797bd741c..7390dee734 100644
>--- a/backends/igvm.c
>+++ b/backends/igvm.c
>@@ -11,6 +11,7 @@
>
> #include "qemu/osdep.h"
>
>+#include "hw/boards.h"
> #include "qapi/error.h"
> #include "qemu/target-info-qapi.h"
> #include "system/igvm.h"
>@@ -93,6 +94,7 @@ typedef struct QIgvm {
> unsigned region_start_index;
> unsigned region_last_index;
> unsigned region_page_count;
>+ MachineState *machine_state;
> } QIgvm;
>
> static QIgvmParameterData *qigvm_find_param_entry(QIgvm *igvm, const IGVM_VHS_PARAMETER *param) {
>@@ -906,7 +908,7 @@ IgvmHandle qigvm_file_init(char *filename, Error **errp)
> }
>
> int qigvm_process_file(IgvmCfg *cfg, ConfidentialGuestSupport *cgs,
>- bool onlyVpContext, Error **errp)
>+ bool onlyVpContext, MachineState *machine_state, Error **errp)
> {
> int32_t header_count;
> QIgvmParameterData *parameter;
>@@ -929,6 +931,8 @@ int qigvm_process_file(IgvmCfg *cfg, ConfidentialGuestSupport *cgs,
> ctx.cgs = cgs;
> ctx.cgsc = cgs ? CONFIDENTIAL_GUEST_SUPPORT_GET_CLASS(cgs) : NULL;
>
>+ ctx.machine_state = machine_state;
>+
> /*
> * Check that the IGVM file provides configuration for the current
> * platform
>diff --git a/include/system/igvm-cfg.h b/include/system/igvm-cfg.h
>index 7dc48677fd..2783fc542e 100644
>--- a/include/system/igvm-cfg.h
>+++ b/include/system/igvm-cfg.h
>@@ -12,6 +12,7 @@
> #ifndef QEMU_IGVM_CFG_H
> #define QEMU_IGVM_CFG_H
>
>+#include "hw/boards.h"
> #include "qom/object.h"
> #include "hw/resettable.h"
>
>@@ -43,7 +44,7 @@ typedef struct IgvmCfgClass {
> * Returns 0 for ok and -1 on error.
> */
> int (*process)(IgvmCfg *cfg, ConfidentialGuestSupport *cgs,
>- bool onlyVpContext, Error **errp);
>+ bool onlyVpContext, MachineState *machine_state, Error **errp);
>
> } IgvmCfgClass;
>
>diff --git a/include/system/igvm.h b/include/system/igvm.h
>index ec2538daa0..0afe784a17 100644
>--- a/include/system/igvm.h
>+++ b/include/system/igvm.h
>@@ -14,11 +14,12 @@
>
> #include "system/confidential-guest-support.h"
> #include "system/igvm-cfg.h"
>+#include "hw/boards.h"
> #include "qapi/error.h"
>
> IgvmHandle qigvm_file_init(char *filename, Error **errp);
> int qigvm_process_file(IgvmCfg *igvm, ConfidentialGuestSupport *cgs,
>- bool onlyVpContext, Error **errp);
>+ bool onlyVpContext, MachineState *machine_state, Error **errp);
>
> /* x86 native */
> int qigvm_x86_get_mem_map_entry(int index,
>diff --git a/target/i386/sev.c b/target/i386/sev.c
>index fd2dada013..a733868043 100644
>--- a/target/i386/sev.c
>+++ b/target/i386/sev.c
>@@ -1892,7 +1892,7 @@ static int sev_common_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
> */
> if (x86machine->igvm) {
> if (IGVM_CFG_GET_CLASS(x86machine->igvm)
>- ->process(x86machine->igvm, machine->cgs, true, errp) ==
>+ ->process(x86machine->igvm, machine->cgs, true, machine, errp) ==
`cgs` is part of the machine state. WDYT about dropping it?
Luigi
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 3/6] igvm: Add missing NULL check
2026-01-09 17:37 ` Luigi Leonardi
@ 2026-01-12 9:41 ` Gerd Hoffmann
2026-01-12 9:49 ` Luigi Leonardi
0 siblings, 1 reply; 19+ messages in thread
From: Gerd Hoffmann @ 2026-01-12 9:41 UTC (permalink / raw)
To: Luigi Leonardi
Cc: Oliver Steffen, qemu-devel, Richard Henderson, Igor Mammedov,
Paolo Bonzini, Marcelo Tosatti, Ani Sinha, Stefano Garzarella,
Zhao Liu, Joerg Roedel, kvm, Eduardo Habkost, Michael S. Tsirkin,
Marcel Apfelbaum
On Fri, Jan 09, 2026 at 06:37:04PM +0100, Luigi Leonardi wrote:
> On Fri, Jan 09, 2026 at 03:34:10PM +0100, Oliver Steffen wrote:
> >Check for NULL pointer returned from igvm_get_buffer().
> >Documentation for that function calls for that unconditionally.
> >
> >Signed-off-by: Oliver Steffen <osteffen@redhat.com>
> >---
> > backends/igvm.c | 13 ++++++++++---
> > 1 file changed, 10 insertions(+), 3 deletions(-)
> >
> >diff --git a/backends/igvm.c b/backends/igvm.c
> >index a350c890cc..dc1fd026cb 100644
> >--- a/backends/igvm.c
> >+++ b/backends/igvm.c
> >@@ -170,9 +170,16 @@ static int qigvm_handler(QIgvm *ctx, uint32_t type, Error **errp)
> > (int)header_handle);
> > return -1;
> > }
> >- header_data = igvm_get_buffer(ctx->file, header_handle) +
> >- sizeof(IGVM_VHS_VARIABLE_HEADER);
> >- result = handlers[handler].handler(ctx, header_data, errp);
> >+ header_data = igvm_get_buffer(ctx->file, header_handle);
> >+ if (header_data == NULL) {
> >+ error_setg(
> >+ errp,
> >+ "IGVM: Failed to get directive header data (code: %d)",
> >+ (int)header_handle);
> >+ result = -1;
> >+ } else {
> >+ result = handlers[handler].handler(ctx, header_data + sizeof(IGVM_VHS_VARIABLE_HEADER), errp);
> >+ }
> > igvm_free_buffer(ctx->file, header_handle);
> > return result;
> > }
> >-- 2.52.0
> >
>
> IMHO this should be sent a separate patch
Huh? It /is/ a separate patch ...
> with the Fixes tag as you are
> fixing a bug.
That makes sense indeed.
take care,
Gerd
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 4/6] igvm: Add common function for finding parameter entries
2026-01-09 14:34 ` [PATCH v3 4/6] igvm: Add common function for finding parameter entries Oliver Steffen
@ 2026-01-12 9:43 ` Gerd Hoffmann
0 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2026-01-12 9:43 UTC (permalink / raw)
To: Oliver Steffen
Cc: qemu-devel, Richard Henderson, Igor Mammedov, Paolo Bonzini,
Marcelo Tosatti, Ani Sinha, Stefano Garzarella, Luigi Leonardi,
Zhao Liu, Joerg Roedel, kvm, Eduardo Habkost, Michael S. Tsirkin,
Marcel Apfelbaum
On Fri, Jan 09, 2026 at 03:34:11PM +0100, Oliver Steffen wrote:
> Move repeating code for finding the parameter entries in the IGVM
> backend out of the parameter handlers into a common function.
> ---
> backends/igvm.c | 115 +++++++++++++++++++++++++-----------------------
> 1 file changed, 61 insertions(+), 54 deletions(-)
>
> diff --git a/backends/igvm.c b/backends/igvm.c
> index dc1fd026cb..a797bd741c 100644
> --- a/backends/igvm.c
> +++ b/backends/igvm.c
> @@ -95,6 +95,18 @@ typedef struct QIgvm {
> unsigned region_page_count;
> } QIgvm;
>
> +static QIgvmParameterData *qigvm_find_param_entry(QIgvm *igvm, const IGVM_VHS_PARAMETER *param) {
> +
> + QIgvmParameterData *param_entry;
> + QTAILQ_FOREACH(param_entry, &igvm->parameter_data, next)
> + {
> + if (param_entry->index == param->parameter_area_index) {
> + return param_entry;
> + }
> + }
> + return NULL;
> +}
> +
> static int qigvm_directive_page_data(QIgvm *ctx, const uint8_t *header_data,
> Error **errp);
> static int qigvm_directive_vp_context(QIgvm *ctx, const uint8_t *header_data,
> @@ -576,57 +588,54 @@ static int qigvm_directive_memory_map(QIgvm *ctx, const uint8_t *header_data,
> }
>
> /* Find the parameter area that should hold the memory map */
> - QTAILQ_FOREACH(param_entry, &ctx->parameter_data, next)
> + param_entry = qigvm_find_param_entry(ctx, param);
> + if (param_entry != NULL)
> {
if (param_entry == NULL) {
// handle error if needed
return;
}
take care,
Gerd
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 1/6] hw/acpi: Make BIOS linker optional
2026-01-09 14:34 ` [PATCH v3 1/6] hw/acpi: Make BIOS linker optional Oliver Steffen
@ 2026-01-12 9:47 ` Gerd Hoffmann
0 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2026-01-12 9:47 UTC (permalink / raw)
To: Oliver Steffen
Cc: qemu-devel, Richard Henderson, Igor Mammedov, Paolo Bonzini,
Marcelo Tosatti, Ani Sinha, Stefano Garzarella, Luigi Leonardi,
Zhao Liu, Joerg Roedel, kvm, Eduardo Habkost, Michael S. Tsirkin,
Marcel Apfelbaum
On Fri, Jan 09, 2026 at 03:34:08PM +0100, Oliver Steffen wrote:
> Make the BIOS linker optional in acpi_table_end().
> This makes it possible to call for example
> acpi_build_madt() from outside the ACPI table builder context.
>
> Signed-off-by: Oliver Steffen <osteffen@redhat.com>
> ---
> hw/acpi/aml-build.c | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index 2d5826a8f1..ed86867ae3 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -1748,8 +1748,11 @@ void acpi_table_end(BIOSLinker *linker, AcpiTable *desc)
> */
> memcpy(len_ptr, &table_len_le, sizeof table_len_le);
>
> - bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
> - desc->table_offset, table_len, desc->table_offset + checksum_offset);
> + if (linker != NULL) {
> + bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
> + desc->table_offset, table_len,
> + desc->table_offset + checksum_offset);
> + }
else {
// calculate + fill checksum directly
}
take care,
Gerd
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 3/6] igvm: Add missing NULL check
2026-01-12 9:41 ` Gerd Hoffmann
@ 2026-01-12 9:49 ` Luigi Leonardi
2026-01-12 9:57 ` Gerd Hoffmann
0 siblings, 1 reply; 19+ messages in thread
From: Luigi Leonardi @ 2026-01-12 9:49 UTC (permalink / raw)
To: Gerd Hoffmann
Cc: Oliver Steffen, qemu-devel, Richard Henderson, Igor Mammedov,
Paolo Bonzini, Marcelo Tosatti, Ani Sinha, Stefano Garzarella,
Zhao Liu, Joerg Roedel, kvm, Eduardo Habkost, Michael S. Tsirkin,
Marcel Apfelbaum
On Mon, Jan 12, 2026 at 10:41:01AM +0100, Gerd Hoffmann wrote:
>On Fri, Jan 09, 2026 at 06:37:04PM +0100, Luigi Leonardi wrote:
>> On Fri, Jan 09, 2026 at 03:34:10PM +0100, Oliver Steffen wrote:
>> >Check for NULL pointer returned from igvm_get_buffer().
>> >Documentation for that function calls for that unconditionally.
>> >
>> >Signed-off-by: Oliver Steffen <osteffen@redhat.com>
>> >---
>> > backends/igvm.c | 13 ++++++++++---
>> > 1 file changed, 10 insertions(+), 3 deletions(-)
>> >
>> >diff --git a/backends/igvm.c b/backends/igvm.c
>> >index a350c890cc..dc1fd026cb 100644
>> >--- a/backends/igvm.c
>> >+++ b/backends/igvm.c
>> >@@ -170,9 +170,16 @@ static int qigvm_handler(QIgvm *ctx, uint32_t type, Error **errp)
>> > (int)header_handle);
>> > return -1;
>> > }
>> >- header_data = igvm_get_buffer(ctx->file, header_handle) +
>> >- sizeof(IGVM_VHS_VARIABLE_HEADER);
>> >- result = handlers[handler].handler(ctx, header_data, errp);
>> >+ header_data = igvm_get_buffer(ctx->file, header_handle);
>> >+ if (header_data == NULL) {
>> >+ error_setg(
>> >+ errp,
>> >+ "IGVM: Failed to get directive header data (code: %d)",
>> >+ (int)header_handle);
>> >+ result = -1;
>> >+ } else {
>> >+ result = handlers[handler].handler(ctx, header_data + sizeof(IGVM_VHS_VARIABLE_HEADER), errp);
>> >+ }
>> > igvm_free_buffer(ctx->file, header_handle);
>> > return result;
>> > }
>> >-- 2.52.0
>> >
>>
>> IMHO this should be sent a separate patch
>
>Huh? It /is/ a separate patch ...
Sorry, I meant outside of this series.
Luigi
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 3/6] igvm: Add missing NULL check
2026-01-12 9:49 ` Luigi Leonardi
@ 2026-01-12 9:57 ` Gerd Hoffmann
2026-01-13 9:36 ` Oliver Steffen
0 siblings, 1 reply; 19+ messages in thread
From: Gerd Hoffmann @ 2026-01-12 9:57 UTC (permalink / raw)
To: Luigi Leonardi
Cc: Oliver Steffen, qemu-devel, Richard Henderson, Igor Mammedov,
Paolo Bonzini, Marcelo Tosatti, Ani Sinha, Stefano Garzarella,
Zhao Liu, Joerg Roedel, kvm, Eduardo Habkost, Michael S. Tsirkin,
Marcel Apfelbaum
Hi,
> > > IMHO this should be sent a separate patch
> >
> > Huh? It /is/ a separate patch ...
>
> Sorry, I meant outside of this series.
Not needed, separate patch is good enough, even though sending a
separate 'fixes' series might make sense in some cases (split an
already long patch series, or during freeze where only fixes are
allowed before the next release).
take care,
Gerd
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 6/6] igvm: Fill MADT IGVM parameter field
2026-01-09 14:34 ` [PATCH v3 6/6] igvm: Fill MADT IGVM parameter field Oliver Steffen
@ 2026-01-12 9:57 ` Luigi Leonardi
0 siblings, 0 replies; 19+ messages in thread
From: Luigi Leonardi @ 2026-01-12 9:57 UTC (permalink / raw)
To: Oliver Steffen
Cc: qemu-devel, Richard Henderson, Igor Mammedov, Paolo Bonzini,
Marcelo Tosatti, Ani Sinha, Stefano Garzarella, Zhao Liu,
Joerg Roedel, Gerd Hoffmann, kvm, Eduardo Habkost,
Michael S. Tsirkin, Marcel Apfelbaum
On Fri, Jan 09, 2026 at 03:34:13PM +0100, Oliver Steffen wrote:
>Use the new acpi_build_madt_standalone() function to fill the MADT
>parameter field.
>
>The IGVM parameter can be consumed by Coconut SVSM [1], instead of
>relying on the fw_cfg interface, which has caused problems before due to
>unexpected access [2,3]. Using IGVM parameters is the default way for
>Coconut SVSM; switching over would allow removing specialized code paths
>for QEMU in Coconut.
>
>In any case OVMF, which runs after SVSM has already been initialized,
>will continue reading all ACPI tables via fw_cfg and provide fixed up
>ACPI data to the OS as before.
>
>Generating the MADT twice (during ACPI table building and IGVM processing)
>seems acceptable, since there is no infrastructure to obtain the MADT
>out of the ACPI table memory area.
>
>[1] https://github.com/coconut-svsm/svsm/pull/858
>[2] https://gitlab.com/qemu-project/qemu/-/issues/2882
>[3] https://github.com/coconut-svsm/svsm/issues/646
>
>Signed-off-by: Oliver Steffen <osteffen@redhat.com>
>
>SQUASH: Rename madt parameter handler
Development leftover?
>---
> backends/igvm.c | 35 +++++++++++++++++++++++++++++++++++
> 1 file changed, 35 insertions(+)
>
>diff --git a/backends/igvm.c b/backends/igvm.c
>index 7390dee734..90ea2c22fd 100644
>--- a/backends/igvm.c
>+++ b/backends/igvm.c
>@@ -15,9 +15,11 @@
> #include "qapi/error.h"
> #include "qemu/target-info-qapi.h"
> #include "system/igvm.h"
>+#include "glib.h"
is this needed?
> #include "system/memory.h"
> #include "system/address-spaces.h"
> #include "hw/core/cpu.h"
>+#include "hw/i386/acpi-build.h"
>
> #include "trace.h"
>
>@@ -134,6 +136,8 @@ static int qigvm_directive_snp_id_block(QIgvm *ctx, const uint8_t *header_data,
> static int qigvm_initialization_guest_policy(QIgvm *ctx,
> const uint8_t *header_data,
> Error **errp);
>+static int qigvm_directive_madt(QIgvm *ctx,
>+ const uint8_t *header_data, Error **errp);
>
> struct QIGVMHandler {
> uint32_t type;
>@@ -162,6 +166,8 @@ static struct QIGVMHandler handlers[] = {
> qigvm_directive_snp_id_block },
> { IGVM_VHT_GUEST_POLICY, IGVM_HEADER_SECTION_INITIALIZATION,
> qigvm_initialization_guest_policy },
>+ { IGVM_VHT_MADT, IGVM_HEADER_SECTION_DIRECTIVE,
>+ qigvm_directive_madt },
> };
>
> static int qigvm_handler(QIgvm *ctx, uint32_t type, Error **errp)
>@@ -780,6 +786,35 @@ static int qigvm_initialization_guest_policy(QIgvm *ctx,
> return 0;
> }
>
>+static int qigvm_directive_madt(QIgvm *ctx,
>+ const uint8_t *header_data, Error **errp)
>+{
>+ const IGVM_VHS_PARAMETER *param = (const IGVM_VHS_PARAMETER *)header_data;
>+ QIgvmParameterData *param_entry;
>+
>+ if (ctx->machine_state == NULL) {
>+ return 0;
>+ }
>+
>+ /* Find the parameter area that should hold the MADT data */
>+ param_entry = qigvm_find_param_entry(ctx, param);
>+ if (param_entry != NULL) {
>+
>+ GArray *madt = acpi_build_madt_standalone(ctx->machine_state);
>+
>+ if (madt->len > param_entry->size) {
>+ error_setg(
>+ errp,
>+ "IGVM: MADT size exceeds parameter area defined in IGVM file");
>+ return -1;
>+ }
>+ memcpy(param_entry->data, madt->data, madt->len);
>+
>+ g_array_free(madt, true);
>+ }
>+ return 0;
>+}
>+
> static int qigvm_supported_platform_compat_mask(QIgvm *ctx, Error **errp)
> {
> int32_t header_count;
>--
>2.52.0
>
Rest LGTM!
Luigi
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 0/6] igvm: Supply MADT via IGVM parameter
2026-01-09 14:34 [PATCH v3 0/6] igvm: Supply MADT via IGVM parameter Oliver Steffen
` (5 preceding siblings ...)
2026-01-09 14:34 ` [PATCH v3 6/6] igvm: Fill MADT IGVM parameter field Oliver Steffen
@ 2026-01-12 12:34 ` Igor Mammedov
6 siblings, 0 replies; 19+ messages in thread
From: Igor Mammedov @ 2026-01-12 12:34 UTC (permalink / raw)
To: Oliver Steffen
Cc: qemu-devel, Richard Henderson, Paolo Bonzini, Marcelo Tosatti,
Ani Sinha, Stefano Garzarella, Luigi Leonardi, Zhao Liu,
Joerg Roedel, Gerd Hoffmann, kvm, Eduardo Habkost,
Michael S. Tsirkin, Marcel Apfelbaum
On Fri, 9 Jan 2026 15:34:07 +0100
Oliver Steffen <osteffen@redhat.com> wrote:
> When launching using an IGVM file, supply a copy of the MADT (part of the ACPI
> tables) via an IGVM parameter (IGVM_VHY_MADT) to the guest, in addition to the
> regular fw_cfg mechanism.
I've had some questions wrt using MADT in previous version,
and possible ways to avoid issues.
not of those where addressed though.
So questions stay the same, see:
https://patchew.org/QEMU/20251211103136.1578463-1-osteffen@redhat.com/#20251219140933.7b102fc5@imammedo
>
> The IGVM parameter can be consumed by Coconut SVSM [1], instead of relying on
> the fw_cfg interface, which has caused problems before due to unexpected access
> [2,3]. Using IGVM parameters is the default way for Coconut SVSM; switching
> over would allow removing specialized code paths for QEMU in Coconut.
>
> In any case OVMF, which runs after SVSM has already been initialized, will
> continue reading all ACPI tables via fw_cfg and provide fixed up ACPI data to
> the OS as before.
>
> This series makes ACPI table building more generic by making the BIOS linker
> optional. This allows the MADT to be generated outside of the ACPI build
> context. A new function (acpi_build_madt_standalone()) is added for that. With
> that, the IGVM MADT parameter field can be filled with the MADT data during
> processing of the IGVM file.
>
> Generating the MADT twice (IGVM processing and ACPI table building) seems
> acceptable, since there is no infrastructure to obtain the MADT out of the ACPI
> table memory area during IGVM processing.
>
> [1] https://github.com/coconut-svsm/svsm/pull/858
> [2] https://gitlab.com/qemu-project/qemu/-/issues/2882
> [3] https://github.com/coconut-svsm/svsm/issues/646
>
> v3:
> - Pass the machine state into IGVM file processing context instead of MADT data
> - Generate MADT from inside the IGVM backend
> - Refactor: Extract common code for finding IGVM parameter from IGVM parameter handlers
> - Add NULL pointer check for igvm_get_buffer()
>
> v2:
> - Provide more context in the message of the main commit
> - Document the madt parameter of IgvmCfgClass::process()
> - Document why no MADT data is provided the process call in sev.c
>
> Based-on: <20251118122133.1695767-1-kraxel@redhat.com>
> Signed-off-by: Oliver Steffen <osteffen@redhat.com>
>
> Oliver Steffen (6):
> hw/acpi: Make BIOS linker optional
> hw/acpi: Add standalone function to build MADT
> igvm: Add missing NULL check
> igvm: Add common function for finding parameter entries
> igvm: Pass machine state to IGVM file processing
> igvm: Fill MADT IGVM parameter field
>
> backends/igvm-cfg.c | 2 +-
> backends/igvm.c | 169 +++++++++++++++++++++++++-------------
> hw/acpi/aml-build.c | 7 +-
> hw/i386/acpi-build.c | 8 ++
> hw/i386/acpi-build.h | 2 +
> include/system/igvm-cfg.h | 3 +-
> include/system/igvm.h | 3 +-
> target/i386/sev.c | 2 +-
> 8 files changed, 132 insertions(+), 64 deletions(-)
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 3/6] igvm: Add missing NULL check
2026-01-09 14:34 ` [PATCH v3 3/6] igvm: Add missing NULL check Oliver Steffen
2026-01-09 17:37 ` Luigi Leonardi
@ 2026-01-13 7:21 ` Ani Sinha
2026-01-13 9:04 ` Oliver Steffen
1 sibling, 1 reply; 19+ messages in thread
From: Ani Sinha @ 2026-01-13 7:21 UTC (permalink / raw)
To: Oliver Steffen
Cc: qemu-devel, Richard Henderson, Igor Mammedov, Paolo Bonzini,
Marcelo Tosatti, Stefano Garzarella, Luigi Leonardi, Zhao Liu,
Joerg Roedel, Gerd Hoffmann, kvm, Eduardo Habkost,
Michael Tsirkin, Marcel Apfelbaum
> On 9 Jan 2026, at 8:04 PM, Oliver Steffen <osteffen@redhat.com> wrote:
>
> Check for NULL pointer returned from igvm_get_buffer().
> Documentation for that function calls for that unconditionally.
>
> Signed-off-by: Oliver Steffen <osteffen@redhat.com>
> ---
> backends/igvm.c | 13 ++++++++++---
> 1 file changed, 10 insertions(+), 3 deletions(-)
>
> diff --git a/backends/igvm.c b/backends/igvm.c
> index a350c890cc..dc1fd026cb 100644
> --- a/backends/igvm.c
> +++ b/backends/igvm.c
> @@ -170,9 +170,16 @@ static int qigvm_handler(QIgvm *ctx, uint32_t type, Error **errp)
> (int)header_handle);
> return -1;
> }
> - header_data = igvm_get_buffer(ctx->file, header_handle) +
> - sizeof(IGVM_VHS_VARIABLE_HEADER);
> - result = handlers[handler].handler(ctx, header_data, errp);
> + header_data = igvm_get_buffer(ctx->file, header_handle);
> + if (header_data == NULL) {
> + error_setg(
> + errp,
> + "IGVM: Failed to get directive header data (code: %d)",
> + (int)header_handle);
> + result = -1;
I would just return -1 here and remove the else {} clause below. It makes it slightly easier to follow the code.
> + } else {
> + result = handlers[handler].handler(ctx, header_data + sizeof(IGVM_VHS_VARIABLE_HEADER), errp);
> + }
> igvm_free_buffer(ctx->file, header_handle);
> return result;
> }
> --
> 2.52.0
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 3/6] igvm: Add missing NULL check
2026-01-13 7:21 ` Ani Sinha
@ 2026-01-13 9:04 ` Oliver Steffen
0 siblings, 0 replies; 19+ messages in thread
From: Oliver Steffen @ 2026-01-13 9:04 UTC (permalink / raw)
To: Ani Sinha
Cc: qemu-devel, Richard Henderson, Igor Mammedov, Paolo Bonzini,
Marcelo Tosatti, Stefano Garzarella, Luigi Leonardi, Zhao Liu,
Joerg Roedel, Gerd Hoffmann, kvm, Eduardo Habkost,
Michael Tsirkin, Marcel Apfelbaum
On Tue, Jan 13, 2026 at 8:21 AM Ani Sinha <anisinha@redhat.com> wrote:
>
>
>
> > On 9 Jan 2026, at 8:04 PM, Oliver Steffen <osteffen@redhat.com> wrote:
> >
> > Check for NULL pointer returned from igvm_get_buffer().
> > Documentation for that function calls for that unconditionally.
> >
> > Signed-off-by: Oliver Steffen <osteffen@redhat.com>
> > ---
> > backends/igvm.c | 13 ++++++++++---
> > 1 file changed, 10 insertions(+), 3 deletions(-)
> >
> > diff --git a/backends/igvm.c b/backends/igvm.c
> > index a350c890cc..dc1fd026cb 100644
> > --- a/backends/igvm.c
> > +++ b/backends/igvm.c
> > @@ -170,9 +170,16 @@ static int qigvm_handler(QIgvm *ctx, uint32_t type, Error **errp)
> > (int)header_handle);
> > return -1;
> > }
> > - header_data = igvm_get_buffer(ctx->file, header_handle) +
> > - sizeof(IGVM_VHS_VARIABLE_HEADER);
> > - result = handlers[handler].handler(ctx, header_data, errp);
> > + header_data = igvm_get_buffer(ctx->file, header_handle);
> > + if (header_data == NULL) {
> > + error_setg(
> > + errp,
> > + "IGVM: Failed to get directive header data (code: %d)",
> > + (int)header_handle);
> > + result = -1;
>
> I would just return -1 here and remove the else {} clause below. It makes it slightly easier to follow the code.
Sure, can do.
But are we ok with publicating
igvm_free_buffer(ctx->file, header_handle);
which we need before returning?
>
> > + } else {
> > + result = handlers[handler].handler(ctx, header_data + sizeof(IGVM_VHS_VARIABLE_HEADER), errp);
> > + }
> > igvm_free_buffer(ctx->file, header_handle);
> > return result;
> > }
> > --
> > 2.52.0
> >
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 3/6] igvm: Add missing NULL check
2026-01-12 9:57 ` Gerd Hoffmann
@ 2026-01-13 9:36 ` Oliver Steffen
0 siblings, 0 replies; 19+ messages in thread
From: Oliver Steffen @ 2026-01-13 9:36 UTC (permalink / raw)
To: Gerd Hoffmann
Cc: Luigi Leonardi, qemu-devel, Richard Henderson, Igor Mammedov,
Paolo Bonzini, Marcelo Tosatti, Ani Sinha, Stefano Garzarella,
Zhao Liu, Joerg Roedel, kvm, Eduardo Habkost, Michael S. Tsirkin,
Marcel Apfelbaum
On Mon, Jan 12, 2026 at 10:57 AM Gerd Hoffmann <kraxel@redhat.com> wrote:
>
> Hi,
>
> > > > IMHO this should be sent a separate patch
> > >
> > > Huh? It /is/ a separate patch ...
> >
> > Sorry, I meant outside of this series.
>
> Not needed, separate patch is good enough, even though sending a
> separate 'fixes' series might make sense in some cases (split an
> already long patch series, or during freeze where only fixes are
> allowed before the next release).
Since there are more identical cases of missing NULL checks here,
I'd take this patch out of this series and handle all instances together
in a new patch/series.
Thanks
- Olvier
>
> take care,
> Gerd
>
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-01-13 9:36 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-09 14:34 [PATCH v3 0/6] igvm: Supply MADT via IGVM parameter Oliver Steffen
2026-01-09 14:34 ` [PATCH v3 1/6] hw/acpi: Make BIOS linker optional Oliver Steffen
2026-01-12 9:47 ` Gerd Hoffmann
2026-01-09 14:34 ` [PATCH v3 2/6] hw/acpi: Add standalone function to build MADT Oliver Steffen
2026-01-09 14:34 ` [PATCH v3 3/6] igvm: Add missing NULL check Oliver Steffen
2026-01-09 17:37 ` Luigi Leonardi
2026-01-12 9:41 ` Gerd Hoffmann
2026-01-12 9:49 ` Luigi Leonardi
2026-01-12 9:57 ` Gerd Hoffmann
2026-01-13 9:36 ` Oliver Steffen
2026-01-13 7:21 ` Ani Sinha
2026-01-13 9:04 ` Oliver Steffen
2026-01-09 14:34 ` [PATCH v3 4/6] igvm: Add common function for finding parameter entries Oliver Steffen
2026-01-12 9:43 ` Gerd Hoffmann
2026-01-09 14:34 ` [PATCH v3 5/6] igvm: Pass machine state to IGVM file processing Oliver Steffen
2026-01-12 9:09 ` Luigi Leonardi
2026-01-09 14:34 ` [PATCH v3 6/6] igvm: Fill MADT IGVM parameter field Oliver Steffen
2026-01-12 9:57 ` Luigi Leonardi
2026-01-12 12:34 ` [PATCH v3 0/6] igvm: Supply MADT via IGVM parameter Igor Mammedov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox