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 <[email protected]> --- This device tree will be consumed by Coconut SVSM with the upcoming device tree support [1]. This will allow SVSM to run on a normal CPU (not AMD SEV-SNP) and execute all its tests using upstream QEMU. Eventually edk2 will also be able to consume DT via IGVM, but the work has not started yet. [1] https://github.com/coconut-svsm/svsm/pull/1006 To: [email protected] Cc: Michael S. Tsirkin <[email protected]> Cc: Paolo Bonzini <[email protected]> Cc: Richard Henderson <[email protected]> Cc: Gerd Hoffmann <[email protected]> Cc: Stefano Garzarella <[email protected]> Cc: Ani Sinha <[email protected]> Cc: Zhao Liu <[email protected]> Cc: Oliver Steffen <[email protected]> --- Changes in v4: - Using g_memdup2 [Stefano] - madt directive is now protected by CONFIG_FDT [Stefano] - Link to v3: https://lore.kernel.org/qemu-devel/[email protected] Changes in v3: - Device tree is packed in igvm core code. [Gerd] - Dropped microvm patch. - Link to v2: https://lore.kernel.org/qemu-devel/[email protected] Changes in v2: - First patch introduced a shadowed variable, fixed. - When parameter area is not found return -1. - Moved `qigvm_directive_device_tree` to backends/igvm.c - Link to v1: https://lore.kernel.org/qemu-devel/[email protected] --- Error handling on qigvm_find_param_entry will change once [2] is merged. I am already using the new approach here. [2] https://lore.kernel.org/qemu-devel/[email protected] --- backends/igvm.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/backends/igvm.c b/backends/igvm.c index c347d0c17e..db54f24f7b 100644 --- a/backends/igvm.c +++ b/backends/igvm.c @@ -26,6 +26,9 @@ #include <igvm/igvm.h> #include <igvm/igvm_defs.h> +#ifdef CONFIG_FDT +#include <libfdt.h> +#endif /* * Some directives are specific to particular confidential computing platforms. @@ -100,6 +103,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 { uint32_t type; @@ -130,6 +137,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, uint32_t type, Error **errp) @@ -752,6 +763,49 @@ 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); + if (param_entry == NULL) { + error_setg(errp, "IGVM: parameter area index %u not found", + param->parameter_area_index); + 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) { --- base-commit: cc329c491768b2d91eb0b0984f3baa0bf805776d change-id: 20260608-microvm_device_tree-0263c3b1be86 Best regards, -- Luigi Leonardi <[email protected]>
