Commit 51189c7a authored by Will Deacon's avatar Will Deacon

arm64: scs: Store absolute SCS stack pointer value in thread_info

Storing the SCS information in thread_info as a {base,offset} pair
introduces an additional load instruction on the ret-to-user path,
since the SCS stack pointer in x18 has to be converted back to an offset
by subtracting the base.

Replace the offset with the absolute SCS stack pointer value instead
and avoid the redundant load.
Tested-by: default avatarSami Tolvanen <samitolvanen@google.com>
Reviewed-by: default avatarMark Rutland <mark.rutland@arm.com>
Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent cc49c71d
...@@ -4,16 +4,15 @@ ...@@ -4,16 +4,15 @@
#ifdef __ASSEMBLY__ #ifdef __ASSEMBLY__
#include <asm/asm-offsets.h>
#ifdef CONFIG_SHADOW_CALL_STACK #ifdef CONFIG_SHADOW_CALL_STACK
.macro scs_load tsk, tmp .macro scs_load tsk, tmp
ldp x18, \tmp, [\tsk, #TSK_TI_SCS_BASE] ldr x18, [\tsk, #TSK_TI_SCS_SP]
add x18, x18, \tmp
.endm .endm
.macro scs_save tsk, tmp .macro scs_save tsk, tmp
ldr \tmp, [\tsk, #TSK_TI_SCS_BASE] str x18, [\tsk, #TSK_TI_SCS_SP]
sub \tmp, x18, \tmp
str \tmp, [\tsk, #TSK_TI_SCS_OFFSET]
.endm .endm
#else #else
.macro scs_load tsk, tmp .macro scs_load tsk, tmp
......
...@@ -43,7 +43,7 @@ struct thread_info { ...@@ -43,7 +43,7 @@ struct thread_info {
}; };
#ifdef CONFIG_SHADOW_CALL_STACK #ifdef CONFIG_SHADOW_CALL_STACK
void *scs_base; void *scs_base;
unsigned long scs_offset; void *scs_sp;
#endif #endif
}; };
...@@ -107,7 +107,7 @@ void arch_release_task_struct(struct task_struct *tsk); ...@@ -107,7 +107,7 @@ void arch_release_task_struct(struct task_struct *tsk);
#ifdef CONFIG_SHADOW_CALL_STACK #ifdef CONFIG_SHADOW_CALL_STACK
#define INIT_SCS \ #define INIT_SCS \
.scs_base = init_shadow_call_stack, \ .scs_base = init_shadow_call_stack, \
.scs_offset = 0, .scs_sp = init_shadow_call_stack,
#else #else
#define INIT_SCS #define INIT_SCS
#endif #endif
......
...@@ -36,7 +36,7 @@ int main(void) ...@@ -36,7 +36,7 @@ int main(void)
#endif #endif
#ifdef CONFIG_SHADOW_CALL_STACK #ifdef CONFIG_SHADOW_CALL_STACK
DEFINE(TSK_TI_SCS_BASE, offsetof(struct task_struct, thread_info.scs_base)); DEFINE(TSK_TI_SCS_BASE, offsetof(struct task_struct, thread_info.scs_base));
DEFINE(TSK_TI_SCS_OFFSET, offsetof(struct task_struct, thread_info.scs_offset)); DEFINE(TSK_TI_SCS_SP, offsetof(struct task_struct, thread_info.scs_sp));
#endif #endif
DEFINE(TSK_STACK, offsetof(struct task_struct, stack)); DEFINE(TSK_STACK, offsetof(struct task_struct, stack));
#ifdef CONFIG_STACKPROTECTOR #ifdef CONFIG_STACKPROTECTOR
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#define SCS_END_MAGIC (0x5f6UL + POISON_POINTER_DELTA) #define SCS_END_MAGIC (0x5f6UL + POISON_POINTER_DELTA)
#define task_scs(tsk) (task_thread_info(tsk)->scs_base) #define task_scs(tsk) (task_thread_info(tsk)->scs_base)
#define task_scs_offset(tsk) (task_thread_info(tsk)->scs_offset) #define task_scs_sp(tsk) (task_thread_info(tsk)->scs_sp)
void scs_init(void); void scs_init(void);
int scs_prepare(struct task_struct *tsk, int node); int scs_prepare(struct task_struct *tsk, int node);
...@@ -39,7 +39,7 @@ static inline void scs_task_reset(struct task_struct *tsk) ...@@ -39,7 +39,7 @@ static inline void scs_task_reset(struct task_struct *tsk)
* Reset the shadow stack to the base address in case the task * Reset the shadow stack to the base address in case the task
* is reused. * is reused.
*/ */
task_scs_offset(tsk) = 0; task_scs_sp(tsk) = task_scs(tsk);
} }
static inline unsigned long *__scs_magic(void *s) static inline unsigned long *__scs_magic(void *s)
...@@ -50,9 +50,9 @@ static inline unsigned long *__scs_magic(void *s) ...@@ -50,9 +50,9 @@ static inline unsigned long *__scs_magic(void *s)
static inline bool scs_corrupted(struct task_struct *tsk) static inline bool scs_corrupted(struct task_struct *tsk)
{ {
unsigned long *magic = __scs_magic(task_scs(tsk)); unsigned long *magic = __scs_magic(task_scs(tsk));
unsigned long sz = task_scs_sp(tsk) - task_scs(tsk);
return (task_scs_offset(tsk) >= SCS_SIZE - 1 || return sz >= SCS_SIZE - 1 || READ_ONCE_NOCHECK(*magic) != SCS_END_MAGIC;
READ_ONCE_NOCHECK(*magic) != SCS_END_MAGIC);
} }
#else /* CONFIG_SHADOW_CALL_STACK */ #else /* CONFIG_SHADOW_CALL_STACK */
......
...@@ -60,8 +60,7 @@ int scs_prepare(struct task_struct *tsk, int node) ...@@ -60,8 +60,7 @@ int scs_prepare(struct task_struct *tsk, int node)
if (!s) if (!s)
return -ENOMEM; return -ENOMEM;
task_scs(tsk) = s; task_scs(tsk) = task_scs_sp(tsk) = s;
task_scs_offset(tsk) = 0;
scs_account(tsk, 1); scs_account(tsk, 1);
return 0; return 0;
} }
......
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