diff options
Diffstat (limited to 'backends/igvm.c')
| -rw-r--r-- | backends/igvm.c | 80 |
1 files changed, 70 insertions, 10 deletions
diff --git a/backends/igvm.c b/backends/igvm.c index 3f4b97a5d4..80e87fe602 100644 --- a/backends/igvm.c +++ b/backends/igvm.c @@ -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 @@ -81,7 +85,8 @@ struct QEMU_PACKED sev_id_authentication { #define IGVM_SEV_ID_BLOCK_VERSION 1 QIgvmParameterData* -qigvm_find_param_entry(QIgvm *igvm, uint32_t parameter_area_index) +qigvm_find_param_entry(QIgvm *igvm, uint32_t parameter_area_index, + Error **errp) { QIgvmParameterData *param_entry; QTAILQ_FOREACH(param_entry, &igvm->parameter_data, next) @@ -90,7 +95,8 @@ qigvm_find_param_entry(QIgvm *igvm, uint32_t parameter_area_index) return param_entry; } } - warn_report("IGVM: No parameter area for index %u", parameter_area_index); + error_setg(errp, "IGVM: parameter area index %u not found", + parameter_area_index); return NULL; } @@ -119,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; @@ -149,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, @@ -528,9 +542,10 @@ static int qigvm_directive_parameter_insert(QIgvm *ctx, return 0; } - param_entry = qigvm_find_param_entry(ctx, param->parameter_area_index); + param_entry = qigvm_find_param_entry(ctx, + param->parameter_area_index, errp); if (param_entry == NULL) { - return 0; + return -1; } region = qigvm_prepare_memory(ctx, param->gpa, param_entry->size, @@ -601,9 +616,10 @@ static int qigvm_directive_memory_map(QIgvm *ctx, const uint8_t *header_data, } /* Find the parameter area that should hold the memory map */ - param_entry = qigvm_find_param_entry(ctx, param->parameter_area_index); + param_entry = qigvm_find_param_entry(ctx, + param->parameter_area_index, errp); if (param_entry == NULL) { - return 0; + return -1; } max_entry_count = param_entry->size / sizeof(IGVM_VHS_MEMORY_MAP_ENTRY); @@ -660,9 +676,10 @@ static int qigvm_directive_vp_count(QIgvm *ctx, const uint8_t *header_data, uint32_t *vp_count; CPUState *cpu; - param_entry = qigvm_find_param_entry(ctx, param->parameter_area_index); + param_entry = qigvm_find_param_entry(ctx, + param->parameter_area_index, errp); if (param_entry == NULL) { - return 0; + return -1; } vp_count = (uint32_t *)(param_entry->data + param->byte_offset); @@ -683,9 +700,10 @@ static int qigvm_directive_environment_info(QIgvm *ctx, QIgvmParameterData *param_entry; IgvmEnvironmentInfo *environmental_state; - param_entry = qigvm_find_param_entry(ctx, param->parameter_area_index); + param_entry = qigvm_find_param_entry(ctx, + param->parameter_area_index, errp); if (param_entry == NULL) { - return 0; + return -1; } environmental_state = @@ -780,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) { |
