mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 10:33:41 +02:00
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. -----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE+9lifEBpyUIVN1cpw08iOZLZjyQFAmFR3FQACgkQw08iOZLZ jySeZQwAoeDNTyw6YEZO1A8zhvzv0o3tuq2ifWTK2p8P6sJ9dbbghCN1wZtaYhcz YM7rDHGRlu9wT1ad/fYEsZTRnZ6/RlrKoJKF8921mXIMBRHPC4KXDJwsXxvZAjS8 MB4FEPPN80H3MLIR4d16NBlVjcXuQ+J5+mBMcFRIP2zSdOTFkgS7yCP8dy+ryDLe TDJvh/N7ig6DszEEKo7uLIRSt2MIYN7rHPVuKxDDHgKLq/bYDxh+qHprXwhtnxWw CGlUmOXBSFuSMyAQ1WHr4ZDyHolfL89U++a+ZH/TQB38PY/2bCCdUbx5np7q7Jv5 n/eL5Up70+gx9FH7XIAXRpPKJzrQEn0vrQLKBsOLqBNX1lXH1I/IE+GavfRLXbkV 9ZEo1hj/v1DiLQdrCuoxMFwXZryQ5/KQfolFEjPKS6bbqStAO1S3jrEQtzt2JGo3 PW5UA0ZQC1nwc/l9GoG/AEm1QV4aHxKqLdFQV0L/ZBN0KOL+xsJYb7dm8mIhLzzh xGWDOD7a =fGHe -----END PGP SIGNATURE----- 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.
This commit is contained in:
commit
13a695aa50
|
|
@ -125,6 +125,7 @@ config ARM
|
|||
select PERF_USE_VMALLOC
|
||||
select RTC_LIB
|
||||
select SYS_SUPPORTS_APM_EMULATION
|
||||
select THREAD_INFO_IN_TASK if CURRENT_POINTER_IN_TPIDRURO
|
||||
select TRACE_IRQFLAGS_SUPPORT if !CPU_V7M
|
||||
# Above selects are sorted alphabetically; please add new ones
|
||||
# according to that. Thanks.
|
||||
|
|
@ -1157,6 +1158,11 @@ config SMP_ON_UP
|
|||
|
||||
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
|
||||
bool "Support cpu topology definition"
|
||||
depends on SMP && CPU_V7
|
||||
|
|
@ -1600,7 +1606,7 @@ config XEN
|
|||
|
||||
config STACKPROTECTOR_PER_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
|
||||
default y
|
||||
help
|
||||
|
|
|
|||
|
|
@ -113,6 +113,10 @@ ifeq ($(CONFIG_CC_IS_CLANG),y)
|
|||
CFLAGS_ABI += -meabi gnu
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CURRENT_POINTER_IN_TPIDRURO),y)
|
||||
CFLAGS_ABI += -mtp=cp15
|
||||
endif
|
||||
|
||||
# Accept old syntax despite ".syntax unified"
|
||||
AFLAGS_NOWARN :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W)
|
||||
|
||||
|
|
@ -273,11 +277,8 @@ ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y)
|
|||
prepare: stack_protector_prepare
|
||||
stack_protector_prepare: prepare0
|
||||
$(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 \
|
||||
awk '{if ($$2 == "TI_STACK_CANARY") print $$3;}'\
|
||||
awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}'\
|
||||
include/generated/asm-offsets.h))
|
||||
$(eval KBUILD_CFLAGS += $(SSP_PLUGIN_CFLAGS))
|
||||
$(eval GCC_PLUGINS_CFLAGS += $(SSP_PLUGIN_CFLAGS))
|
||||
|
|
|
|||
|
|
@ -199,14 +199,43 @@
|
|||
.endm
|
||||
.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.
|
||||
*/
|
||||
.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 )
|
||||
THUMB( mov \rd, sp )
|
||||
THUMB( lsr \rd, \rd, #THREAD_SIZE_ORDER + PAGE_SHIFT )
|
||||
mov \rd, \rd, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
|
|
|
|||
50
arch/arm/include/asm/current.h
Normal file
50
arch/arm/include/asm/current.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/* 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);
|
|||
* Called from platform specific assembly code, this is the
|
||||
* 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 {
|
|||
};
|
||||
unsigned long swapper_pg_dir;
|
||||
void *stack;
|
||||
struct task_struct *task;
|
||||
};
|
||||
extern struct secondary_data secondary_data;
|
||||
extern void secondary_startup(void);
|
||||
|
|
|
|||
|
|
@ -39,8 +39,6 @@ static __always_inline void boot_init_stack_canary(void)
|
|||
current->stack_canary = canary;
|
||||
#ifndef CONFIG_STACKPROTECTOR_PER_TASK
|
||||
__stack_chk_guard = current->stack_canary;
|
||||
#else
|
||||
current_thread_info()->stack_canary = current->stack_canary;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,9 +23,25 @@
|
|||
*/
|
||||
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) \
|
||||
do { \
|
||||
__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)); \
|
||||
} while (0)
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
struct task_struct;
|
||||
|
||||
DECLARE_PER_CPU(struct task_struct *, __entry_task);
|
||||
|
||||
#include <asm/types.h>
|
||||
|
||||
struct cpu_context_save {
|
||||
|
|
@ -52,12 +54,11 @@ struct cpu_context_save {
|
|||
struct thread_info {
|
||||
unsigned long flags; /* low level flags */
|
||||
int preempt_count; /* 0 => preemptable, <0 => bug */
|
||||
#ifndef CONFIG_THREAD_INFO_IN_TASK
|
||||
struct task_struct *task; /* main task structure */
|
||||
#endif
|
||||
__u32 cpu; /* cpu */
|
||||
__u32 cpu_domain; /* cpu domain */
|
||||
#ifdef CONFIG_STACKPROTECTOR_PER_TASK
|
||||
unsigned long stack_canary;
|
||||
#endif
|
||||
struct cpu_context_save cpu_context; /* cpu context */
|
||||
__u32 abi_syscall; /* ABI type and syscall nr */
|
||||
__u8 used_cp[16]; /* thread used copro */
|
||||
|
|
@ -71,11 +72,16 @@ struct thread_info {
|
|||
|
||||
#define INIT_THREAD_INFO(tsk) \
|
||||
{ \
|
||||
.task = &tsk, \
|
||||
INIT_THREAD_INFO_TASK(tsk) \
|
||||
.flags = 0, \
|
||||
.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
|
||||
*/
|
||||
|
|
@ -86,6 +92,7 @@ static inline struct thread_info *current_thread_info(void)
|
|||
return (struct thread_info *)
|
||||
(current_stack_pointer & ~(THREAD_SIZE - 1));
|
||||
}
|
||||
#endif
|
||||
|
||||
#define thread_saved_pc(tsk) \
|
||||
((unsigned long)(task_thread_info(tsk)->cpu_context.pc))
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
|
||||
.macro switch_tls_v6k, base, tp, tpuser, tmp1, tmp2
|
||||
mrc p15, 0, \tmp2, c13, c0, 2 @ get the user r/w register
|
||||
mcr p15, 0, \tp, c13, c0, 3 @ set TLS register
|
||||
mcr p15, 0, \tpuser, c13, c0, 2 @ and the user r/w register
|
||||
@ TLS register update is deferred until return to user space
|
||||
mcr p15, 0, \tpuser, c13, c0, 2 @ set the user r/w register
|
||||
str \tmp2, [\base, #TI_TP_VALUE + 4] @ save it
|
||||
.endm
|
||||
|
||||
|
|
@ -38,18 +38,22 @@
|
|||
#ifdef CONFIG_TLS_REG_EMUL
|
||||
#define tls_emu 1
|
||||
#define has_tls_reg 1
|
||||
#define defer_tls_reg_update 0
|
||||
#define switch_tls switch_tls_none
|
||||
#elif defined(CONFIG_CPU_V6)
|
||||
#define tls_emu 0
|
||||
#define has_tls_reg (elf_hwcap & HWCAP_TLS)
|
||||
#define defer_tls_reg_update 0
|
||||
#define switch_tls switch_tls_v6
|
||||
#elif defined(CONFIG_CPU_32v6K)
|
||||
#define tls_emu 0
|
||||
#define has_tls_reg 1
|
||||
#define defer_tls_reg_update 1
|
||||
#define switch_tls switch_tls_v6k
|
||||
#else
|
||||
#define tls_emu 0
|
||||
#define has_tls_reg 0
|
||||
#define defer_tls_reg_update 0
|
||||
#define switch_tls switch_tls_software
|
||||
#endif
|
||||
|
||||
|
|
@ -77,7 +81,7 @@ static inline void set_tls(unsigned long val)
|
|||
*/
|
||||
barrier();
|
||||
|
||||
if (!tls_emu) {
|
||||
if (!tls_emu && !defer_tls_reg_update) {
|
||||
if (has_tls_reg) {
|
||||
asm("mcr p15, 0, %0, c13, c0, 3"
|
||||
: : "r" (val));
|
||||
|
|
|
|||
|
|
@ -43,7 +43,9 @@ int main(void)
|
|||
BLANK();
|
||||
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
|
||||
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
|
||||
#ifndef CONFIG_THREAD_INFO_IN_TASK
|
||||
DEFINE(TI_TASK, offsetof(struct thread_info, task));
|
||||
#endif
|
||||
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
|
||||
DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain));
|
||||
DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context));
|
||||
|
|
@ -63,10 +65,6 @@ int main(void)
|
|||
#ifdef CONFIG_IWMMXT
|
||||
DEFINE(TI_IWMMXT_STATE, offsetof(struct thread_info, fpstate.iwmmxt));
|
||||
#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();
|
||||
DEFINE(S_R0, offsetof(struct pt_regs, ARM_r0));
|
||||
DEFINE(S_R1, offsetof(struct pt_regs, ARM_r1));
|
||||
|
|
|
|||
|
|
@ -384,6 +384,8 @@ ENDPROC(__fiq_abt)
|
|||
ATRAP( teq r8, r7)
|
||||
ATRAP( mcrne p15, 0, r8, c1, c0, 0)
|
||||
|
||||
reload_current r7, r8
|
||||
|
||||
@
|
||||
@ Clear FP to mark the first stack frame
|
||||
@
|
||||
|
|
@ -762,6 +764,8 @@ ENTRY(__switch_to)
|
|||
add r7, r7, #TSK_STACK_CANARY & ~IMM12_MASK
|
||||
.endif
|
||||
ldr r7, [r7, #TSK_STACK_CANARY & IMM12_MASK]
|
||||
#elif defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO)
|
||||
mov r7, r2 @ Preserve 'next'
|
||||
#endif
|
||||
#ifdef CONFIG_CPU_USE_DOMAINS
|
||||
mcr p15, 0, r6, c3, c0, 0 @ Set domain register
|
||||
|
|
@ -776,6 +780,7 @@ ENTRY(__switch_to)
|
|||
#endif
|
||||
THUMB( mov ip, r4 )
|
||||
mov r0, r5
|
||||
set_current r7
|
||||
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( ldr sp, [ip], #4 )
|
||||
|
|
|
|||
|
|
@ -170,6 +170,7 @@ ENTRY(vector_swi)
|
|||
str saved_psr, [sp, #S_PSR] @ Save CPSR
|
||||
str r0, [sp, #S_OLD_R0] @ Save OLD_R0
|
||||
#endif
|
||||
reload_current r10, ip
|
||||
zero_fp
|
||||
alignment_trap r10, ip, __cr_alignment
|
||||
asm_trace_hardirqs_on save=0
|
||||
|
|
|
|||
|
|
@ -292,6 +292,14 @@
|
|||
|
||||
|
||||
.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
|
||||
#ifndef CONFIG_THUMB2_KERNEL
|
||||
@ ARM mode restore
|
||||
|
|
|
|||
|
|
@ -105,6 +105,11 @@ __mmap_switched:
|
|||
mov r1, #0
|
||||
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}
|
||||
str r9, [r0] @ Save processor ID
|
||||
str r7, [r1] @ Save machine type
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ ENTRY(secondary_startup)
|
|||
ret r12
|
||||
1: bl __after_proc_init
|
||||
ldr sp, [r7, #12] @ set up the stack pointer
|
||||
ldr r0, [r7, #16] @ set up task pointer
|
||||
mov fp, #0
|
||||
b secondary_start_kernel
|
||||
ENDPROC(secondary_startup)
|
||||
|
|
|
|||
|
|
@ -424,8 +424,9 @@ ENDPROC(secondary_startup)
|
|||
ENDPROC(secondary_startup_arm)
|
||||
|
||||
ENTRY(__secondary_switched)
|
||||
ldr_l r7, secondary_data + 12 @ get secondary_data.stack
|
||||
mov sp, r7
|
||||
adr_l r7, secondary_data + 12 @ get secondary_data.stack
|
||||
ldr sp, [r7]
|
||||
ldr r0, [r7, #4] @ get secondary_data.task
|
||||
mov fp, #0
|
||||
b secondary_start_kernel
|
||||
ENDPROC(__secondary_switched)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,10 @@
|
|||
|
||||
#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)
|
||||
#include <linux/stackprotector.h>
|
||||
unsigned long __stack_chk_guard __read_mostly;
|
||||
|
|
@ -269,10 +273,6 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
|
|||
|
||||
thread_notify(THREAD_NOTIFY_COPY, thread);
|
||||
|
||||
#ifdef CONFIG_STACKPROTECTOR_PER_TASK
|
||||
thread->stack_canary = p->stack_canary;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -153,6 +153,10 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
|
|||
secondary_data.pgdir = virt_to_phys(idmap_pgd);
|
||||
secondary_data.swapper_pg_dir = get_arch_pgd(swapper_pg_dir);
|
||||
#endif
|
||||
secondary_data.task = idle;
|
||||
if (IS_ENABLED(CONFIG_THREAD_INFO_IN_TASK))
|
||||
task_thread_info(idle)->cpu = cpu;
|
||||
|
||||
sync_cache_w(&secondary_data);
|
||||
|
||||
/*
|
||||
|
|
@ -375,9 +379,12 @@ void arch_cpu_idle_dead(void)
|
|||
*/
|
||||
__asm__("mov sp, %0\n"
|
||||
" mov fp, #0\n"
|
||||
" mov r0, %1\n"
|
||||
" 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 */
|
||||
|
||||
|
|
@ -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
|
||||
* 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;
|
||||
unsigned int cpu;
|
||||
|
||||
set_current(task);
|
||||
|
||||
secondary_biglittle_init();
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -30,8 +30,7 @@
|
|||
* act_mm - get current->active_mm
|
||||
*/
|
||||
.macro act_mm, rd
|
||||
get_thread_info \rd
|
||||
ldr \rd, [\rd, #TI_TASK]
|
||||
get_current \rd
|
||||
.if (TSK_ACTIVE_MM > IMM12_MASK)
|
||||
add \rd, \rd, #TSK_ACTIVE_MM & ~IMM12_MASK
|
||||
.endif
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
__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)
|
||||
{
|
||||
|
|
@ -13,7 +13,7 @@ static unsigned int arm_pertask_ssp_rtl_execute(void)
|
|||
for (insn = get_insns(); insn; insn = NEXT_INSN(insn)) {
|
||||
const char *sym;
|
||||
rtx body;
|
||||
rtx mask, masked_sp;
|
||||
rtx current;
|
||||
|
||||
/*
|
||||
* 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)
|
|||
|
||||
/*
|
||||
* Replace the source of the SET insn with an expression that
|
||||
* produces the address of the copy of the stack canary value
|
||||
* stored in struct thread_info
|
||||
* produces the address of the current task's stack canary value
|
||||
*/
|
||||
mask = GEN_INT(sext_hwi(sp_mask, GET_MODE_PRECISION(Pmode)));
|
||||
masked_sp = gen_reg_rtx(Pmode);
|
||||
current = gen_reg_rtx(Pmode);
|
||||
|
||||
emit_insn_before(gen_rtx_set(masked_sp,
|
||||
gen_rtx_AND(Pmode,
|
||||
stack_pointer_rtx,
|
||||
mask)),
|
||||
insn);
|
||||
emit_insn_before(gen_load_tp_hard(current), insn);
|
||||
|
||||
SET_SRC(body) = gen_rtx_PLUS(Pmode, masked_sp,
|
||||
SET_SRC(body) = gen_rtx_PLUS(Pmode, current,
|
||||
GEN_INT(canary_offset));
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -72,7 +66,6 @@ __visible int plugin_init(struct plugin_name_args *plugin_info,
|
|||
const char * const plugin_name = plugin_info->base_name;
|
||||
const int argc = plugin_info->argc;
|
||||
const struct plugin_argument *argv = plugin_info->argv;
|
||||
int tso = 0;
|
||||
int i;
|
||||
|
||||
if (!plugin_default_version_check(version, &gcc_version)) {
|
||||
|
|
@ -91,11 +84,6 @@ __visible int plugin_init(struct plugin_name_args *plugin_info,
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[i].key, "tso")) {
|
||||
tso = atoi(argv[i].value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[i].key, "offset")) {
|
||||
canary_offset = atoi(argv[i].value);
|
||||
continue;
|
||||
|
|
@ -105,9 +93,6 @@ __visible int plugin_init(struct plugin_name_args *plugin_info,
|
|||
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);
|
||||
|
||||
register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user