Commit 8e3032f9 authored by Jeenu Viswambharan's avatar Jeenu Viswambharan
Browse files

SDEI: Pop dispatch context only after error checking



Currently, when the client attempts to do SDEI_EVENT_COMPLETE or
SDEI_EVENT_COMPLETE_AND_RESUME, the dispatcher pops off the outstanding
dispatch context for sanity check. There are however other checks
following this, which could potentially return failure. If that happens,
by popping the context, the dispatcher has inadvertently discarded a
valid context.

This patch fixes this bug by inspecting (not actually popping) the
outstanding context. The context is popped only after all error checks
are completed.

Change-Id: Ie199f6442f871a8177a8247a0c646543bad76d21
Signed-off-by: default avatarJeenu Viswambharan <jeenu.viswambharan@arm.com>
parent 5ff6da94
/* /*
* 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 * SPDX-License-Identifier: BSD-3-Clause
*/ */
...@@ -556,7 +556,7 @@ int sdei_event_complete(int resume, uint64_t pc) ...@@ -556,7 +556,7 @@ int sdei_event_complete(int resume, uint64_t pc)
unsigned int client_el = sdei_client_el(); unsigned int client_el = sdei_client_el();
/* Return error if called without an active event */ /* Return error if called without an active event */
disp_ctx = pop_dispatch(); disp_ctx = get_outstanding_dispatch();
if (!disp_ctx) if (!disp_ctx)
return SDEI_EDENY; return SDEI_EDENY;
...@@ -566,15 +566,8 @@ int sdei_event_complete(int resume, uint64_t pc) ...@@ -566,15 +566,8 @@ int sdei_event_complete(int resume, uint64_t pc)
map = disp_ctx->map; map = disp_ctx->map;
assert(map); assert(map);
se = get_event_entry(map); se = get_event_entry(map);
SDEI_LOG("EOI:%lx, %d spsr:%lx elr:%lx\n", read_mpidr_el1(),
map->ev_num, read_spsr_el3(), read_elr_el3());
if (is_event_shared(map))
sdei_map_lock(map);
act = resume ? DO_COMPLETE_RESUME : DO_COMPLETE; act = resume ? DO_COMPLETE_RESUME : DO_COMPLETE;
if (!can_sdei_state_trans(se, act)) { if (!can_sdei_state_trans(se, act)) {
if (is_event_shared(map)) if (is_event_shared(map))
...@@ -582,6 +575,15 @@ int sdei_event_complete(int resume, uint64_t pc) ...@@ -582,6 +575,15 @@ int sdei_event_complete(int resume, uint64_t pc)
return SDEI_EDENY; return SDEI_EDENY;
} }
/* Having done sanity checks, pop dispatch */
pop_dispatch();
SDEI_LOG("EOI:%lx, %d spsr:%lx elr:%lx\n", read_mpidr_el1(),
map->ev_num, read_spsr_el3(), read_elr_el3());
if (is_event_shared(map))
sdei_map_lock(map);
/* /*
* Restore Non-secure to how it was originally interrupted. Once done, * Restore Non-secure to how it was originally interrupted. Once done,
* it's up-to-date with the saved copy. * it's up-to-date with the saved copy.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment