summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/igvm.c80
-rw-r--r--backends/meson.build7
-rw-r--r--include/system/igvm-internal.h3
-rw-r--r--target/i386/igvm.c5
4 files changed, 77 insertions, 18 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)
{
diff --git a/backends/meson.build b/backends/meson.build
index 60021f45d1..8792c58c36 100644
--- a/backends/meson.build
+++ b/backends/meson.build
@@ -34,11 +34,8 @@ if have_vhost_user_crypto
endif
system_ss.add(when: gio, if_true: files('dbus-vmstate.c'))
system_ss.add(when: 'CONFIG_SGX', if_true: files('hostmem-epc.c'))
-if igvm.found()
- system_ss.add(igvm)
- system_ss.add(files('igvm-cfg.c'), igvm)
- system_ss.add(files('igvm.c'), igvm)
-endif
+
+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'))
diff --git a/include/system/igvm-internal.h b/include/system/igvm-internal.h
index 7f131c4d03..7eb3792ed8 100644
--- a/include/system/igvm-internal.h
+++ b/include/system/igvm-internal.h
@@ -72,6 +72,7 @@ struct QIgvm {
IgvmHandle qigvm_file_init(char *filename, Error **errp);
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);
#endif
diff --git a/target/i386/igvm.c b/target/i386/igvm.c
index f41b498b89..ad9bf87761 100644
--- a/target/i386/igvm.c
+++ b/target/i386/igvm.c
@@ -191,9 +191,10 @@ int qigvm_directive_madt(QIgvm *ctx, const uint8_t *header_data, Error **errp)
int result = 0;
/* Find the parameter area that should hold the MADT data */
- 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;
}
GArray *madt = acpi_build_madt_standalone(ctx->machine_state);