Add and wire up qigvm_x86_get_mem_map_entry function which converts the
e820 table into an igvm memory map parameter. This makes igvm files for
the native (non-confidential) platform with memory map parameter work.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
include/system/igvm.h | 5 +++++
backends/igvm.c | 18 ++++++++++++----
stubs/igvm.c | 21 +++++++++++++++++++
target/i386/igvm.c | 46 +++++++++++++++++++++++++++++++++++++++++
stubs/meson.build | 1 +
target/i386/meson.build | 3 +++
6 files changed, 90 insertions(+), 4 deletions(-)
create mode 100644 stubs/igvm.c
create mode 100644 target/i386/igvm.c
diff --git a/include/system/igvm.h b/include/system/igvm.h
index a4abab043a1f..3f72a40b8897 100644
--- a/include/system/igvm.h
+++ b/include/system/igvm.h
@@ -19,4 +19,9 @@
int qigvm_process_file(IgvmCfg *igvm, ConfidentialGuestSupport *cgs,
bool onlyVpContext, Error **errp);
+/* x86 native */
+int qigvm_x86_get_mem_map_entry(int index,
+ ConfidentialGuestMemoryMapEntry *entry,
+ Error **errp);
+
#endif
diff --git a/backends/igvm.c b/backends/igvm.c
index 723d45b755a0..e949c81abb9a 100644
--- a/backends/igvm.c
+++ b/backends/igvm.c
@@ -12,6 +12,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
+#include "qemu/target-info-qapi.h"
#include "system/igvm.h"
#include "system/memory.h"
#include "system/address-spaces.h"
@@ -543,6 +544,8 @@ static int qigvm_directive_memory_map(QIgvm *ctx, const uint8_t *header_data,
Error **errp)
{
const IGVM_VHS_PARAMETER *param = (const IGVM_VHS_PARAMETER *)header_data;
+ int (*get_mem_map_entry)(int index, ConfidentialGuestMemoryMapEntry *entry,
+ Error **errp) = NULL;
QIgvmParameterData *param_entry;
int max_entry_count;
int entry = 0;
@@ -550,7 +553,15 @@ static int qigvm_directive_memory_map(QIgvm *ctx, const uint8_t *header_data,
ConfidentialGuestMemoryMapEntry cgmm_entry;
int retval = 0;
- if (!ctx->cgs) {
+ if (ctx->cgs && ctx->cgsc->get_mem_map_entry) {
+ get_mem_map_entry = ctx->cgsc->get_mem_map_entry;
+ }
+
+ if (!get_mem_map_entry && target_arch() == SYS_EMU_TARGET_X86_64) {
+ get_mem_map_entry = qigvm_x86_get_mem_map_entry;
+ }
+
+ if (!get_mem_map_entry) {
error_setg(errp,
"IGVM file contains a memory map but this is not supported "
"by the current system.");
@@ -565,7 +576,7 @@ static int qigvm_directive_memory_map(QIgvm *ctx, const uint8_t *header_data,
param_entry->size / sizeof(IGVM_VHS_MEMORY_MAP_ENTRY);
mm_entry = (IGVM_VHS_MEMORY_MAP_ENTRY *)param_entry->data;
- retval = ctx->cgsc->get_mem_map_entry(entry, &cgmm_entry, errp);
+ retval = get_mem_map_entry(entry, &cgmm_entry, errp);
while (retval == 0) {
if (entry > max_entry_count) {
error_setg(
@@ -598,8 +609,7 @@ static int qigvm_directive_memory_map(QIgvm *ctx, const uint8_t *header_data,
IGVM_MEMORY_MAP_ENTRY_TYPE_PLATFORM_RESERVED;
break;
}
- retval =
- ctx->cgsc->get_mem_map_entry(++entry, &cgmm_entry, errp);
+ retval = get_mem_map_entry(++entry, &cgmm_entry, errp);
}
if (retval < 0) {
return retval;
diff --git a/stubs/igvm.c b/stubs/igvm.c
new file mode 100644
index 000000000000..c32058eb2a6e
--- /dev/null
+++ b/stubs/igvm.c
@@ -0,0 +1,21 @@
+/*
+ * QEMU IGVM, stubs
+ *
+ * Copyright (C) 2026 Red Hat
+ *
+ * Authors:
+ * Gerd Hoffmann <kraxel@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+
+#include "system/igvm.h"
+
+int qigvm_x86_get_mem_map_entry(int index,
+ ConfidentialGuestMemoryMapEntry *entry,
+ Error **errp)
+{
+ return -1;
+}
diff --git a/target/i386/igvm.c b/target/i386/igvm.c
new file mode 100644
index 000000000000..2ed6cd052c79
--- /dev/null
+++ b/target/i386/igvm.c
@@ -0,0 +1,46 @@
+/*
+ * QEMU IGVM, support for native x86 guests
+ *
+ * Copyright (C) 2026 Red Hat
+ *
+ * Authors:
+ * Gerd Hoffmann <kraxel@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/i386/e820_memory_layout.h"
+#include "system/igvm.h"
+
+/*
+ * convert e820 table into igvm memory map
+ */
+int qigvm_x86_get_mem_map_entry(int index,
+ ConfidentialGuestMemoryMapEntry *entry,
+ Error **errp)
+{
+ struct e820_entry *table;
+ int num_entries;
+
+ num_entries = e820_get_table(&table);
+ if ((index < 0) || (index >= num_entries)) {
+ return 1;
+ }
+ entry->gpa = table[index].address;
+ entry->size = table[index].length;
+ switch (table[index].type) {
+ case E820_RAM:
+ entry->type = CGS_MEM_RAM;
+ break;
+ case E820_RESERVED:
+ entry->type = CGS_MEM_RESERVED;
+ break;
+ default:
+ /* should not happen */
+ error_setg(errp, "unknown e820 type");
+ return -1;
+ }
+ return 0;
+}
diff --git a/stubs/meson.build b/stubs/meson.build
index 5d577467bfdd..27be2dec9f9e 100644
--- a/stubs/meson.build
+++ b/stubs/meson.build
@@ -74,6 +74,7 @@ if have_system
stub_ss.add(files('dump.c'))
stub_ss.add(files('cmos.c'))
stub_ss.add(files('fw_cfg.c'))
+ stub_ss.add(files('igvm.c'))
stub_ss.add(files('target-get-monitor-def.c'))
stub_ss.add(files('target-monitor-defs.c'))
stub_ss.add(files('win32-kbd-hook.c'))
diff --git a/target/i386/meson.build b/target/i386/meson.build
index 89ba4912aaeb..d385eafdf7e1 100644
--- a/target/i386/meson.build
+++ b/target/i386/meson.build
@@ -26,6 +26,9 @@ i386_system_ss.add(files(
))
i386_system_ss.add(when: 'CONFIG_SEV', if_true: files('sev.c'),
if_false: files('sev-system-stub.c'))
+if igvm.found()
+ i386_system_ss.add(files('igvm.c'))
+endif
i386_user_ss = ss.source_set()
--
2.51.0
On Wed, Oct 15, 2025 at 01:23:39PM +0200, Gerd Hoffmann wrote:
>Add and wire up qigvm_x86_get_mem_map_entry function which converts the
>e820 table into an igvm memory map parameter. This makes igvm files for
>the native (non-confidential) platform with memory map parameter work.
>
>Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
>---
> include/system/igvm.h | 5 +++++
> backends/igvm.c | 18 ++++++++++++----
> stubs/igvm.c | 21 +++++++++++++++++++
> target/i386/igvm.c | 46 +++++++++++++++++++++++++++++++++++++++++
> stubs/meson.build | 1 +
> target/i386/meson.build | 3 +++
> 6 files changed, 90 insertions(+), 4 deletions(-)
> create mode 100644 stubs/igvm.c
> create mode 100644 target/i386/igvm.c
>
>diff --git a/include/system/igvm.h b/include/system/igvm.h
>index a4abab043a1f..3f72a40b8897 100644
>--- a/include/system/igvm.h
>+++ b/include/system/igvm.h
>@@ -19,4 +19,9 @@
> int qigvm_process_file(IgvmCfg *igvm, ConfidentialGuestSupport *cgs,
> bool onlyVpContext, Error **errp);
>
>+/* x86 native */
>+int qigvm_x86_get_mem_map_entry(int index,
>+ ConfidentialGuestMemoryMapEntry *entry,
>+ Error **errp);
>+
> #endif
>diff --git a/backends/igvm.c b/backends/igvm.c
>index 723d45b755a0..e949c81abb9a 100644
>--- a/backends/igvm.c
>+++ b/backends/igvm.c
>@@ -12,6 +12,7 @@
> #include "qemu/osdep.h"
>
> #include "qapi/error.h"
>+#include "qemu/target-info-qapi.h"
> #include "system/igvm.h"
> #include "system/memory.h"
> #include "system/address-spaces.h"
>@@ -543,6 +544,8 @@ static int qigvm_directive_memory_map(QIgvm *ctx, const uint8_t *header_data,
> Error **errp)
> {
> const IGVM_VHS_PARAMETER *param = (const IGVM_VHS_PARAMETER *)header_data;
>+ int (*get_mem_map_entry)(int index, ConfidentialGuestMemoryMapEntry *entry,
>+ Error **errp) = NULL;
> QIgvmParameterData *param_entry;
> int max_entry_count;
> int entry = 0;
>@@ -550,7 +553,15 @@ static int qigvm_directive_memory_map(QIgvm *ctx, const uint8_t *header_data,
> ConfidentialGuestMemoryMapEntry cgmm_entry;
> int retval = 0;
>
>- if (!ctx->cgs) {
>+ if (ctx->cgs && ctx->cgsc->get_mem_map_entry) {
>+ get_mem_map_entry = ctx->cgsc->get_mem_map_entry;
>+ }
>+
>+ if (!get_mem_map_entry && target_arch() == SYS_EMU_TARGET_X86_64) {
nit: we can avoid to re-evaluate `get_mem_map_entry` again, so we can
do: (not a strong opinion, just more readable IMHO)
else if (target_arch() == SYS_EMU_TARGET_X86_64) {
>+ get_mem_map_entry = qigvm_x86_get_mem_map_entry;
>+ }
>+
>+ if (!get_mem_map_entry) {
> error_setg(errp,
> "IGVM file contains a memory map but this is not supported "
> "by the current system.");
>@@ -565,7 +576,7 @@ static int qigvm_directive_memory_map(QIgvm *ctx, const uint8_t *header_data,
> param_entry->size / sizeof(IGVM_VHS_MEMORY_MAP_ENTRY);
> mm_entry = (IGVM_VHS_MEMORY_MAP_ENTRY *)param_entry->data;
>
>- retval = ctx->cgsc->get_mem_map_entry(entry, &cgmm_entry, errp);
>+ retval = get_mem_map_entry(entry, &cgmm_entry, errp);
> while (retval == 0) {
> if (entry > max_entry_count) {
pre-existing, but should this be `entry >= max_entry_count` ?
BTW this should be eventually fixed in another patch, so for this patch:
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
> error_setg(
>@@ -598,8 +609,7 @@ static int qigvm_directive_memory_map(QIgvm *ctx, const uint8_t *header_data,
> IGVM_MEMORY_MAP_ENTRY_TYPE_PLATFORM_RESERVED;
> break;
> }
>- retval =
>- ctx->cgsc->get_mem_map_entry(++entry, &cgmm_entry, errp);
>+ retval = get_mem_map_entry(++entry, &cgmm_entry, errp);
> }
> if (retval < 0) {
> return retval;
>diff --git a/stubs/igvm.c b/stubs/igvm.c
>new file mode 100644
>index 000000000000..c32058eb2a6e
>--- /dev/null
>+++ b/stubs/igvm.c
>@@ -0,0 +1,21 @@
>+/*
>+ * QEMU IGVM, stubs
>+ *
>+ * Copyright (C) 2026 Red Hat
>+ *
>+ * Authors:
>+ * Gerd Hoffmann <kraxel@redhat.com>
>+ *
>+ * SPDX-License-Identifier: GPL-2.0-or-later
>+ */
>+
>+#include "qemu/osdep.h"
>+
>+#include "system/igvm.h"
>+
>+int qigvm_x86_get_mem_map_entry(int index,
>+ ConfidentialGuestMemoryMapEntry *entry,
>+ Error **errp)
>+{
>+ return -1;
>+}
>diff --git a/target/i386/igvm.c b/target/i386/igvm.c
>new file mode 100644
>index 000000000000..2ed6cd052c79
>--- /dev/null
>+++ b/target/i386/igvm.c
>@@ -0,0 +1,46 @@
>+/*
>+ * QEMU IGVM, support for native x86 guests
>+ *
>+ * Copyright (C) 2026 Red Hat
>+ *
>+ * Authors:
>+ * Gerd Hoffmann <kraxel@redhat.com>
>+ *
>+ * SPDX-License-Identifier: GPL-2.0-or-later
>+ */
>+
>+#include "qemu/osdep.h"
>+
>+#include "hw/i386/e820_memory_layout.h"
>+#include "system/igvm.h"
>+
>+/*
>+ * convert e820 table into igvm memory map
>+ */
>+int qigvm_x86_get_mem_map_entry(int index,
>+ ConfidentialGuestMemoryMapEntry *entry,
>+ Error **errp)
>+{
>+ struct e820_entry *table;
>+ int num_entries;
>+
>+ num_entries = e820_get_table(&table);
>+ if ((index < 0) || (index >= num_entries)) {
>+ return 1;
>+ }
>+ entry->gpa = table[index].address;
>+ entry->size = table[index].length;
>+ switch (table[index].type) {
>+ case E820_RAM:
>+ entry->type = CGS_MEM_RAM;
>+ break;
>+ case E820_RESERVED:
>+ entry->type = CGS_MEM_RESERVED;
>+ break;
>+ default:
>+ /* should not happen */
>+ error_setg(errp, "unknown e820 type");
>+ return -1;
>+ }
>+ return 0;
>+}
>diff --git a/stubs/meson.build b/stubs/meson.build
>index 5d577467bfdd..27be2dec9f9e 100644
>--- a/stubs/meson.build
>+++ b/stubs/meson.build
>@@ -74,6 +74,7 @@ if have_system
> stub_ss.add(files('dump.c'))
> stub_ss.add(files('cmos.c'))
> stub_ss.add(files('fw_cfg.c'))
>+ stub_ss.add(files('igvm.c'))
> stub_ss.add(files('target-get-monitor-def.c'))
> stub_ss.add(files('target-monitor-defs.c'))
> stub_ss.add(files('win32-kbd-hook.c'))
>diff --git a/target/i386/meson.build b/target/i386/meson.build
>index 89ba4912aaeb..d385eafdf7e1 100644
>--- a/target/i386/meson.build
>+++ b/target/i386/meson.build
>@@ -26,6 +26,9 @@ i386_system_ss.add(files(
> ))
> i386_system_ss.add(when: 'CONFIG_SEV', if_true: files('sev.c'),
> if_false: files('sev-system-stub.c'))
>+if igvm.found()
>+ i386_system_ss.add(files('igvm.c'))
>+endif
>
> i386_user_ss = ss.source_set()
>
>--
>2.51.0
>
© 2016 - 2025 Red Hat, Inc.