/*
 * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
#include <inttypes.h>
#include <stdint.h>
#include <string.h>

#include <arch_helpers.h>
#include <arch_features.h>
#include <bl31/ehf.h>
#include <bl31/interrupt_mgmt.h>
#include <common/bl_common.h>
#include <common/debug.h>
#include <common/runtime_svc.h>
#include <lib/cassert.h>
#include <services/sdei.h>

#include "sdei_private.h"

/* x0-x17 GPREGS context */
#define SDEI_SAVED_GPREGS	18U

/* Maximum preemption nesting levels: Critical priority and Normal priority */
#define MAX_EVENT_NESTING	2U

/* Per-CPU SDEI state access macro */
#define sdei_get_this_pe_state()	(&cpu_state[plat_my_core_pos()])

/* Structure to store information about an outstanding dispatch */
typedef struct sdei_dispatch_context {
	sdei_ev_map_t *map;
	uint64_t x[SDEI_SAVED_GPREGS];
	jmp_buf *dispatch_jmp;

	/* Exception state registers */
	uint64_t elr_el3;
	uint64_t spsr_el3;

#if DYNAMIC_WORKAROUND_CVE_2018_3639
	/* CVE-2018-3639 mitigation state */
	uint64_t disable_cve_2018_3639;
#endif
} sdei_dispatch_context_t;

/* Per-CPU SDEI state data */
typedef struct sdei_cpu_state {
	sdei_dispatch_context_t dispatch_stack[MAX_EVENT_NESTING];
	unsigned short stack_top; /* Empty ascending */
	bool pe_masked;
	bool pending_enables;
} sdei_cpu_state_t;

/* SDEI states for all cores in the system */
static sdei_cpu_state_t cpu_state[PLATFORM_CORE_COUNT];

int64_t sdei_pe_mask(void)
{
	int64_t ret = 0;
	sdei_cpu_state_t *state = sdei_get_this_pe_state();

	/*
	 * Return value indicates whether this call had any effect in the mask
	 * status of this PE.
	 */
	if (!state->pe_masked) {
		state->pe_masked = true;
		ret = 1;
	}

	return ret;
}

void sdei_pe_unmask(void)
{
	unsigned int i;
	sdei_ev_map_t *map;
	sdei_entry_t *se;
	sdei_cpu_state_t *state = sdei_get_this_pe_state();
	uint64_t my_mpidr = read_mpidr_el1() & MPIDR_AFFINITY_MASK;

	/*
	 * If there are pending enables, iterate through the private mappings
	 * and enable those bound maps that are in enabled state. Also, iterate
	 * through shared mappings and enable interrupts of events that are
	 * targeted to this PE.
	 */
	if (state->pending_enables) {
		for_each_private_map(i, map) {
			se = get_event_entry(map);
			if (is_map_bound(map) && GET_EV_STATE(se, ENABLED))
				plat_ic_enable_interrupt(map->intr);
		}

		for_each_shared_map(i, map) {
			se = get_event_entry(map);

			sdei_map_lock(map);
			if (is_map_bound(map) && GET_EV_STATE(se, ENABLED) &&
					(se->reg_flags == SDEI_REGF_RM_PE) &&
					(se->affinity == my_mpidr)) {
				plat_ic_enable_interrupt(map->intr);
			}
			sdei_map_unlock(map);
		}
	}

	state->pending_enables = false;
	state->pe_masked = false;
}

/* Push a dispatch context to the dispatch stack */
static sdei_dispatch_context_t *push_dispatch(void)
{
	sdei_cpu_state_t *state = sdei_get_this_pe_state();
	sdei_dispatch_context_t *disp_ctx;

	/* Cannot have more than max events */
	assert(state->stack_top < MAX_EVENT_NESTING);

	disp_ctx = &state->dispatch_stack[state->stack_top];
	state->stack_top++;

	return disp_ctx;
}

/* Pop a dispatch context to the dispatch stack */
static sdei_dispatch_context_t *pop_dispatch(void)
{
	sdei_cpu_state_t *state = sdei_get_this_pe_state();

	if (state->stack_top == 0U)
		return NULL;

	assert(state->stack_top <= MAX_EVENT_NESTING);

	state->stack_top--;

	return &state->dispatch_stack[state->stack_top];
}

/* Retrieve the context at the top of dispatch stack */
static sdei_dispatch_context_t *get_outstanding_dispatch(void)
{
	sdei_cpu_state_t *state = sdei_get_this_pe_state();

	if (state->stack_top == 0U)
		return NULL;

	assert(state->stack_top <= MAX_EVENT_NESTING);

	return &state->dispatch_stack[state->stack_top - 1U];
}

static sdei_dispatch_context_t *save_event_ctx(sdei_ev_map_t *map,
		void *tgt_ctx)
{
	sdei_dispatch_context_t *disp_ctx;
	const gp_regs_t *tgt_gpregs;
	const el3_state_t *tgt_el3;

	assert(tgt_ctx != NULL);
	tgt_gpregs = get_gpregs_ctx(tgt_ctx);
	tgt_el3 = get_el3state_ctx(tgt_ctx);

	disp_ctx = push_dispatch();
	assert(disp_ctx != NULL);
	disp_ctx->map = map;

	/* Save general purpose and exception registers */
	memcpy(disp_ctx->x, tgt_gpregs, sizeof(disp_ctx->x));
	disp_ctx->spsr_el3 = read_ctx_reg(tgt_el3, CTX_SPSR_EL3);
	disp_ctx->elr_el3 = read_ctx_reg(tgt_el3, CTX_ELR_EL3);

	return disp_ctx;
}

static void restore_event_ctx(const sdei_dispatch_context_t *disp_ctx, void *tgt_ctx)
{
	gp_regs_t *tgt_gpregs;
	el3_state_t *tgt_el3;

	assert(tgt_ctx != NULL);
	tgt_gpregs = get_gpregs_ctx(tgt_ctx);
	tgt_el3 = get_el3state_ctx(tgt_ctx);

	CASSERT(sizeof(disp_ctx->x) == (SDEI_SAVED_GPREGS * sizeof(uint64_t)),
			foo);

	/* Restore general purpose and exception registers */
	memcpy(tgt_gpregs, disp_ctx->x, sizeof(disp_ctx->x));
	write_ctx_reg(tgt_el3, CTX_SPSR_EL3, disp_ctx->spsr_el3);
	write_ctx_reg(tgt_el3, CTX_ELR_EL3, disp_ctx->elr_el3);

#if DYNAMIC_WORKAROUND_CVE_2018_3639
	cve_2018_3639_t *tgt_cve_2018_3639;
	tgt_cve_2018_3639 = get_cve_2018_3639_ctx(tgt_ctx);

	/* Restore CVE-2018-3639 mitigation state */
	write_ctx_reg(tgt_cve_2018_3639, CTX_CVE_2018_3639_DISABLE,
		disp_ctx->disable_cve_2018_3639);
#endif
}

static void save_secure_context(void)
{
	cm_el1_sysregs_context_save(SECURE);
}

/* Restore Secure context and arrange to resume it at the next ERET */
static void restore_and_resume_secure_context(void)
{
	cm_el1_sysregs_context_restore(SECURE);
	cm_set_next_eret_context(SECURE);
}

/*
 * Restore Non-secure context and arrange to resume it at the next ERET. Return
 * pointer to the Non-secure context.
 */
static cpu_context_t *restore_and_resume_ns_context(void)
{
	cpu_context_t *ns_ctx;

	cm_el1_sysregs_context_restore(NON_SECURE);
	cm_set_next_eret_context(NON_SECURE);

	ns_ctx = cm_get_context(NON_SECURE);
	assert(ns_ctx != NULL);

	return ns_ctx;
}

/*
 * Prepare for ERET:
 * - Set the ELR to the registered handler address
 * - Set the SPSR register as described in the SDEI documentation and
 *   the AArch64.TakeException() pseudocode function in
 *   ARM DDI 0487F.c page J1-7635
 */

static void sdei_set_elr_spsr(sdei_entry_t *se, sdei_dispatch_context_t *disp_ctx)
{
	unsigned int client_el = sdei_client_el();
	u_register_t sdei_spsr = SPSR_64(client_el, MODE_SP_ELX,
					DISABLE_ALL_EXCEPTIONS);

	u_register_t interrupted_pstate = disp_ctx->spsr_el3;

	/* Check the SPAN bit in the client el SCTLR */
	u_register_t client_el_sctlr;

	if (client_el == MODE_EL2) {
		client_el_sctlr = read_sctlr_el2();
	} else {
		client_el_sctlr = read_sctlr_el1();
	}

	/*
	 * Check whether to force the PAN bit or use the value in the
	 * interrupted EL according to the check described in
	 * TakeException. Since the client can only be Non-Secure
	 * EL2 or El1 some of the conditions in ElIsInHost() we know
	 * will always be True.
	 * When the client_el is EL2 we know that there will be a SPAN
	 * bit in SCTLR_EL2 as we have already checked for the condition
	 * HCR_EL2.E2H = 1 and HCR_EL2.TGE = 1
	 */
	u_register_t hcr_el2 = read_hcr();
	bool el_is_in_host = (read_feat_vhe_id_field() != 0U) &&
			     (hcr_el2 & HCR_TGE_BIT) &&
			     (hcr_el2 & HCR_E2H_BIT);

	if (is_feat_pan_supported() &&
	    ((client_el == MODE_EL1) ||
		(client_el == MODE_EL2 && el_is_in_host)) &&
	    ((client_el_sctlr & SCTLR_SPAN_BIT) == 0U)) {
		sdei_spsr |=  SPSR_PAN_BIT;
	} else {
		sdei_spsr |= (interrupted_pstate & SPSR_PAN_BIT);
	}

	/* If SSBS is implemented, take the value from the client el SCTLR */
	u_register_t ssbs_enabled = (read_id_aa64pfr1_el1()
					>> ID_AA64PFR1_EL1_SSBS_SHIFT)
					& ID_AA64PFR1_EL1_SSBS_MASK;
	if (ssbs_enabled != SSBS_UNAVAILABLE) {
		u_register_t  ssbs_bit = ((client_el_sctlr & SCTLR_DSSBS_BIT)
						>> SCTLR_DSSBS_SHIFT)
						<< SPSR_SSBS_SHIFT_AARCH64;
		sdei_spsr |= ssbs_bit;
	}

	/* If MTE is implemented in the client el set the TCO bit */
	if (get_armv8_5_mte_support() >= MTE_IMPLEMENTED_ELX) {
		sdei_spsr |= SPSR_TCO_BIT_AARCH64;
	}

	/* Take the DIT field from the pstate of the interrupted el */
	sdei_spsr |= (interrupted_pstate & SPSR_DIT_BIT);

	cm_set_elr_spsr_el3(NON_SECURE, (uintptr_t) se->ep, sdei_spsr);
}

/*
 * Populate the Non-secure context so that the next ERET will dispatch to the
 * SDEI client.
 */
static void setup_ns_dispatch(sdei_ev_map_t *map, sdei_entry_t *se,
		cpu_context_t *ctx, jmp_buf *dispatch_jmp)
{
	sdei_dispatch_context_t *disp_ctx;

	/* Push the event and context */
	disp_ctx = save_event_ctx(map, ctx);

	/*
	 * Setup handler arguments:
	 *
	 * - x0: Event number
	 * - x1: Handler argument supplied at the time of event registration
	 * - x2: Interrupted PC
	 * - x3: Interrupted SPSR
	 */
	SMC_SET_GP(ctx, CTX_GPREG_X0, (uint64_t) map->ev_num);
	SMC_SET_GP(ctx, CTX_GPREG_X1, se->arg);
	SMC_SET_GP(ctx, CTX_GPREG_X2, disp_ctx->elr_el3);
	SMC_SET_GP(ctx, CTX_GPREG_X3, disp_ctx->spsr_el3);

	/* Setup the elr and spsr register to prepare for ERET */
	sdei_set_elr_spsr(se, disp_ctx);

#if DYNAMIC_WORKAROUND_CVE_2018_3639
	cve_2018_3639_t *tgt_cve_2018_3639;
	tgt_cve_2018_3639 = get_cve_2018_3639_ctx(ctx);

	/* Save CVE-2018-3639 mitigation state */
	disp_ctx->disable_cve_2018_3639 = read_ctx_reg(tgt_cve_2018_3639,
		CTX_CVE_2018_3639_DISABLE);

	/* Force SDEI handler to execute with mitigation enabled by default */
	write_ctx_reg(tgt_cve_2018_3639, CTX_CVE_2018_3639_DISABLE, 0);
#endif

	disp_ctx->dispatch_jmp = dispatch_jmp;
}

/* Handle a triggered SDEI interrupt while events were masked on this PE */
static void handle_masked_trigger(sdei_ev_map_t *map, sdei_entry_t *se,
		sdei_cpu_state_t *state, unsigned int intr_raw)
{
	uint64_t my_mpidr __unused = (read_mpidr_el1() & MPIDR_AFFINITY_MASK);
	bool disable = false;

	/* Nothing to do for event 0 */
	if (map->ev_num == SDEI_EVENT_0)
		return;

	/*
	 * For a private event, or for a shared event specifically routed to
	 * this CPU, we disable interrupt, leave the interrupt pending, and do
	 * EOI.
	 */
	if (is_event_private(map) || (se->reg_flags == SDEI_REGF_RM_PE))
		disable = true;

	if (se->reg_flags == SDEI_REGF_RM_PE)
		assert(se->affinity == my_mpidr);

	if (disable) {
		plat_ic_disable_interrupt(map->intr);
		plat_ic_set_interrupt_pending(map->intr);
		plat_ic_end_of_interrupt(intr_raw);
		state->pending_enables = true;

		return;
	}

	/*
	 * We just received a shared event with routing set to ANY PE. The
	 * interrupt can't be delegated on this PE as SDEI events are masked.
	 * However, because its routing mode is ANY, it is possible that the
	 * event can be delegated on any other PE that hasn't masked events.
	 * Therefore, we set the interrupt back pending so as to give other
	 * suitable PEs a chance of handling it.
	 */
	assert(plat_ic_is_spi(map->intr) != 0);
	plat_ic_set_interrupt_pending(map->intr);

	/*
	 * Leaving the same interrupt pending also means that the same interrupt
	 * can target this PE again as soon as this PE leaves EL3. Whether and
	 * how often that happens depends on the implementation of GIC.
	 *
	 * We therefore call a platform handler to resolve this situation.
	 */
	plat_sdei_handle_masked_trigger(my_mpidr, map->intr);

	/* This PE is masked. We EOI the interrupt, as it can't be delegated */
	plat_ic_end_of_interrupt(intr_raw);
}

/* SDEI main interrupt handler */
int sdei_intr_handler(uint32_t intr_raw, uint32_t flags, void *handle,
		void *cookie)
{
	sdei_entry_t *se;
	cpu_context_t *ctx;
	sdei_ev_map_t *map;
	const sdei_dispatch_context_t *disp_ctx;
	unsigned int sec_state;
	sdei_cpu_state_t *state;
	uint32_t intr;
	jmp_buf dispatch_jmp;
	const uint64_t mpidr = read_mpidr_el1();

	/*
	 * To handle an event, the following conditions must be true:
	 *
	 * 1. Event must be signalled
	 * 2. Event must be enabled
	 * 3. This PE must be a target PE for the event
	 * 4. PE must be unmasked for SDEI
	 * 5. If this is a normal event, no event must be running
	 * 6. If this is a critical event, no critical event must be running
	 *
	 * (1) and (2) are true when this function is running
	 * (3) is enforced in GIC by selecting the appropriate routing option
	 * (4) is satisfied by client calling PE_UNMASK
	 * (5) and (6) is enforced using interrupt priority, the RPR, in GIC:
	 *   - Normal SDEI events belong to Normal SDE priority class
	 *   - Critical SDEI events belong to Critical CSDE priority class
	 *
	 * The interrupt has already been acknowledged, and therefore is active,
	 * so no other PE can handle this event while we are at it.
	 *
	 * Find if this is an SDEI interrupt. There must be an event mapped to
	 * this interrupt
	 */
	intr = plat_ic_get_interrupt_id(intr_raw);
	map = find_event_map_by_intr(intr, (plat_ic_is_spi(intr) != 0));
	if (map == NULL) {
		ERROR("No SDEI map for interrupt %u\n", intr);
		panic();
	}

	/*
	 * Received interrupt number must either correspond to event 0, or must
	 * be bound interrupt.
	 */
	assert((map->ev_num == SDEI_EVENT_0) || is_map_bound(map));

	se = get_event_entry(map);
	state = sdei_get_this_pe_state();

	if (state->pe_masked) {
		/*
		 * Interrupts received while this PE was masked can't be
		 * dispatched.
		 */
		SDEI_LOG("interrupt %u on %" PRIx64 " while PE masked\n",
			 map->intr, mpidr);
		if (is_event_shared(map))
			sdei_map_lock(map);

		handle_masked_trigger(map, se, state, intr_raw);

		if (is_event_shared(map))
			sdei_map_unlock(map);

		return 0;
	}

	/* Insert load barrier for signalled SDEI event */
	if (map->ev_num == SDEI_EVENT_0)
		dmbld();

	if (is_event_shared(map))
		sdei_map_lock(map);

	/* Assert shared event routed to this PE had been configured so */
	if (is_event_shared(map) && (se->reg_flags == SDEI_REGF_RM_PE)) {
		assert(se->affinity == (mpidr & MPIDR_AFFINITY_MASK));
	}

	if (!can_sdei_state_trans(se, DO_DISPATCH)) {
		SDEI_LOG("SDEI event 0x%x can't be dispatched; state=0x%x\n",
				map->ev_num, se->state);

		/*
		 * If the event is registered, leave the interrupt pending so
		 * that it's delivered when the event is enabled.
		 */
		if (GET_EV_STATE(se, REGISTERED))
			plat_ic_set_interrupt_pending(map->intr);

		/*
		 * The interrupt was disabled or unregistered after the handler
		 * started to execute, which means now the interrupt is already
		 * disabled and we just need to EOI the interrupt.
		 */
		plat_ic_end_of_interrupt(intr_raw);

		if (is_event_shared(map))
			sdei_map_unlock(map);

		return 0;
	}

	disp_ctx = get_outstanding_dispatch();
	if (is_event_critical(map)) {
		/*
		 * If this event is Critical, and if there's an outstanding
		 * dispatch, assert the latter is a Normal dispatch. Critical
		 * events can preempt an outstanding Normal event dispatch.
		 */
		if (disp_ctx != NULL)
			assert(is_event_normal(disp_ctx->map));
	} else {
		/*
		 * If this event is Normal, assert that there are no outstanding
		 * dispatches. Normal events can't preempt any outstanding event
		 * dispatches.
		 */
		assert(disp_ctx == NULL);
	}

	sec_state = get_interrupt_src_ss(flags);

	if (is_event_shared(map))
		sdei_map_unlock(map);

	SDEI_LOG("ACK %" PRIx64 ", ev:0x%x ss:%d spsr:%lx ELR:%lx\n",
		 mpidr, map->ev_num, sec_state, read_spsr_el3(), read_elr_el3());

	ctx = handle;

	/*
	 * Check if we interrupted secure state. Perform a context switch so
	 * that we can delegate to NS.
	 */
	if (sec_state == SECURE) {
		save_secure_context();
		ctx = restore_and_resume_ns_context();
	}

	/* Synchronously dispatch event */
	setup_ns_dispatch(map, se, ctx, &dispatch_jmp);
	begin_sdei_synchronous_dispatch(&dispatch_jmp);

	/*
	 * We reach here when client completes the event.
	 *
	 * If the cause of dispatch originally interrupted the Secure world,
	 * resume Secure.
	 *
	 * No need to save the Non-secure context ahead of a world switch: the
	 * Non-secure context was fully saved before dispatch, and has been
	 * returned to its pre-dispatch state.
	 */
	if (sec_state == SECURE)
		restore_and_resume_secure_context();

	/*
	 * The event was dispatched after receiving SDEI interrupt. With
	 * the event handling completed, EOI the corresponding
	 * interrupt.
	 */
	if ((map->ev_num != SDEI_EVENT_0) && !is_map_bound(map)) {
		ERROR("Invalid SDEI mapping: ev=0x%x\n", map->ev_num);
		panic();
	}
	plat_ic_end_of_interrupt(intr_raw);

	return 0;
}

/*
 * Explicitly dispatch the given SDEI event.
 *
 * When calling this API, the caller must be prepared for the SDEI dispatcher to
 * restore and make Non-secure context as active. This call returns only after
 * the client has completed the dispatch. Then, the Non-secure context will be
 * active, and the following ERET will return to Non-secure.
 *
 * Should the caller require re-entry to Secure, it must restore the Secure
 * context and program registers for ERET.
 */
int sdei_dispatch_event(int ev_num)
{
	sdei_entry_t *se;
	sdei_ev_map_t *map;
	cpu_context_t *ns_ctx;
	sdei_dispatch_context_t *disp_ctx;
	sdei_cpu_state_t *state;
	jmp_buf dispatch_jmp;

	/* Can't dispatch if events are masked on this PE */
	state = sdei_get_this_pe_state();
	if (state->pe_masked)
		return -1;

	/* Event 0 can't be dispatched */
	if (ev_num == SDEI_EVENT_0)
		return -1;

	/* Locate mapping corresponding to this event */
	map = find_event_map(ev_num);
	if (map == NULL)
		return -1;

	/* Only explicit events can be dispatched */
	if (!is_map_explicit(map))
		return -1;

	/* Examine state of dispatch stack */
	disp_ctx = get_outstanding_dispatch();
	if (disp_ctx != NULL) {
		/*
		 * There's an outstanding dispatch. If the outstanding dispatch
		 * is critical, no more dispatches are possible.
		 */
		if (is_event_critical(disp_ctx->map))
			return -1;

		/*
		 * If the outstanding dispatch is Normal, only critical events
		 * can be dispatched.
		 */
		if (is_event_normal(map))
			return -1;
	}

	se = get_event_entry(map);
	if (!can_sdei_state_trans(se, DO_DISPATCH))
		return -1;

	/*
	 * Prepare for NS dispatch by restoring the Non-secure context and
	 * marking that as active.
	 */
	ns_ctx = restore_and_resume_ns_context();

	/* Activate the priority corresponding to the event being dispatched */
	ehf_activate_priority(sdei_event_priority(map));

	/* Dispatch event synchronously */
	setup_ns_dispatch(map, se, ns_ctx, &dispatch_jmp);
	begin_sdei_synchronous_dispatch(&dispatch_jmp);

	/*
	 * We reach here when client completes the event.
	 *
	 * Deactivate the priority level that was activated at the time of
	 * explicit dispatch.
	 */
	ehf_deactivate_priority(sdei_event_priority(map));

	return 0;
}

static void end_sdei_synchronous_dispatch(jmp_buf *buffer)
{
	longjmp(*buffer, 1);
}

int sdei_event_complete(bool resume, uint64_t pc)
{
	sdei_dispatch_context_t *disp_ctx;
	sdei_entry_t *se;
	sdei_ev_map_t *map;
	cpu_context_t *ctx;
	sdei_action_t act;
	unsigned int client_el = sdei_client_el();

	/* Return error if called without an active event */
	disp_ctx = get_outstanding_dispatch();
	if (disp_ctx == NULL)
		return SDEI_EDENY;

	/* Validate resumption point */
	if (resume && (plat_sdei_validate_entry_point(pc, client_el) != 0))
		return SDEI_EDENY;

	map = disp_ctx->map;
	assert(map != NULL);
	se = get_event_entry(map);

	if (is_event_shared(map))
		sdei_map_lock(map);

	act = resume ? DO_COMPLETE_RESUME : DO_COMPLETE;
	if (!can_sdei_state_trans(se, act)) {
		if (is_event_shared(map))
			sdei_map_unlock(map);
		return SDEI_EDENY;
	}

	if (is_event_shared(map))
		sdei_map_unlock(map);

	/* Having done sanity checks, pop dispatch */
	(void) pop_dispatch();

	SDEI_LOG("EOI:%lx, %d spsr:%lx elr:%lx\n", read_mpidr_el1(),
			map->ev_num, read_spsr_el3(), read_elr_el3());

	/*
	 * Restore Non-secure to how it was originally interrupted. Once done,
	 * it's up-to-date with the saved copy.
	 */
	ctx = cm_get_context(NON_SECURE);
	restore_event_ctx(disp_ctx, ctx);

	if (resume) {
		/*
		 * Complete-and-resume call. Prepare the Non-secure context
		 * (currently active) for complete and resume.
		 */
		cm_set_elr_spsr_el3(NON_SECURE, pc, SPSR_64(client_el,
					MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS));

		/*
		 * Make it look as if a synchronous exception were taken at the
		 * supplied Non-secure resumption point. Populate SPSR and
		 * ELR_ELx so that an ERET from there works as expected.
		 *
		 * The assumption is that the client, if necessary, would have
		 * saved any live content in these registers before making this
		 * call.
		 */
		if (client_el == MODE_EL2) {
			write_elr_el2(disp_ctx->elr_el3);
			write_spsr_el2(disp_ctx->spsr_el3);
		} else {
			/* EL1 */
			write_elr_el1(disp_ctx->elr_el3);
			write_spsr_el1(disp_ctx->spsr_el3);
		}
	}

	/* End the outstanding dispatch */
	end_sdei_synchronous_dispatch(disp_ctx->dispatch_jmp);

	return 0;
}

int64_t sdei_event_context(void *handle, unsigned int param)
{
	sdei_dispatch_context_t *disp_ctx;

	if (param >= SDEI_SAVED_GPREGS)
		return SDEI_EINVAL;

	/* Get outstanding dispatch on this CPU */
	disp_ctx = get_outstanding_dispatch();
	if (disp_ctx == NULL)
		return SDEI_EDENY;

	assert(disp_ctx->map != NULL);

	if (!can_sdei_state_trans(get_event_entry(disp_ctx->map), DO_CONTEXT))
		return SDEI_EDENY;

	/*
	 * No locking is required for the Running status as this is the only CPU
	 * which can complete the event
	 */

	return (int64_t) disp_ctx->x[param];
}
