igvm: add device tree parameter support

Coconut SVSM, with the upcoming device tree support [1], will use
the IGVM device tree parameter to discover virtio-mmio and ISA serial
devices instead of relying on the fw_cfg interface, which is
QEMU-specific.

The device tree is packed before copying into the IGVM parameter area
to reduce its size, since IGVM files can define tighter memory
constraints for parameter areas. Packing is done in the generic IGVM
backend rather than in per-architecture device tree setup code, so
that each architecture does not need to handle it individually.

[1] https://github.com/coconut-svsm/svsm/pull/1006

Signed-off-by: Luigi Leonardi <leonardi@redhat.com>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Message-ID: <20260626-microvm_device_tree-v6-3-9cd13cf057e2@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Luigi Leonardi
2026-06-26 12:04:03 +02:00
committed by Gerd Hoffmann
parent 85db68ba49
commit 1c4bd8f13c
2 changed files with 55 additions and 1 deletions

View File

@@ -26,6 +26,10 @@
#include <igvm/igvm.h>
#include <igvm/igvm_defs.h>
#ifdef CONFIG_FDT
#include <libfdt.h>
#endif
#ifndef IGVM_VHT_OPTIONAL_BIT
#define IGVM_VHT_OPTIONAL_BIT (1U << 31)
#endif
@@ -121,6 +125,10 @@ 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);
#ifdef CONFIG_FDT
static int qigvm_directive_device_tree(QIgvm *ctx, const uint8_t *header_data,
Error **errp);
#endif
struct QIGVMHandler {
IgvmVariableHeaderType type;
@@ -151,6 +159,10 @@ static struct QIGVMHandler handlers[] = {
qigvm_initialization_guest_policy },
{ IGVM_VHT_MADT, IGVM_HEADER_SECTION_DIRECTIVE,
qigvm_directive_madt },
#ifdef CONFIG_FDT
{ IGVM_VHT_DEVICE_TREE, IGVM_HEADER_SECTION_DIRECTIVE,
qigvm_directive_device_tree },
#endif
};
static int qigvm_handler(QIgvm *ctx, IgvmVariableHeaderType raw_type,
@@ -786,6 +798,48 @@ static int qigvm_directive_snp_id_block(QIgvm *ctx, const uint8_t *header_data,
return 0;
}
#ifdef CONFIG_FDT
static int qigvm_directive_device_tree(QIgvm *ctx, const uint8_t *header_data,
Error **errp)
{
const IGVM_VHS_PARAMETER *param = (const IGVM_VHS_PARAMETER *)header_data;
g_autofree void *fdt_packed = NULL;
QIgvmParameterData *param_entry;
uint32_t fdt_size;
param_entry = qigvm_find_param_entry(ctx,
param->parameter_area_index, errp);
if (param_entry == NULL) {
return -1;
}
if (ctx->machine_state->fdt == NULL) {
error_setg(errp, "IGVM: device tree not available");
return -1;
}
fdt_size = fdt_totalsize(ctx->machine_state->fdt);
fdt_packed = g_memdup2(ctx->machine_state->fdt, fdt_size);
if (fdt_pack(fdt_packed)) {
error_setg(errp, "IGVM: failed to pack device tree");
return -1;
}
fdt_size = fdt_totalsize(fdt_packed);
if (fdt_size > param_entry->size) {
error_setg(errp,
"IGVM: device tree size exceeds parameter area"
" defined in IGVM file");
return -1;
}
memcpy(param_entry->data, fdt_packed, fdt_size);
return 0;
}
#endif
static int qigvm_initialization_guest_policy(QIgvm *ctx,
const uint8_t *header_data, Error **errp)
{

View File

@@ -35,7 +35,7 @@ endif
system_ss.add(when: gio, if_true: files('dbus-vmstate.c'))
system_ss.add(when: 'CONFIG_SGX', if_true: files('hostmem-epc.c'))
system_ss.add(when: igvm, if_true: [files('igvm-cfg.c', 'igvm.c')])
system_ss.add(when: igvm, if_true: [files('igvm-cfg.c', 'igvm.c'), fdt])
system_ss.add(when: 'CONFIG_SPDM_SOCKET', if_true: files('spdm-socket.c'))