Commit 13a695aa authored by Russell King (Oracle)'s avatar Russell King (Oracle)

Merge tag 'pr-arm32-ti-in-task' of...

Merge tag 'pr-arm32-ti-in-task' of git://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux into devel-stable

ARM: support THREAD_INFO_IN_TASK

Move thread_info off the stack and into the task struct, as is done by
many other architectures. This requires a method to find the task struct
of the task currently running on the CPU, which is provided in this case
by the user space TLS (Thread Local Storage) register. This implies that
the feature is only supported on CPUs that implement this register,
i.e., ARM v6k or later.

Kindly tested by Amit and reviewed by Linus. The first patch is against
the GCC plugins subsystem, but was reviewed by the maintainer and can be
taken through the ARM tree.
parents 6880fa6c 18ed1c01
...@@ -125,6 +125,7 @@ config ARM ...@@ -125,6 +125,7 @@ config ARM
select PERF_USE_VMALLOC select PERF_USE_VMALLOC
select RTC_LIB select RTC_LIB
select SYS_SUPPORTS_APM_EMULATION select SYS_SUPPORTS_APM_EMULATION
select THREAD_INFO_IN_TASK if CURRENT_POINTER_IN_TPIDRURO
select TRACE_IRQFLAGS_SUPPORT if !CPU_V7M select TRACE_IRQFLAGS_SUPPORT if !CPU_V7M
# Above selects are sorted alphabetically; please add new ones # Above selects are sorted alphabetically; please add new ones
# according to that. Thanks. # according to that. Thanks.
...@@ -1157,6 +1158,11 @@ config SMP_ON_UP ...@@ -1157,6 +1158,11 @@ config SMP_ON_UP
If you don't know what to do here, say Y. If you don't know what to do here, say Y.
config CURRENT_POINTER_IN_TPIDRURO
def_bool y
depends on SMP && CPU_32v6K && !CPU_V6
config ARM_CPU_TOPOLOGY config ARM_CPU_TOPOLOGY
bool "Support cpu topology definition" bool "Support cpu topology definition"
depends on SMP && CPU_V7 depends on SMP && CPU_V7
...@@ -1600,7 +1606,7 @@ config XEN ...@@ -1600,7 +1606,7 @@ config XEN
config STACKPROTECTOR_PER_TASK config STACKPROTECTOR_PER_TASK
bool "Use a unique stack canary value for each task" bool "Use a unique stack canary value for each task"
depends on GCC_PLUGINS && STACKPROTECTOR && SMP && !XIP_DEFLATED_DATA depends on GCC_PLUGINS && STACKPROTECTOR && THREAD_INFO_IN_TASK && !XIP_DEFLATED_DATA
select GCC_PLUGIN_ARM_SSP_PER_TASK select GCC_PLUGIN_ARM_SSP_PER_TASK
default y default y
help help
......
...@@ -113,6 +113,10 @@ ifeq ($(CONFIG_CC_IS_CLANG),y) ...@@ -113,6 +113,10 @@ ifeq ($(CONFIG_CC_IS_CLANG),y)
CFLAGS_ABI += -meabi gnu CFLAGS_ABI += -meabi gnu
endif endif
ifeq ($(CONFIG_CURRENT_POINTER_IN_TPIDRURO),y)
CFLAGS_ABI += -mtp=cp15
endif
# Accept old syntax despite ".syntax unified" # Accept old syntax despite ".syntax unified"
AFLAGS_NOWARN :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W) AFLAGS_NOWARN :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W)
...@@ -273,11 +277,8 @@ ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y) ...@@ -273,11 +277,8 @@ ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y)
prepare: stack_protector_prepare prepare: stack_protector_prepare
stack_protector_prepare: prepare0 stack_protector_prepare: prepare0
$(eval SSP_PLUGIN_CFLAGS := \ $(eval SSP_PLUGIN_CFLAGS := \
-fplugin-arg-arm_ssp_per_task_plugin-tso=$(shell \
awk '{if ($$2 == "THREAD_SZ_ORDER") print $$3;}'\
include/generated/asm-offsets.h) \
-fplugin-arg-arm_ssp_per_task_plugin-offset=$(shell \ -fplugin-arg-arm_ssp_per_task_plugin-offset=$(shell \
awk '{if ($$2 == "TI_STACK_CANARY") print $$3;}'\ awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}'\
include/generated/asm-offsets.h)) include/generated/asm-offsets.h))
$(eval KBUILD_CFLAGS += $(SSP_PLUGIN_CFLAGS)) $(eval KBUILD_CFLAGS += $(SSP_PLUGIN_CFLAGS))
$(eval GCC_PLUGINS_CFLAGS += $(SSP_PLUGIN_CFLAGS)) $(eval GCC_PLUGINS_CFLAGS += $(SSP_PLUGIN_CFLAGS))
......
...@@ -199,14 +199,43 @@ ...@@ -199,14 +199,43 @@
.endm .endm
.endr .endr
.macro get_current, rd
#ifdef CONFIG_CURRENT_POINTER_IN_TPIDRURO
mrc p15, 0, \rd, c13, c0, 3 @ get TPIDRURO register
#else
get_thread_info \rd
ldr \rd, [\rd, #TI_TASK]
#endif
.endm
.macro set_current, rn
#ifdef CONFIG_CURRENT_POINTER_IN_TPIDRURO
mcr p15, 0, \rn, c13, c0, 3 @ set TPIDRURO register
#endif
.endm
.macro reload_current, t1:req, t2:req
#ifdef CONFIG_CURRENT_POINTER_IN_TPIDRURO
adr_l \t1, __entry_task @ get __entry_task base address
mrc p15, 0, \t2, c13, c0, 4 @ get per-CPU offset
ldr \t1, [\t1, \t2] @ load variable
mcr p15, 0, \t1, c13, c0, 3 @ store in TPIDRURO
#endif
.endm
/* /*
* Get current thread_info. * Get current thread_info.
*/ */
.macro get_thread_info, rd .macro get_thread_info, rd
#ifdef CONFIG_THREAD_INFO_IN_TASK
/* thread_info is the first member of struct task_struct */
get_current \rd
#else
ARM( mov \rd, sp, lsr #THREAD_SIZE_ORDER + PAGE_SHIFT ) ARM( mov \rd, sp, lsr #THREAD_SIZE_ORDER + PAGE_SHIFT )
THUMB( mov \rd, sp ) THUMB( mov \rd, sp )
THUMB( lsr \rd, \rd, #THREAD_SIZE_ORDER + PAGE_SHIFT ) THUMB( lsr \rd, \rd, #THREAD_SIZE_ORDER + PAGE_SHIFT )
mov \rd, \rd, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT mov \rd, \rd, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT
#endif
.endm .endm
/* /*
......
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2021 Keith Packard <keithp@keithp.com>
* Copyright (c) 2021 Google, LLC <ardb@kernel.org>
*/
#ifndef _ASM_ARM_CURRENT_H
#define _ASM_ARM_CURRENT_H
#ifndef __ASSEMBLY__
struct task_struct;
static inline void set_current(struct task_struct *cur)
{
if (!IS_ENABLED(CONFIG_CURRENT_POINTER_IN_TPIDRURO))
return;
/* Set TPIDRURO */
asm("mcr p15, 0, %0, c13, c0, 3" :: "r"(cur) : "memory");
}
#ifdef CONFIG_CURRENT_POINTER_IN_TPIDRURO
static inline struct task_struct *get_current(void)
{
struct task_struct *cur;
#if __has_builtin(__builtin_thread_pointer)
/*
* Use the __builtin helper when available - this results in better
* code, especially when using GCC in combination with the per-task
* stack protector, as the compiler will recognize that it needs to
* load the TLS register only once in every function.
*/
cur = __builtin_thread_pointer();
#else
asm("mrc p15, 0, %0, c13, c0, 3" : "=r"(cur));
#endif
return cur;
}
#define current get_current()
#else
#include <asm-generic/current.h>
#endif /* CONFIG_CURRENT_POINTER_IN_TPIDRURO */
#endif /* __ASSEMBLY__ */
#endif /* _ASM_ARM_CURRENT_H */
...@@ -48,7 +48,7 @@ extern void set_smp_ipi_range(int ipi_base, int nr_ipi); ...@@ -48,7 +48,7 @@ extern void set_smp_ipi_range(int ipi_base, int nr_ipi);
* Called from platform specific assembly code, this is the * Called from platform specific assembly code, this is the
* secondary CPU entry point. * secondary CPU entry point.
*/ */
asmlinkage void secondary_start_kernel(void); asmlinkage void secondary_start_kernel(struct task_struct *task);
/* /*
...@@ -61,6 +61,7 @@ struct secondary_data { ...@@ -61,6 +61,7 @@ struct secondary_data {
}; };
unsigned long swapper_pg_dir; unsigned long swapper_pg_dir;
void *stack; void *stack;
struct task_struct *task;
}; };
extern struct secondary_data secondary_data; extern struct secondary_data secondary_data;
extern void secondary_startup(void); extern void secondary_startup(void);
......
...@@ -39,8 +39,6 @@ static __always_inline void boot_init_stack_canary(void) ...@@ -39,8 +39,6 @@ static __always_inline void boot_init_stack_canary(void)
current->stack_canary = canary; current->stack_canary = canary;
#ifndef CONFIG_STACKPROTECTOR_PER_TASK #ifndef CONFIG_STACKPROTECTOR_PER_TASK
__stack_chk_guard = current->stack_canary; __stack_chk_guard = current->stack_canary;
#else
current_thread_info()->stack_canary = current->stack_canary;
#endif #endif
} }
......
...@@ -23,9 +23,25 @@ ...@@ -23,9 +23,25 @@
*/ */
extern struct task_struct *__switch_to(struct task_struct *, struct thread_info *, struct thread_info *); extern struct task_struct *__switch_to(struct task_struct *, struct thread_info *, struct thread_info *);
static inline void set_ti_cpu(struct task_struct *p)
{
#ifdef CONFIG_THREAD_INFO_IN_TASK
/*
* The core code no longer maintains the thread_info::cpu field once
* CONFIG_THREAD_INFO_IN_TASK is in effect, but we rely on it for
* raw_smp_processor_id(), which cannot access struct task_struct*
* directly for reasons of circular #inclusion hell.
*/
task_thread_info(p)->cpu = task_cpu(p);
#endif
}
#define switch_to(prev,next,last) \ #define switch_to(prev,next,last) \
do { \ do { \
__complete_pending_tlbi(); \ __complete_pending_tlbi(); \
set_ti_cpu(next); \
if (IS_ENABLED(CONFIG_CURRENT_POINTER_IN_TPIDRURO)) \
__this_cpu_write(__entry_task, next); \
last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \ last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \
} while (0) } while (0)
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
struct task_struct; struct task_struct;
DECLARE_PER_CPU(struct task_struct *, __entry_task);
#include <asm/types.h> #include <asm/types.h>
struct cpu_context_save { struct cpu_context_save {
...@@ -52,12 +54,11 @@ struct cpu_context_save { ...@@ -52,12 +54,11 @@ struct cpu_context_save {
struct thread_info { struct thread_info {
unsigned long flags; /* low level flags */ unsigned long flags; /* low level flags */
int preempt_count; /* 0 => preemptable, <0 => bug */ int preempt_count; /* 0 => preemptable, <0 => bug */
#ifndef CONFIG_THREAD_INFO_IN_TASK
struct task_struct *task; /* main task structure */ struct task_struct *task; /* main task structure */
#endif
__u32 cpu; /* cpu */ __u32 cpu; /* cpu */
__u32 cpu_domain; /* cpu domain */ __u32 cpu_domain; /* cpu domain */
#ifdef CONFIG_STACKPROTECTOR_PER_TASK
unsigned long stack_canary;
#endif
struct cpu_context_save cpu_context; /* cpu context */ struct cpu_context_save cpu_context; /* cpu context */
__u32 abi_syscall; /* ABI type and syscall nr */ __u32 abi_syscall; /* ABI type and syscall nr */
__u8 used_cp[16]; /* thread used copro */ __u8 used_cp[16]; /* thread used copro */
...@@ -71,11 +72,16 @@ struct thread_info { ...@@ -71,11 +72,16 @@ struct thread_info {
#define INIT_THREAD_INFO(tsk) \ #define INIT_THREAD_INFO(tsk) \
{ \ { \
.task = &tsk, \ INIT_THREAD_INFO_TASK(tsk) \
.flags = 0, \ .flags = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \ .preempt_count = INIT_PREEMPT_COUNT, \
} }
#ifdef CONFIG_THREAD_INFO_IN_TASK
#define INIT_THREAD_INFO_TASK(tsk)
#else
#define INIT_THREAD_INFO_TASK(tsk) .task = &(tsk),
/* /*
* how to get the thread information struct from C * how to get the thread information struct from C
*/ */
...@@ -86,6 +92,7 @@ static inline struct thread_info *current_thread_info(void) ...@@ -86,6 +92,7 @@ static inline struct thread_info *current_thread_info(void)
return (struct thread_info *) return (struct thread_info *)
(current_stack_pointer & ~(THREAD_SIZE - 1)); (current_stack_pointer & ~(THREAD_SIZE - 1));
} }
#endif
#define thread_saved_pc(tsk) \ #define thread_saved_pc(tsk) \
((unsigned long)(task_thread_info(tsk)->cpu_context.pc)) ((unsigned long)(task_thread_info(tsk)->cpu_context.pc))
......
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
.macro switch_tls_v6k, base, tp, tpuser, tmp1, tmp2 .macro switch_tls_v6k, base, tp, tpuser, tmp1, tmp2
mrc p15, 0, \tmp2, c13, c0, 2 @ get the user r/w register mrc p15, 0, \tmp2, c13, c0, 2 @ get the user r/w register
mcr p15, 0, \tp, c13, c0, 3 @ set TLS register @ TLS register update is deferred until return to user space
mcr p15, 0, \tpuser, c13, c0, 2 @ and the user r/w register mcr p15, 0, \tpuser, c13, c0, 2 @ set the user r/w register
str \tmp2, [\base, #TI_TP_VALUE + 4] @ save it str \tmp2, [\base, #TI_TP_VALUE + 4] @ save it
.endm .endm
...@@ -38,18 +38,22 @@ ...@@ -38,18 +38,22 @@
#ifdef CONFIG_TLS_REG_EMUL #ifdef CONFIG_TLS_REG_EMUL
#define tls_emu 1 #define tls_emu 1
#define has_tls_reg 1 #define has_tls_reg 1
#define defer_tls_reg_update 0
#define switch_tls switch_tls_none #define switch_tls switch_tls_none
#elif defined(CONFIG_CPU_V6) #elif defined(CONFIG_CPU_V6)
#define tls_emu 0 #define tls_emu 0
#define has_tls_reg (elf_hwcap & HWCAP_TLS) #define has_tls_reg (elf_hwcap & HWCAP_TLS)
#define defer_tls_reg_update 0
#define switch_tls switch_tls_v6 #define switch_tls switch_tls_v6
#elif defined(CONFIG_CPU_32v6K) #elif defined(CONFIG_CPU_32v6K)
#define tls_emu 0 #define tls_emu 0
#define has_tls_reg 1 #define has_tls_reg 1
#define defer_tls_reg_update 1
#define switch_tls switch_tls_v6k #define switch_tls switch_tls_v6k
#else #else
#define tls_emu 0 #define tls_emu 0
#define has_tls_reg 0 #define has_tls_reg 0
#define defer_tls_reg_update 0
#define switch_tls switch_tls_software #define switch_tls switch_tls_software
#endif #endif
...@@ -77,7 +81,7 @@ static inline void set_tls(unsigned long val) ...@@ -77,7 +81,7 @@ static inline void set_tls(unsigned long val)
*/ */
barrier(); barrier();
if (!tls_emu) { if (!tls_emu && !defer_tls_reg_update) {
if (has_tls_reg) { if (has_tls_reg) {
asm("mcr p15, 0, %0, c13, c0, 3" asm("mcr p15, 0, %0, c13, c0, 3"
: : "r" (val)); : : "r" (val));
......
...@@ -43,7 +43,9 @@ int main(void) ...@@ -43,7 +43,9 @@ int main(void)
BLANK(); BLANK();
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
#ifndef CONFIG_THREAD_INFO_IN_TASK
DEFINE(TI_TASK, offsetof(struct thread_info, task)); DEFINE(TI_TASK, offsetof(struct thread_info, task));
#endif
DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain)); DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain));
DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context)); DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context));
...@@ -63,10 +65,6 @@ int main(void) ...@@ -63,10 +65,6 @@ int main(void)
#ifdef CONFIG_IWMMXT #ifdef CONFIG_IWMMXT
DEFINE(TI_IWMMXT_STATE, offsetof(struct thread_info, fpstate.iwmmxt)); DEFINE(TI_IWMMXT_STATE, offsetof(struct thread_info, fpstate.iwmmxt));
#endif #endif
#ifdef CONFIG_STACKPROTECTOR_PER_TASK
DEFINE(TI_STACK_CANARY, offsetof(struct thread_info, stack_canary));
#endif
DEFINE(THREAD_SZ_ORDER, THREAD_SIZE_ORDER);
BLANK(); BLANK();
DEFINE(S_R0, offsetof(struct pt_regs, ARM_r0)); DEFINE(S_R0, offsetof(struct pt_regs, ARM_r0));
DEFINE(S_R1, offsetof(struct pt_regs, ARM_r1)); DEFINE(S_R1, offsetof(struct pt_regs, ARM_r1));
......
...@@ -384,6 +384,8 @@ ENDPROC(__fiq_abt) ...@@ -384,6 +384,8 @@ ENDPROC(__fiq_abt)
ATRAP( teq r8, r7) ATRAP( teq r8, r7)
ATRAP( mcrne p15, 0, r8, c1, c0, 0) ATRAP( mcrne p15, 0, r8, c1, c0, 0)
reload_current r7, r8
@ @
@ Clear FP to mark the first stack frame @ Clear FP to mark the first stack frame
@ @
...@@ -762,6 +764,8 @@ ENTRY(__switch_to) ...@@ -762,6 +764,8 @@ ENTRY(__switch_to)
add r7, r7, #TSK_STACK_CANARY & ~IMM12_MASK add r7, r7, #TSK_STACK_CANARY & ~IMM12_MASK
.endif .endif
ldr r7, [r7, #TSK_STACK_CANARY & IMM12_MASK] ldr r7, [r7, #TSK_STACK_CANARY & IMM12_MASK]
#elif defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO)
mov r7, r2 @ Preserve 'next'
#endif #endif
#ifdef CONFIG_CPU_USE_DOMAINS #ifdef CONFIG_CPU_USE_DOMAINS
mcr p15, 0, r6, c3, c0, 0 @ Set domain register mcr p15, 0, r6, c3, c0, 0 @ Set domain register
...@@ -776,6 +780,7 @@ ENTRY(__switch_to) ...@@ -776,6 +780,7 @@ ENTRY(__switch_to)
#endif #endif
THUMB( mov ip, r4 ) THUMB( mov ip, r4 )
mov r0, r5 mov r0, r5
set_current r7
ARM( ldmia r4, {r4 - sl, fp, sp, pc} ) @ Load all regs saved previously ARM( ldmia r4, {r4 - sl, fp, sp, pc} ) @ Load all regs saved previously
THUMB( ldmia ip!, {r4 - sl, fp} ) @ Load all regs saved previously THUMB( ldmia ip!, {r4 - sl, fp} ) @ Load all regs saved previously
THUMB( ldr sp, [ip], #4 ) THUMB( ldr sp, [ip], #4 )
......
...@@ -170,6 +170,7 @@ ENTRY(vector_swi) ...@@ -170,6 +170,7 @@ ENTRY(vector_swi)
str saved_psr, [sp, #S_PSR] @ Save CPSR str saved_psr, [sp, #S_PSR] @ Save CPSR
str r0, [sp, #S_OLD_R0] @ Save OLD_R0 str r0, [sp, #S_OLD_R0] @ Save OLD_R0
#endif #endif
reload_current r10, ip
zero_fp zero_fp
alignment_trap r10, ip, __cr_alignment alignment_trap r10, ip, __cr_alignment
asm_trace_hardirqs_on save=0 asm_trace_hardirqs_on save=0
......
...@@ -292,6 +292,14 @@ ...@@ -292,6 +292,14 @@
.macro restore_user_regs, fast = 0, offset = 0 .macro restore_user_regs, fast = 0, offset = 0
#if defined(CONFIG_CPU_32v6K) && !defined(CONFIG_CPU_V6)
@ The TLS register update is deferred until return to user space so we
@ can use it for other things while running in the kernel
get_thread_info r1
ldr r1, [r1, #TI_TP_VALUE]
mcr p15, 0, r1, c13, c0, 3 @ set TLS register
#endif
uaccess_enable r1, isb=0 uaccess_enable r1, isb=0
#ifndef CONFIG_THUMB2_KERNEL #ifndef CONFIG_THUMB2_KERNEL
@ ARM mode restore @ ARM mode restore
......
...@@ -105,6 +105,11 @@ __mmap_switched: ...@@ -105,6 +105,11 @@ __mmap_switched:
mov r1, #0 mov r1, #0
bl __memset @ clear .bss bl __memset @ clear .bss
#ifdef CONFIG_CURRENT_POINTER_IN_TPIDRURO
adr_l r0, init_task @ get swapper task_struct
set_current r0
#endif
ldmia r4, {r0, r1, r2, r3} ldmia r4, {r0, r1, r2, r3}
str r9, [r0] @ Save processor ID str r9, [r0] @ Save processor ID
str r7, [r1] @ Save machine type str r7, [r1] @ Save machine type
......
...@@ -115,6 +115,7 @@ ENTRY(secondary_startup) ...@@ -115,6 +115,7 @@ ENTRY(secondary_startup)
ret r12 ret r12
1: bl __after_proc_init 1: bl __after_proc_init
ldr sp, [r7, #12] @ set up the stack pointer ldr sp, [r7, #12] @ set up the stack pointer
ldr r0, [r7, #16] @ set up task pointer
mov fp, #0 mov fp, #0
b secondary_start_kernel b secondary_start_kernel
ENDPROC(secondary_startup) ENDPROC(secondary_startup)
......
...@@ -424,8 +424,9 @@ ENDPROC(secondary_startup) ...@@ -424,8 +424,9 @@ ENDPROC(secondary_startup)
ENDPROC(secondary_startup_arm) ENDPROC(secondary_startup_arm)
ENTRY(__secondary_switched) ENTRY(__secondary_switched)
ldr_l r7, secondary_data + 12 @ get secondary_data.stack adr_l r7, secondary_data + 12 @ get secondary_data.stack
mov sp, r7 ldr sp, [r7]
ldr r0, [r7, #4] @ get secondary_data.task
mov fp, #0 mov fp, #0
b secondary_start_kernel b secondary_start_kernel
ENDPROC(__secondary_switched) ENDPROC(__secondary_switched)
......
...@@ -36,6 +36,10 @@ ...@@ -36,6 +36,10 @@
#include "signal.h" #include "signal.h"
#ifdef CONFIG_CURRENT_POINTER_IN_TPIDRURO
DEFINE_PER_CPU(struct task_struct *, __entry_task);
#endif
#if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_STACKPROTECTOR_PER_TASK) #if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_STACKPROTECTOR_PER_TASK)
#include <linux/stackprotector.h> #include <linux/stackprotector.h>
unsigned long __stack_chk_guard __read_mostly; unsigned long __stack_chk_guard __read_mostly;
...@@ -269,10 +273,6 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start, ...@@ -269,10 +273,6 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
thread_notify(THREAD_NOTIFY_COPY, thread); thread_notify(THREAD_NOTIFY_COPY, thread);
#ifdef CONFIG_STACKPROTECTOR_PER_TASK
thread->stack_canary = p->stack_canary;
#endif
return 0; return 0;
} }
......
...@@ -153,6 +153,10 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) ...@@ -153,6 +153,10 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
secondary_data.pgdir = virt_to_phys(idmap_pgd); secondary_data.pgdir = virt_to_phys(idmap_pgd);
secondary_data.swapper_pg_dir = get_arch_pgd(swapper_pg_dir); secondary_data.swapper_pg_dir = get_arch_pgd(swapper_pg_dir);
#endif #endif
secondary_data.task = idle;
if (IS_ENABLED(CONFIG_THREAD_INFO_IN_TASK))
task_thread_info(idle)->cpu = cpu;
sync_cache_w(&secondary_data); sync_cache_w(&secondary_data);
/* /*
...@@ -375,9 +379,12 @@ void arch_cpu_idle_dead(void) ...@@ -375,9 +379,12 @@ void arch_cpu_idle_dead(void)
*/ */
__asm__("mov sp, %0\n" __asm__("mov sp, %0\n"
" mov fp, #0\n" " mov fp, #0\n"
" mov r0, %1\n"
" b secondary_start_kernel" " b secondary_start_kernel"
: :
: "r" (task_stack_page(current) + THREAD_SIZE - 8)); : "r" (task_stack_page(current) + THREAD_SIZE - 8),
"r" (current)
: "r0");
} }
#endif /* CONFIG_HOTPLUG_CPU */ #endif /* CONFIG_HOTPLUG_CPU */
...@@ -400,11 +407,13 @@ static void smp_store_cpu_info(unsigned int cpuid) ...@@ -400,11 +407,13 @@ static void smp_store_cpu_info(unsigned int cpuid)
* This is the secondary CPU boot entry. We're using this CPUs * This is the secondary CPU boot entry. We're using this CPUs
* idle thread stack, but a set of temporary page tables. * idle thread stack, but a set of temporary page tables.
*/ */
asmlinkage void secondary_start_kernel(void) asmlinkage void secondary_start_kernel(struct task_struct *task)
{ {
struct mm_struct *mm = &init_mm; struct mm_struct *mm = &init_mm;
unsigned int cpu; unsigned int cpu;
set_current(task);
secondary_biglittle_init(); secondary_biglittle_init();
/* /*
......
...@@ -30,8 +30,7 @@ ...@@ -30,8 +30,7 @@
* act_mm - get current->active_mm * act_mm - get current->active_mm
*/ */
.macro act_mm, rd .macro act_mm, rd
get_thread_info \rd get_current \rd
ldr \rd, [\rd, #TI_TASK]
.if (TSK_ACTIVE_MM > IMM12_MASK) .if (TSK_ACTIVE_MM > IMM12_MASK)
add \rd, \rd, #TSK_ACTIVE_MM & ~IMM12_MASK add \rd, \rd, #TSK_ACTIVE_MM & ~IMM12_MASK
.endif .endif
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
__visible int plugin_is_GPL_compatible; __visible int plugin_is_GPL_compatible;
static unsigned int sp_mask, canary_offset; static unsigned int canary_offset;
static unsigned int arm_pertask_ssp_rtl_execute(void) static unsigned int arm_pertask_ssp_rtl_execute(void)
{ {
...@@ -13,7 +13,7 @@ static unsigned int arm_pertask_ssp_rtl_execute(void) ...@@ -13,7 +13,7 @@ static unsigned int arm_pertask_ssp_rtl_execute(void)
for (insn = get_insns(); insn; insn = NEXT_INSN(insn)) { for (insn = get_insns(); insn; insn = NEXT_INSN(insn)) {
const char *sym; const char *sym;
rtx body; rtx body;
rtx mask, masked_sp; rtx current;
/* /*
* Find a SET insn involving a SYMBOL_REF to __stack_chk_guard * Find a SET insn involving a SYMBOL_REF to __stack_chk_guard
...@@ -30,19 +30,13 @@ static unsigned int arm_pertask_ssp_rtl_execute(void) ...@@ -30,19 +30,13 @@ static unsigned int arm_pertask_ssp_rtl_execute(void)
/* /*
* Replace the source of the SET insn with an expression that * Replace the source of the SET insn with an expression that
* produces the address of the copy of the stack canary value * produces the address of the current task's stack canary value
* stored in struct thread_info
*/ */
mask = GEN_INT(sext_hwi(sp_mask, GET_MODE_PRECISION(Pmode))); current = gen_reg_rtx(Pmode);
masked_sp = gen_reg_rtx(Pmode);
emit_insn_before(gen_rtx_set(masked_sp, emit_insn_before(gen_load_tp_hard(current), insn);
gen_rtx_AND(Pmode,
stack_pointer_rtx,
mask)),
insn);
SET_SRC(body) = gen_rtx_PLUS(Pmode, masked_sp, SET_SRC(body) = gen_rtx_PLUS(Pmode, current,
GEN_INT(canary_offset)); GEN_INT(canary_offset));
} }
return 0; return 0;
...@@ -72,7 +66,6 @@ __visible int plugin_init(struct plugin_name_args *plugin_info, ...@@ -72,7 +66,6 @@ __visible int plugin_init(struct plugin_name_args *plugin_info,
const char * const plugin_name = plugin_info->base_name; const char * const plugin_name = plugin_info->base_name;
const int argc = plugin_info->argc; const int argc = plugin_info->argc;
const struct plugin_argument *argv = plugin_info->argv; const struct plugin_argument *argv = plugin_info->argv;
int tso = 0;
int i; int i;
if (!plugin_default_version_check(version, &gcc_version)) { if (!plugin_default_version_check(version, &gcc_version)) {
...@@ -91,11 +84,6 @@ __visible int plugin_init(struct plugin_name_args *plugin_info, ...@@ -91,11 +84,6 @@ __visible int plugin_init(struct plugin_name_args *plugin_info,
return 1; return 1;
} }
if (!strcmp(argv[i].key, "tso")) {
tso = atoi(argv[i].value);
continue;
}
if (!strcmp(argv[i].key, "offset")) { if (!strcmp(argv[i].key, "offset")) {
canary_offset = atoi(argv[i].value); canary_offset = atoi(argv[i].value);
continue; continue;
...@@ -105,9 +93,6 @@ __visible int plugin_init(struct plugin_name_args *plugin_info, ...@@ -105,9 +93,6 @@ __visible int plugin_init(struct plugin_name_args *plugin_info,
return 1; return 1;
} }
/* create the mask that produces the base of the stack */
sp_mask = ~((1U << (12 + tso)) - 1);
PASS_INFO(arm_pertask_ssp_rtl, "expand", 1, PASS_POS_INSERT_AFTER); PASS_INFO(arm_pertask_ssp_rtl, "expand", 1, PASS_POS_INSERT_AFTER);
register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP, register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP,
......
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