feat(interrupts): introduce a new paravirtualized interface

This patch adds basic support for a new paravirtualized interface that
allows an SP to reconfigure an interrupt, it owns, in runtime. Further
patches will add the complete support.

Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
Change-Id: I45ad89d177da3303fc413f250e44e4c1ca1bf9dc
diff --git a/inc/hf/arch/plat/ffa.h b/inc/hf/arch/plat/ffa.h
index 2ea7e1a..d68ba60 100644
--- a/inc/hf/arch/plat/ffa.h
+++ b/inc/hf/arch/plat/ffa.h
@@ -372,3 +372,9 @@
 int64_t plat_ffa_mailbox_writable_get(const struct vcpu *current);
 
 int64_t plat_ffa_mailbox_waiter_get(ffa_id_t vm_id, const struct vcpu *current);
+
+/**
+ * Reconfigure the interrupt belonging to the current partition at runtime.
+ */
+int64_t plat_ffa_interrupt_reconfigure(uint32_t int_id, uint32_t command,
+				       uint32_t value, struct vcpu *current);
diff --git a/inc/vmapi/hf/abi.h b/inc/vmapi/hf/abi.h
index 7f2ccde..dd9e698 100644
--- a/inc/vmapi/hf/abi.h
+++ b/inc/vmapi/hf/abi.h
@@ -21,6 +21,7 @@
 #define HF_INTERRUPT_GET               0xff04
 #define HF_INTERRUPT_INJECT            0xff05
 #define HF_INTERRUPT_DEACTIVATE	       0xff08
+#define HF_INTERRUPT_RECONFIGURE       0xff09
 
 /* Custom FF-A-like calls returned from FFA_RUN. */
 #define HF_FFA_RUN_WAIT_FOR_INTERRUPT 0xff06
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index 572c8b8..ab7f9a1 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -1065,6 +1065,11 @@
 		vcpu->regs.r[0] = plat_ffa_interrupt_deactivate(
 			args.arg1, args.arg2, vcpu);
 		break;
+
+	case HF_INTERRUPT_RECONFIGURE:
+		vcpu->regs.r[0] = plat_ffa_interrupt_reconfigure(
+			args.arg1, args.arg2, args.arg3, vcpu);
+		break;
 #endif
 
 	default:
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index 99b8ff0..59bd11c 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -2770,3 +2770,36 @@
 
 	return -1;
 }
+
+/**
+ * Reconfigure the interrupt belonging to the current partition at runtime.
+ */
+int64_t plat_ffa_interrupt_reconfigure(uint32_t int_id, uint32_t command,
+				       uint32_t value, struct vcpu *current)
+{
+	struct vm *vm = current->vm;
+	struct vm_locked vm_locked;
+	int64_t ret = -1;
+	struct interrupt_descriptor *int_desc;
+
+	/*
+	 * Lock VM to protect interrupt descriptor from being modified
+	 * concurrently.
+	 */
+	vm_locked = vm_lock(vm);
+
+	/* Check if the interrupt belongs to the current SP. */
+	int_desc = vm_find_interrupt_descriptor(vm_locked, int_id);
+
+	if (int_desc == NULL) {
+		dlog_verbose("Interrupt %x does not belong to current SP\n",
+			     int_id);
+		goto out_unlock;
+	}
+
+	ret = 0;
+out_unlock:
+	vm_unlock(&vm_locked);
+
+	return ret;
+}