feat(interrupts): allow interrupt to be enabled or disabled in runtime
This patch extends the paravirtualized interface introduced in earlier
patches to either enable or disable a secure physical interrupt.
Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
Change-Id: I86250d8e4788feae4d2b9898567c640aa54b710f
diff --git a/inc/hf/interrupt_desc.h b/inc/hf/interrupt_desc.h
index 815816e..b97bfb0 100644
--- a/inc/hf/interrupt_desc.h
+++ b/inc/hf/interrupt_desc.h
@@ -58,6 +58,14 @@
#define INT_SEC_STATE_S 1
/**
+ * Legal values to enable or disable an interrupt through the
+ * `INT_RECONFIGURE_ENABLE` command using the `HF_INTERRUPT_RECONFIGURE`
+ * paravirtualized interface.
+ */
+#define INT_DISABLE 0
+#define INT_ENABLE 1
+
+/**
* Attributes encoding in the manifest:
* Field Bit(s)
@@ -111,6 +119,7 @@
bool valid;
bool mpidr_valid;
uint64_t mpidr;
+ bool enabled;
};
/**
@@ -213,3 +222,9 @@
{
int_desc->valid = valid;
}
+
+static inline void interrupt_desc_set_enabled(
+ struct interrupt_descriptor *int_desc, bool enable)
+{
+ int_desc->enabled = enable;
+}
diff --git a/inc/hf/vm.h b/inc/hf/vm.h
index 3f06d38..9b7f40e 100644
--- a/inc/hf/vm.h
+++ b/inc/hf/vm.h
@@ -399,3 +399,5 @@
struct vm_locked vm_locked, uint32_t id, uint32_t target_mpidr);
struct interrupt_descriptor *vm_interrupt_set_sec_state(
struct vm_locked vm_locked, uint32_t id, uint32_t sec_state);
+struct interrupt_descriptor *vm_interrupt_set_enable(struct vm_locked vm_locked,
+ uint32_t id, bool enable);
diff --git a/inc/vmapi/hf/abi.h b/inc/vmapi/hf/abi.h
index 9a078d4..8e35ddf 100644
--- a/inc/vmapi/hf/abi.h
+++ b/inc/vmapi/hf/abi.h
@@ -29,5 +29,6 @@
/* Possible commands that reconfigure an interrupt. */
#define INT_RECONFIGURE_TARGET_PE 0
#define INT_RECONFIGURE_SEC_STATE 1
+#define INT_RECONFIGURE_ENABLE 2
/* clang-format on */
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index aca307b..a197256 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -2778,6 +2778,7 @@
* partition:
* - Change the target CPU of the interrupt.
* - Change the security state of the interrupt.
+ * - Enable or disable the physical interrupt.
*/
int64_t plat_ffa_interrupt_reconfigure(uint32_t int_id, uint32_t command,
uint32_t value, struct vcpu *current)
@@ -2832,6 +2833,19 @@
}
int_desc = vm_interrupt_set_sec_state(vm_locked, int_id, value);
break;
+ case INT_RECONFIGURE_ENABLE:
+ /* Enable or disable the interrupt. */
+ if (value != INT_DISABLE && value != INT_ENABLE) {
+ dlog_verbose(
+ "Illegal value %x specified while "
+ "reconfiguring interrupt %x\n",
+ value, int_id);
+ goto out_unlock;
+ } else {
+ int_desc = vm_interrupt_set_enable(vm_locked, int_id,
+ value == INT_ENABLE);
+ }
+ break;
default:
dlog_verbose("Interrupt reconfigure: Unsupported command %x\n",
command);
diff --git a/src/load.c b/src/load.c
index 1c1794d..ae97a2d 100644
--- a/src/load.c
+++ b/src/load.c
@@ -151,6 +151,7 @@
}
interrupt_desc_set_valid(int_desc, true);
+ interrupt_desc_set_enabled(int_desc, true);
}
/**
@@ -184,6 +185,7 @@
interrupt = dev_region.interrupts[j];
infer_interrupt(interrupt, &int_desc);
vm_locked.vm->interrupt_desc[k] = int_desc;
+ assert(int_desc.enabled);
/*
* Configure the physical interrupts allocated for this
diff --git a/src/vm.c b/src/vm.c
index ec1e374..8a91a2b 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -1041,3 +1041,20 @@
return int_desc;
}
+
+/**
+ * Enable or disable the specified interrupt id belonging to specified vm.
+ */
+struct interrupt_descriptor *vm_interrupt_set_enable(struct vm_locked vm_locked,
+ uint32_t id, bool enable)
+{
+ struct interrupt_descriptor *int_desc;
+
+ int_desc = vm_find_interrupt_descriptor(vm_locked, id);
+
+ if (int_desc != NULL) {
+ interrupt_desc_set_enabled(int_desc, enable);
+ }
+
+ return int_desc;
+}