BL31: Add SDEI dispatcher

The implementation currently supports only interrupt-based SDEI events,
and supports all interfaces as defined by SDEI specification version
1.0 [1].

Introduce the build option SDEI_SUPPORT to include SDEI dispatcher in
BL31.

Update user guide and porting guide. SDEI documentation to follow.

[1] http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf

Change-Id: I758b733084e4ea3b27ac77d0259705565842241a
Co-authored-by: Yousuf A <yousuf.sait@arm.com>
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
diff --git a/services/std_svc/sdei/sdei_state.c b/services/std_svc/sdei/sdei_state.c
new file mode 100644
index 0000000..3f60dfd
--- /dev/null
+++ b/services/std_svc/sdei/sdei_state.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <cassert.h>
+#include <stdbool.h>
+#include "sdei_private.h"
+
+/* Aliases for SDEI handler states: 'R'unning, 'E'nabled, and re'G'istered */
+#define r_		0
+#define R_		(1u << SDEI_STATF_RUNNING)
+
+#define e_		0
+#define E_		(1u << SDEI_STATF_ENABLED)
+
+#define g_		0
+#define G_		(1u << SDEI_STATF_REGISTERED)
+
+/* All possible composite handler states */
+#define reg_		(r_ | e_ | g_)
+#define reG_		(r_ | e_ | G_)
+#define rEg_		(r_ | E_ | g_)
+#define rEG_		(r_ | E_ | G_)
+#define Reg_		(R_ | e_ | g_)
+#define ReG_		(R_ | e_ | G_)
+#define REg_		(R_ | E_ | g_)
+#define REG_		(R_ | E_ | G_)
+
+#define MAX_STATES	(REG_ + 1)
+
+/* Invalid state */
+#define	SDEI_STATE_INVALID	((sdei_state_t) (-1))
+
+/* No change in state */
+#define	SDEI_STATE_NOP		((sdei_state_t) (-2))
+
+#define X___		SDEI_STATE_INVALID
+#define NOP_		SDEI_STATE_NOP
+
+/* Ensure special states don't overlap with valid ones */
+CASSERT(X___ > REG_, sdei_state_overlap_invalid);
+CASSERT(NOP_ > REG_, sdei_state_overlap_nop);
+
+/*
+ * SDEI handler state machine: refer to sections 6.1 and 6.1.2 of the SDEI v1.0
+ * specification:
+ *
+ * http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf
+ *
+ * Not all calls contribute to handler state transition. This table is also used
+ * to validate whether a call is permissible at a given handler state:
+ *
+ *  - X___ denotes a forbidden transition;
+ *  - NOP_ denotes a permitted transition, but there's no change in state;
+ *  - Otherwise, XXX_ gives the new state.
+ *
+ * DISP[atch] is a transition added for the implementation, but is not mentioned
+ * in the spec.
+ *
+ * Those calls that the spec mentions as can be made any time don't picture in
+ * this table.
+ */
+
+static const sdei_state_t sdei_state_table[MAX_STATES][DO_MAX] = {
+/*
+ *	Action:		REG     REL	ENA	DISA	UREG	ROUT	CTX	COMP	COMPR	DISP
+ *	Notes:			[3]			[1]	[3]	[3][4]			[2]
+ */
+	/* Handler unregistered, disabled, and not running. This is the default state. */
+/* 0 */	[reg_] = {	reG_,	NOP_,	X___,	X___,	X___,	X___,	X___,	X___,	X___,	X___,	},
+
+	/* Handler unregistered and running */
+/* 4 */	[Reg_] = {	X___,	X___,	X___,	X___,	X___,	X___,	NOP_,	reg_,	reg_,	X___,	},
+
+	/* Handler registered */
+/* 1 */	[reG_] = {	X___,	X___,	rEG_,	NOP_,	reg_,	NOP_,	X___,	X___,	X___,	X___,	},
+
+	/* Handler registered and running */
+/* 5 */	[ReG_] = {	X___,	X___,	REG_,	NOP_,	Reg_,	X___,	NOP_,	reG_,	reG_,	X___,	},
+
+	/* Handler registered and enabled */
+/* 3 */	[rEG_] = {	X___,	X___,	NOP_,	reG_,	reg_,	X___,	X___,	X___,	X___,	REG_,	},
+
+	/* Handler registered, enabled, and running */
+/* 7 */	[REG_] = {	X___,	X___,	NOP_,	ReG_,	Reg_,	X___,	NOP_,	rEG_,	rEG_,	X___,	},
+
+	/*
+	 * Invalid states: no valid transition would leave the handler in these
+	 * states; and no transition from these states is possible either.
+	 */
+
+	/*
+	 * Handler can't be enabled without being registered. I.e., XEg is
+	 * impossible.
+	 */
+/* 2 */	[rEg_] = {	X___,	X___,	X___,	X___,	X___,	X___,	X___,	X___,	X___,	X___,	},
+/* 6 */	[REg_] = {	X___,	X___,	X___,	X___,	X___,	X___,	X___,	X___,	X___,	X___,	},
+};
+
+/*
+ * [1] Unregister will always also disable the event, so the new state will have
+ *     Xeg.
+ * [2] Event is considered for dispatch only when it's both registered and
+ *     enabled.
+ * [3] Never causes change in state.
+ * [4] Only allowed when running.
+ */
+
+/*
+ * Given an action, transition the state of an event by looking up the state
+ * table above:
+ *
+ *  - Return false for invalid transition;
+ *  - Return true for valid transition that causes no change in state;
+ *  - Otherwise, update state and return true.
+ *
+ * This function assumes that the caller holds necessary locks. If the
+ * transition has constrains other than the state table describes, the caller is
+ * expected to restore the previous state. See sdei_event_register() for
+ * example.
+ */
+bool can_sdei_state_trans(sdei_entry_t *se, sdei_action_t act)
+{
+	sdei_state_t next;
+
+	assert(act < DO_MAX);
+	if (se->state >= MAX_STATES) {
+		WARN(" event state invalid: %x\n", se->state);
+		return false;
+	}
+
+	next = sdei_state_table[se->state][act];
+	switch (next) {
+	case SDEI_STATE_INVALID:
+		return false;
+
+	case SDEI_STATE_NOP:
+		return true;
+
+	default:
+		/* Valid transition. Update state. */
+		SDEI_LOG(" event state 0x%x => 0x%x\n", se->state, next);
+		se->state = next;
+
+		return true;
+	}
+}