feat(interrupts): support for registering custom handler

This patch provides support for registering and unregistering
handler that is invoked by SP at the tail end of the virtual interrupt
processing.

Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
Change-Id: Ia12686361063bb680ff32b4f4bf90e0af2521c36
diff --git a/spm/common/sp_helpers.c b/spm/common/sp_helpers.c
index 77031f8..448084f 100644
--- a/spm/common/sp_helpers.c
+++ b/spm/common/sp_helpers.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,6 +13,10 @@
 
 #include "sp_helpers.h"
 
+spinlock_t sp_handler_lock[NUM_VINT_ID];
+
+void (*sp_interrupt_tail_end_handler[NUM_VINT_ID])(void);
+
 uintptr_t bound_rand(uintptr_t min, uintptr_t max)
 {
 	/*
@@ -80,3 +84,35 @@
 {
 	(void)sp_sleep_elapsed_time(ms);
 }
+
+void sp_handler_spin_lock_init(void)
+{
+	for (uint32_t i = 0; i < NUM_VINT_ID; i++) {
+		init_spinlock(&sp_handler_lock[i]);
+	}
+}
+
+void sp_register_interrupt_tail_end_handler(void (*handler)(void),
+			uint32_t interrupt_id)
+{
+	if (interrupt_id >= NUM_VINT_ID) {
+		ERROR("Cannot register handler for interrupt %u\n", interrupt_id);
+		panic();
+	}
+
+	spin_lock(&sp_handler_lock[interrupt_id]);
+	sp_interrupt_tail_end_handler[interrupt_id] = handler;
+	spin_unlock(&sp_handler_lock[interrupt_id]);
+}
+
+void sp_unregister_interrupt_tail_end_handler(uint32_t interrupt_id)
+{
+	if (interrupt_id >= NUM_VINT_ID) {
+		ERROR("Cannot unregister handler for interrupt %u\n", interrupt_id);
+		panic();
+	}
+
+	spin_lock(&sp_handler_lock[interrupt_id]);
+	sp_interrupt_tail_end_handler[interrupt_id] = NULL;
+	spin_unlock(&sp_handler_lock[interrupt_id]);
+}