Skip to content

Commit 51189c7

Browse files
committed
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: Sami Tolvanen <[email protected]> Reviewed-by: Mark Rutland <[email protected]> Signed-off-by: Will Deacon <[email protected]>
1 parent cc49c71 commit 51189c7

File tree

5 files changed

+12
-14
lines changed

5 files changed

+12
-14
lines changed

arch/arm64/include/asm/scs.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,15 @@
44

55
#ifdef __ASSEMBLY__
66

7+
#include <asm/asm-offsets.h>
8+
79
#ifdef CONFIG_SHADOW_CALL_STACK
810
.macro scs_load tsk, tmp
9-
ldp x18, \tmp, [\tsk, #TSK_TI_SCS_BASE]
10-
add x18, x18, \tmp
11+
ldr x18, [\tsk, #TSK_TI_SCS_SP]
1112
.endm
1213

1314
.macro scs_save tsk, tmp
14-
ldr \tmp, [\tsk, #TSK_TI_SCS_BASE]
15-
sub \tmp, x18, \tmp
16-
str \tmp, [\tsk, #TSK_TI_SCS_OFFSET]
15+
str x18, [\tsk, #TSK_TI_SCS_SP]
1716
.endm
1817
#else
1918
.macro scs_load tsk, tmp

arch/arm64/include/asm/thread_info.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ struct thread_info {
4343
};
4444
#ifdef CONFIG_SHADOW_CALL_STACK
4545
void *scs_base;
46-
unsigned long scs_offset;
46+
void *scs_sp;
4747
#endif
4848
};
4949

@@ -107,7 +107,7 @@ void arch_release_task_struct(struct task_struct *tsk);
107107
#ifdef CONFIG_SHADOW_CALL_STACK
108108
#define INIT_SCS \
109109
.scs_base = init_shadow_call_stack, \
110-
.scs_offset = 0,
110+
.scs_sp = init_shadow_call_stack,
111111
#else
112112
#define INIT_SCS
113113
#endif

arch/arm64/kernel/asm-offsets.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ int main(void)
3636
#endif
3737
#ifdef CONFIG_SHADOW_CALL_STACK
3838
DEFINE(TSK_TI_SCS_BASE, offsetof(struct task_struct, thread_info.scs_base));
39-
DEFINE(TSK_TI_SCS_OFFSET, offsetof(struct task_struct, thread_info.scs_offset));
39+
DEFINE(TSK_TI_SCS_SP, offsetof(struct task_struct, thread_info.scs_sp));
4040
#endif
4141
DEFINE(TSK_STACK, offsetof(struct task_struct, stack));
4242
#ifdef CONFIG_STACKPROTECTOR

include/linux/scs.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
#define SCS_END_MAGIC (0x5f6UL + POISON_POINTER_DELTA)
2828

2929
#define task_scs(tsk) (task_thread_info(tsk)->scs_base)
30-
#define task_scs_offset(tsk) (task_thread_info(tsk)->scs_offset)
30+
#define task_scs_sp(tsk) (task_thread_info(tsk)->scs_sp)
3131

3232
void scs_init(void);
3333
int scs_prepare(struct task_struct *tsk, int node);
@@ -39,7 +39,7 @@ static inline void scs_task_reset(struct task_struct *tsk)
3939
* Reset the shadow stack to the base address in case the task
4040
* is reused.
4141
*/
42-
task_scs_offset(tsk) = 0;
42+
task_scs_sp(tsk) = task_scs(tsk);
4343
}
4444

4545
static inline unsigned long *__scs_magic(void *s)
@@ -50,9 +50,9 @@ static inline unsigned long *__scs_magic(void *s)
5050
static inline bool scs_corrupted(struct task_struct *tsk)
5151
{
5252
unsigned long *magic = __scs_magic(task_scs(tsk));
53+
unsigned long sz = task_scs_sp(tsk) - task_scs(tsk);
5354

54-
return (task_scs_offset(tsk) >= SCS_SIZE - 1 ||
55-
READ_ONCE_NOCHECK(*magic) != SCS_END_MAGIC);
55+
return sz >= SCS_SIZE - 1 || READ_ONCE_NOCHECK(*magic) != SCS_END_MAGIC;
5656
}
5757

5858
#else /* CONFIG_SHADOW_CALL_STACK */

kernel/scs.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ int scs_prepare(struct task_struct *tsk, int node)
6060
if (!s)
6161
return -ENOMEM;
6262

63-
task_scs(tsk) = s;
64-
task_scs_offset(tsk) = 0;
63+
task_scs(tsk) = task_scs_sp(tsk) = s;
6564
scs_account(tsk, 1);
6665
return 0;
6766
}

0 commit comments

Comments
 (0)