2018-01-08 15:38:09 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
// Copyright (C) 2017 Arm Ltd.
|
|
|
|
#ifndef __ASM_SDEI_H
|
|
|
|
#define __ASM_SDEI_H
|
|
|
|
|
arm64: kernel: Add arch-specific SDEI entry code and CPU masking
The Software Delegated Exception Interface (SDEI) is an ARM standard
for registering callbacks from the platform firmware into the OS.
This is typically used to implement RAS notifications.
Such notifications enter the kernel at the registered entry-point
with the register values of the interrupted CPU context. Because this
is not a CPU exception, it cannot reuse the existing entry code.
(crucially we don't implicitly know which exception level we interrupted),
Add the entry point to entry.S to set us up for calling into C code. If
the event interrupted code that had interrupts masked, we always return
to that location. Otherwise we pretend this was an IRQ, and use SDEI's
complete_and_resume call to return to vbar_el1 + offset.
This allows the kernel to deliver signals to user space processes. For
KVM this triggers the world switch, a quick spin round vcpu_run, then
back into the guest, unless there are pending signals.
Add sdei_mask_local_cpu() calls to the smp_send_stop() code, this covers
the panic() code-path, which doesn't invoke cpuhotplug notifiers.
Because we can interrupt entry-from/exit-to another EL, we can't trust the
value in sp_el0 or x29, even if we interrupted the kernel, in this case
the code in entry.S will save/restore sp_el0 and use the value in
__entry_task.
When we have VMAP stacks we can interrupt the stack-overflow test, which
stirs x0 into sp, meaning we have to have our own VMAP stacks. For now
these are allocated when we probe the interface. Future patches will add
refcounting hooks to allow the arch code to allocate them lazily.
Signed-off-by: James Morse <james.morse@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2018-01-08 15:38:12 +00:00
|
|
|
/* Values for sdei_exit_mode */
|
|
|
|
#define SDEI_EXIT_HVC 0
|
|
|
|
#define SDEI_EXIT_SMC 1
|
2018-01-08 15:38:09 +00:00
|
|
|
|
arm64: kernel: Add arch-specific SDEI entry code and CPU masking
The Software Delegated Exception Interface (SDEI) is an ARM standard
for registering callbacks from the platform firmware into the OS.
This is typically used to implement RAS notifications.
Such notifications enter the kernel at the registered entry-point
with the register values of the interrupted CPU context. Because this
is not a CPU exception, it cannot reuse the existing entry code.
(crucially we don't implicitly know which exception level we interrupted),
Add the entry point to entry.S to set us up for calling into C code. If
the event interrupted code that had interrupts masked, we always return
to that location. Otherwise we pretend this was an IRQ, and use SDEI's
complete_and_resume call to return to vbar_el1 + offset.
This allows the kernel to deliver signals to user space processes. For
KVM this triggers the world switch, a quick spin round vcpu_run, then
back into the guest, unless there are pending signals.
Add sdei_mask_local_cpu() calls to the smp_send_stop() code, this covers
the panic() code-path, which doesn't invoke cpuhotplug notifiers.
Because we can interrupt entry-from/exit-to another EL, we can't trust the
value in sp_el0 or x29, even if we interrupted the kernel, in this case
the code in entry.S will save/restore sp_el0 and use the value in
__entry_task.
When we have VMAP stacks we can interrupt the stack-overflow test, which
stirs x0 into sp, meaning we have to have our own VMAP stacks. For now
these are allocated when we probe the interface. Future patches will add
refcounting hooks to allow the arch code to allocate them lazily.
Signed-off-by: James Morse <james.morse@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2018-01-08 15:38:12 +00:00
|
|
|
#define SDEI_STACK_SIZE IRQ_STACK_SIZE
|
|
|
|
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
|
|
|
|
#include <linux/linkage.h>
|
|
|
|
#include <linux/preempt.h>
|
|
|
|
#include <linux/types.h>
|
|
|
|
|
|
|
|
#include <asm/virt.h>
|
|
|
|
|
|
|
|
extern unsigned long sdei_exit_mode;
|
|
|
|
|
|
|
|
/* Software Delegated Exception entry point from firmware*/
|
|
|
|
asmlinkage void __sdei_asm_handler(unsigned long event_num, unsigned long arg,
|
|
|
|
unsigned long pc, unsigned long pstate);
|
|
|
|
|
2018-01-08 15:38:18 +00:00
|
|
|
/* and its CONFIG_UNMAP_KERNEL_AT_EL0 trampoline */
|
|
|
|
asmlinkage void __sdei_asm_entry_trampoline(unsigned long event_num,
|
|
|
|
unsigned long arg,
|
|
|
|
unsigned long pc,
|
|
|
|
unsigned long pstate);
|
|
|
|
|
arm64: kernel: Add arch-specific SDEI entry code and CPU masking
The Software Delegated Exception Interface (SDEI) is an ARM standard
for registering callbacks from the platform firmware into the OS.
This is typically used to implement RAS notifications.
Such notifications enter the kernel at the registered entry-point
with the register values of the interrupted CPU context. Because this
is not a CPU exception, it cannot reuse the existing entry code.
(crucially we don't implicitly know which exception level we interrupted),
Add the entry point to entry.S to set us up for calling into C code. If
the event interrupted code that had interrupts masked, we always return
to that location. Otherwise we pretend this was an IRQ, and use SDEI's
complete_and_resume call to return to vbar_el1 + offset.
This allows the kernel to deliver signals to user space processes. For
KVM this triggers the world switch, a quick spin round vcpu_run, then
back into the guest, unless there are pending signals.
Add sdei_mask_local_cpu() calls to the smp_send_stop() code, this covers
the panic() code-path, which doesn't invoke cpuhotplug notifiers.
Because we can interrupt entry-from/exit-to another EL, we can't trust the
value in sp_el0 or x29, even if we interrupted the kernel, in this case
the code in entry.S will save/restore sp_el0 and use the value in
__entry_task.
When we have VMAP stacks we can interrupt the stack-overflow test, which
stirs x0 into sp, meaning we have to have our own VMAP stacks. For now
these are allocated when we probe the interface. Future patches will add
refcounting hooks to allow the arch code to allocate them lazily.
Signed-off-by: James Morse <james.morse@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2018-01-08 15:38:12 +00:00
|
|
|
/*
|
|
|
|
* The above entry point does the minimum to call C code. This function does
|
|
|
|
* anything else, before calling the driver.
|
|
|
|
*/
|
|
|
|
struct sdei_registered_event;
|
|
|
|
asmlinkage unsigned long __sdei_handler(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)
|
|
|
|
|
|
|
|
bool _on_sdei_stack(unsigned long sp);
|
|
|
|
static inline bool on_sdei_stack(unsigned long sp)
|
|
|
|
{
|
|
|
|
if (!IS_ENABLED(CONFIG_VMAP_STACK))
|
|
|
|
return false;
|
|
|
|
if (!IS_ENABLED(CONFIG_ARM_SDE_INTERFACE))
|
|
|
|
return false;
|
|
|
|
if (in_nmi())
|
|
|
|
return _on_sdei_stack(sp);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* __ASSEMBLY__ */
|
|
|
|
#endif /* __ASM_SDEI_H */
|