mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 23:22:31 +02:00
arm64: entry: split SDEI entry
We'd like to keep all the entry sequencing in entry-common.c, as this
will allow us to ensure this is consistent, and free from any unsound
instrumentation.
Currently __sdei_handler() performs the NMI entry/exit sequences in
sdei.c. Let's split the low-level entry sequence from the event
handling, moving the former to entry-common.c and keeping the latter in
sdei.c. The event handling function is renamed to do_sdei_event(),
matching the do_${FOO}() pattern used for other exception handlers.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: Joey Gouly <joey.gouly@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20210607094624.34689-18-mark.rutland@arm.com
Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
parent
8168f09886
commit
d60b228fd1
|
|
@ -37,6 +37,9 @@ struct sdei_registered_event;
|
|||
asmlinkage unsigned long __sdei_handler(struct pt_regs *regs,
|
||||
struct sdei_registered_event *arg);
|
||||
|
||||
unsigned long do_sdei_event(struct pt_regs *regs,
|
||||
struct sdei_registered_event *arg);
|
||||
|
||||
unsigned long sdei_arch_get_entry_point(int conduit);
|
||||
#define sdei_arch_get_entry_point(x) sdei_arch_get_entry_point(x)
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include <asm/kprobes.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/sdei.h>
|
||||
#include <asm/stacktrace.h>
|
||||
#include <asm/sysreg.h>
|
||||
#include <asm/system_misc.h>
|
||||
|
|
@ -710,3 +711,39 @@ asmlinkage void noinstr handle_bad_stack(struct pt_regs *regs)
|
|||
panic_bad_stack(regs, esr, far);
|
||||
}
|
||||
#endif /* CONFIG_VMAP_STACK */
|
||||
|
||||
#ifdef CONFIG_ARM_SDE_INTERFACE
|
||||
asmlinkage noinstr unsigned long
|
||||
__sdei_handler(struct pt_regs *regs, struct sdei_registered_event *arg)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
/*
|
||||
* We didn't take an exception to get here, so the HW hasn't
|
||||
* set/cleared bits in PSTATE that we may rely on.
|
||||
*
|
||||
* The original SDEI spec (ARM DEN 0054A) can be read ambiguously as to
|
||||
* whether PSTATE bits are inherited unchanged or generated from
|
||||
* scratch, and the TF-A implementation always clears PAN and always
|
||||
* clears UAO. There are no other known implementations.
|
||||
*
|
||||
* Subsequent revisions (ARM DEN 0054B) follow the usual rules for how
|
||||
* PSTATE is modified upon architectural exceptions, and so PAN is
|
||||
* either inherited or set per SCTLR_ELx.SPAN, and UAO is always
|
||||
* cleared.
|
||||
*
|
||||
* We must explicitly reset PAN to the expected state, including
|
||||
* clearing it when the host isn't using it, in case a VM had it set.
|
||||
*/
|
||||
if (system_uses_hw_pan())
|
||||
set_pstate_pan(1);
|
||||
else if (cpu_has_pan())
|
||||
set_pstate_pan(0);
|
||||
|
||||
arm64_enter_nmi(regs);
|
||||
ret = do_sdei_event(regs, arg);
|
||||
arm64_exit_nmi(regs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_ARM_SDE_INTERFACE */
|
||||
|
|
|
|||
|
|
@ -231,13 +231,13 @@ unsigned long sdei_arch_get_entry_point(int conduit)
|
|||
}
|
||||
|
||||
/*
|
||||
* __sdei_handler() returns one of:
|
||||
* do_sdei_event() returns one of:
|
||||
* SDEI_EV_HANDLED - success, return to the interrupted context.
|
||||
* SDEI_EV_FAILED - failure, return this error code to firmare.
|
||||
* virtual-address - success, return to this address.
|
||||
*/
|
||||
static __kprobes unsigned long _sdei_handler(struct pt_regs *regs,
|
||||
struct sdei_registered_event *arg)
|
||||
unsigned long __kprobes do_sdei_event(struct pt_regs *regs,
|
||||
struct sdei_registered_event *arg)
|
||||
{
|
||||
u32 mode;
|
||||
int i, err = 0;
|
||||
|
|
@ -292,45 +292,3 @@ static __kprobes unsigned long _sdei_handler(struct pt_regs *regs,
|
|||
|
||||
return vbar + 0x480;
|
||||
}
|
||||
|
||||
static void __kprobes notrace __sdei_pstate_entry(void)
|
||||
{
|
||||
/*
|
||||
* The original SDEI spec (ARM DEN 0054A) can be read ambiguously as to
|
||||
* whether PSTATE bits are inherited unchanged or generated from
|
||||
* scratch, and the TF-A implementation always clears PAN and always
|
||||
* clears UAO. There are no other known implementations.
|
||||
*
|
||||
* Subsequent revisions (ARM DEN 0054B) follow the usual rules for how
|
||||
* PSTATE is modified upon architectural exceptions, and so PAN is
|
||||
* either inherited or set per SCTLR_ELx.SPAN, and UAO is always
|
||||
* cleared.
|
||||
*
|
||||
* We must explicitly reset PAN to the expected state, including
|
||||
* clearing it when the host isn't using it, in case a VM had it set.
|
||||
*/
|
||||
if (system_uses_hw_pan())
|
||||
set_pstate_pan(1);
|
||||
else if (cpu_has_pan())
|
||||
set_pstate_pan(0);
|
||||
}
|
||||
|
||||
asmlinkage noinstr unsigned long
|
||||
__sdei_handler(struct pt_regs *regs, struct sdei_registered_event *arg)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
/*
|
||||
* We didn't take an exception to get here, so the HW hasn't
|
||||
* set/cleared bits in PSTATE that we may rely on. Initialize PAN.
|
||||
*/
|
||||
__sdei_pstate_entry();
|
||||
|
||||
arm64_enter_nmi(regs);
|
||||
|
||||
ret = _sdei_handler(regs, arg);
|
||||
|
||||
arm64_exit_nmi(regs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user