feat(interrupts): support for parsing interrupt ..
properties node from manifest and populating the interrupt descriptor
structure per VM.
Change-Id: I17f6dcd5d4af6eb37f1bb64770052fd6e8f23542
Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
diff --git a/src/load.c b/src/load.c
index 0db27c5..14194ec 100644
--- a/src/load.c
+++ b/src/load.c
@@ -23,6 +23,7 @@
#include "hf/memiter.h"
#include "hf/mm.h"
#include "hf/plat/console.h"
+#include "hf/plat/interrupts.h"
#include "hf/plat/iommu.h"
#include "hf/static_assert.h"
#include "hf/std.h"
@@ -125,6 +126,25 @@
return true;
}
+static void infer_interrupt(struct interrupt interrupt,
+ struct interrupt_descriptor *int_desc)
+{
+ uint32_t attr = interrupt.attributes;
+
+ interrupt_desc_set_id(int_desc, interrupt.id);
+ interrupt_desc_set_priority(int_desc,
+ (attr >> INT_DESC_PRIORITY_SHIFT) & 0xff);
+
+ /* Refer to the comments in interrupt_descriptor struct definition. */
+ interrupt_desc_set_type_config_sec_state(
+ int_desc,
+ (((attr >> INT_DESC_TYPE_SHIFT) & 0x3) << 2) |
+ (((attr >> INT_DESC_CONFIG_SHIFT) & 0x1) << 1) |
+ ((attr >> INT_DESC_SEC_STATE_SHIFT) & 0x1));
+
+ interrupt_desc_set_valid(int_desc, true);
+}
+
/**
* Performs VM loading activities that are common between the primary and
* secondaries.
@@ -134,9 +154,33 @@
const struct manifest_vm *manifest_vm,
struct mpool *ppool)
{
+ struct device_region dev_region;
+ struct interrupt interrupt;
+ uint32_t k = 0;
+
vm_locked.vm->smc_whitelist = manifest_vm->smc_whitelist;
vm_locked.vm->uuid = manifest_vm->partition.uuid;
+ /* Populate the interrupt descriptor for current VM. */
+ for (uint8_t i = 0; i < SP_MAX_DEVICE_REGIONS; i++) {
+ dev_region = manifest_vm->partition.dev_regions[i];
+
+ CHECK(dev_region.interrupt_count <=
+ SP_MAX_INTERRUPTS_PER_DEVICE);
+
+ for (uint8_t j = 0; j < dev_region.interrupt_count; j++) {
+ struct interrupt_descriptor int_desc;
+
+ interrupt = dev_region.interrupts[j];
+ infer_interrupt(interrupt, &int_desc);
+ vm_locked.vm->interrupt_desc[k] = int_desc;
+
+ k++;
+ CHECK(k <= VM_MANIFEST_MAX_INTERRUPTS);
+ }
+ }
+ dlog_verbose("VM has %d physical interrupts defined in manifest.\n", k);
+
if (manifest_vm->is_ffa_partition) {
struct ffa_value bitmap_create_res;
diff --git a/src/manifest.c b/src/manifest.c
index bd8c016..1d2d37a 100644
--- a/src/manifest.c
+++ b/src/manifest.c
@@ -430,7 +430,7 @@
{
struct uint32list_iter list;
uint8_t i = 0;
- uint8_t j = 0;
+ uint32_t j = 0;
dlog_verbose(" Partition Device Regions\n");
@@ -495,6 +495,8 @@
dev_regions[i].interrupts[j].attributes);
j++;
}
+
+ dev_regions[i].interrupt_count = j;
if (j == 0) {
dlog_verbose(" Empty\n");
}
@@ -659,6 +661,7 @@
uint16_t ffa_version_minor;
enum manifest_return_code ret_code = MANIFEST_SUCCESS;
const char *error_string = "specified in manifest is unsupported";
+ uint32_t k = 0;
/* ensure that the SPM version is compatible */
ffa_version_major = (vm->partition.ffa_version & 0xffff0000) >>
@@ -710,6 +713,31 @@
ret_code = MANIFEST_ERROR_NOT_COMPATIBLE;
}
+ for (uint8_t i = 0; i < vm->partition.dev_region_count; i++) {
+ struct device_region dev_region;
+
+ dev_region = vm->partition.dev_regions[i];
+
+ if (dev_region.interrupt_count > SP_MAX_INTERRUPTS_PER_DEVICE) {
+ dlog_error(
+ "Interrupt count for device region exceeds "
+ "limit.\n");
+ ret_code = MANIFEST_ERROR_NOT_COMPATIBLE;
+ continue;
+ }
+
+ for (uint8_t j = 0; j < dev_region.interrupt_count; j++) {
+ k++;
+ if (k > VM_MANIFEST_MAX_INTERRUPTS) {
+ dlog_error(
+ "Interrupt count for VM exceeds "
+ "limit.\n");
+ ret_code = MANIFEST_ERROR_NOT_COMPATIBLE;
+ continue;
+ }
+ }
+ }
+
return ret_code;
}