SDEI: Allow platforms to define explicit events

The current macros only allow to define dynamic and statically-bound
SDEI events. However, there ought be a mechanism to define SDEI events
that are explicitly dispatched; i.e., events that are dispatched as a
result of a previous secure interrupt or other exception

This patch introduces SDEI_EXPLICIT_EVENT() macro to define an explicit
event. They must be placed under private mappings. Only the priority
flags are allowed to be additionally specified.

Documentation updated.

Change-Id: I2e12f5571381195d6234c9dfbd5904608ad41db3
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
diff --git a/services/std_svc/sdei/sdei_intr_mgmt.c b/services/std_svc/sdei/sdei_intr_mgmt.c
index c0bd9de..a7104b4 100644
--- a/services/std_svc/sdei/sdei_intr_mgmt.c
+++ b/services/std_svc/sdei/sdei_intr_mgmt.c
@@ -520,15 +520,8 @@
 	if (!map)
 		return -1;
 
-	/*
-	 * Statically-bound or dynamic maps are dispatched only as a result of
-	 * interrupt, and not upon explicit request.
-	 */
-	if (is_map_dynamic(map) || is_map_bound(map))
-		return -1;
-
-	/* The event must be private */
-	if (is_event_shared(map))
+	/* Only explicit events can be dispatched */
+	if (!is_map_explicit(map))
 		return -1;
 
 	/* Examine state of dispatch stack */
diff --git a/services/std_svc/sdei/sdei_main.c b/services/std_svc/sdei/sdei_main.c
index 9589a25..f881ba8 100644
--- a/services/std_svc/sdei/sdei_main.c
+++ b/services/std_svc/sdei/sdei_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -111,6 +111,9 @@
 
 		/* No shared mapping should have signalable property */
 		assert(!is_event_signalable(map));
+
+		/* Shared mappings can't be explicit */
+		assert(!is_map_explicit(map));
 #endif
 
 		/* Skip initializing the wrong priority */
@@ -162,6 +165,16 @@
 
 		/* Make sure it's a private event */
 		assert(is_event_private(map));
+
+		/*
+		 * Other than priority, explicit events can only have explicit
+		 * and private flags set.
+		 */
+		if (is_map_explicit(map)) {
+			assert((map->map_flags | SDEI_MAPF_CRITICAL) ==
+					(SDEI_MAPF_EXPLICIT | SDEI_MAPF_PRIVATE
+					| SDEI_MAPF_CRITICAL));
+		}
 #endif
 
 		/* Skip initializing the wrong priority */
@@ -174,6 +187,12 @@
 				assert(map->intr == SDEI_DYN_IRQ);
 				assert(is_event_normal(map));
 				num_dyn_priv_slots++;
+			} else if (is_map_explicit(map)) {
+				/*
+				 * Explicit mappings don't have a backing
+				 * SDEI interrupt, but verify that anyway.
+				 */
+				assert(map->intr == SDEI_DYN_IRQ);
 			} else {
 				/*
 				 * Private mappings must be bound to private
diff --git a/services/std_svc/sdei/sdei_private.h b/services/std_svc/sdei/sdei_private.h
index 44db419..45d537f 100644
--- a/services/std_svc/sdei/sdei_private.h
+++ b/services/std_svc/sdei/sdei_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -137,6 +137,11 @@
 	map->map_flags |= BIT(_SDEI_MAPF_BOUND_SHIFT);
 }
 
+static inline int is_map_explicit(sdei_ev_map_t *map)
+{
+	return ((map->map_flags & BIT(_SDEI_MAPF_EXPLICIT_SHIFT)) != 0);
+}
+
 static inline void clr_map_bound(sdei_ev_map_t *map)
 {
 	map->map_flags &= ~(BIT(_SDEI_MAPF_BOUND_SHIFT));