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

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
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -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
+5 −4
Original line number Diff line number Diff line
@@ -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))
+29 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
/* 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 */
+2 −1
Original line number Diff line number Diff line
@@ -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);
Loading