summaryrefslogtreecommitdiff
path: root/backends/igvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'backends/igvm.c')
-rw-r--r--backends/igvm.c80
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)
{