[RFC PATCH 16/16] MIPS: Activate CONFIG_THREAD_INFO_IN_TASK

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Enable CONFIG_THREAD_INFO_IN_TASK, which embeds the thread_info at the
start of the task struct, rather than locating it at the bottom of the
kernel stack. This is a step towards allowing mapped kernel stacks, and
is in general a kernel hardening feature because a kernel stack overflow
will not overwrite the thread_info (of course, it might overwrite
something else below the stack page, but that's where mapped stacks come
in...).
- Load the initial $28 with the init_task.
- Add a arch specific current.h, which replaces reading
  current_thread_info from $28 with reading $current. The generic kernel
  provides current_thread_info when CONFIG_THREAD_INFO_IN_TASK is
  enabled.
- When resume()ing a thread, pass the task's stack pointer rather that
  using task_thread_info() to get the stack base.
- Remove task and cpu members from the thread_info struct. Task is
  redundant since current / current_thread_info are now aliases to the
  same structure. The cpu field is not managed by the generic kernel when
  CONFIG_THREAD_INFO_IN_TASK is active, since task->cpu replaces it.
- Fix up all locations which get the task struct from the thread_info.
  They are now one and the same so the pointer dereference can be
  removed.

Since this is quite an invasive change, here is quantification of it's
impact. All tests are from start of series to this patch with a 64r6
defconfig on Boston platform.

Total: Before=10010245, After=10001800, chg -0.08%

Average latency of syscall (10 x lat_syscall -W 2 -N 10 null)
Before: 6.13729, After: 6.12153, chg -0.25%

Average latency of syscall (10 x lat_syscall -W 2 -N 10 stat /dev/null)
Before: 102.21804, After: 102.58439, chg +0.36%

Average latency of syscall (10 x lat_syscall -W 2 -N 10 exec"
Before: 16051.1, After: 16130.0, chg +0.49%

Signed-off-by: Matt Redfearn <matt.redfearn@xxxxxxxx>

---

 arch/mips/Kconfig                       |  1 +
 arch/mips/cavium-octeon/octeon-memcpy.S |  6 ++----
 arch/mips/include/asm/Kbuild            |  1 -
 arch/mips/include/asm/current.h         | 22 ++++++++++++++++++++++
 arch/mips/include/asm/stackframe.h      |  2 --
 arch/mips/include/asm/switch_to.h       |  5 ++---
 arch/mips/include/asm/thread_info.h     | 12 ------------
 arch/mips/kernel/asm-offsets.c          |  2 --
 arch/mips/kernel/head.S                 |  5 +++--
 arch/mips/kernel/octeon_switch.S        |  5 ++---
 arch/mips/kernel/r2300_switch.S         |  5 ++---
 arch/mips/kernel/r4k_switch.S           |  5 ++---
 arch/mips/kernel/smp.c                  |  3 +--
 arch/mips/lib/csum_partial.S            |  7 ++-----
 arch/mips/lib/memcpy.S                  |  8 ++------
 arch/mips/lib/memset.S                  |  6 ++----
 16 files changed, 43 insertions(+), 52 deletions(-)
 create mode 100644 arch/mips/include/asm/current.h

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 350a990fc719..f50f87c6ef24 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -72,6 +72,7 @@ config MIPS
 	select PERF_USE_VMALLOC
 	select RTC_LIB if !MACH_LOONGSON64
 	select SYSCTL_EXCEPTION_TRACE
+	select THREAD_INFO_IN_TASK
 	select VIRT_TO_BUS
 
 menu "Machine selection"
diff --git a/arch/mips/cavium-octeon/octeon-memcpy.S b/arch/mips/cavium-octeon/octeon-memcpy.S
index 0a7c9834b81c..1621995c76b5 100644
--- a/arch/mips/cavium-octeon/octeon-memcpy.S
+++ b/arch/mips/cavium-octeon/octeon-memcpy.S
@@ -391,8 +391,7 @@ l_exc_copy:
 	 *
 	 * Assumes src < THREAD_BUADDR($28)
 	 */
-	LOAD	t0, TI_TASK($28)
-	LOAD	t0, THREAD_BUADDR(t0)
+	LOAD	t0, THREAD_BUADDR($28)
 1:
 EXC(	lb	t1, 0(src),	l_exc)
 	ADD	src, src, 1
@@ -400,8 +399,7 @@ EXC(	lb	t1, 0(src),	l_exc)
 	bne	src, t0, 1b
 	 ADD	dst, dst, 1
 l_exc:
-	LOAD	t0, TI_TASK($28)
-	LOAD	t0, THREAD_BUADDR(t0)	# t0 is just past last good address
+	LOAD	t0, THREAD_BUADDR($28)	# t0 is just past last good address
 	SUB	len, AT, t0		# len number of uncopied bytes
 	jr	ra
 	 nop
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 7c8aab23bce8..21e15df89b4e 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -1,7 +1,6 @@
 # MIPS headers
 generic-(CONFIG_GENERIC_CSUM) += checksum.h
 generic-y += clkdev.h
-generic-y += current.h
 generic-y += dma-contiguous.h
 generic-y += emergency-restart.h
 generic-y += export.h
diff --git a/arch/mips/include/asm/current.h b/arch/mips/include/asm/current.h
new file mode 100644
index 000000000000..b004856d5b1f
--- /dev/null
+++ b/arch/mips/include/asm/current.h
@@ -0,0 +1,22 @@
+#ifndef __ASM_CURRENT_H
+#define __ASM_CURRENT_H
+
+#include <linux/compiler.h>
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+
+/* How to get the thread information struct from C.  */
+register struct task_struct *__current_task __asm__("$28");
+
+static __always_inline struct task_struct *get_current(void)
+{
+	return __current_task;
+}
+
+#define current get_current()
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_CURRENT_H */
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index 2ba65600a8d9..92ea518edbf5 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -219,8 +219,6 @@
 		.macro	get_saved_sp docfi=0
 		/* Get current thread info into k1 */
 		get_saved_ti	k1, k0
-		/* Get task struct into k1 */
-		LONG_L		k1, TI_TASK(k1)
 		/* Get the stack into k1 */
 		LONG_L		k1, TASK_STACK(k1)
 		/* Get starting stack location */
diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
index e610473d61b8..446cf3e80276 100644
--- a/arch/mips/include/asm/switch_to.h
+++ b/arch/mips/include/asm/switch_to.h
@@ -24,13 +24,12 @@ struct task_struct;
  * resume - resume execution of a task
  * @prev:	The task previously executed.
  * @next:	The task to begin executing.
- * @next_ti:	task_thread_info(next).
  *
  * This function is used whilst scheduling to save the context of prev & load
  * the context of next. Returns prev.
  */
 extern asmlinkage struct task_struct *resume(struct task_struct *prev,
-		struct task_struct *next, struct thread_info *next_ti);
+					     struct task_struct *next);
 
 extern unsigned int ll_bit;
 extern struct task_struct *ll_task;
@@ -130,7 +129,7 @@ do {									\
 	if (cpu_has_userlocal)						\
 		write_c0_userlocal(task_thread_info(next)->tp_value);	\
 	__restore_watch(next);						\
-	(last) = resume(prev, next, task_thread_info(next));		\
+	(last) = resume(prev, next);					\
 } while (0)
 
 #endif /* _ASM_SWITCH_TO_H */
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index b8cc81055d57..2d83cb9e238d 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -23,10 +23,8 @@
  *   must also be changed
  */
 struct thread_info {
-	struct task_struct	*task;		/* main task structure */
 	unsigned long		flags;		/* low level flags */
 	unsigned long		tp_value;	/* thread pointer */
-	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
 	mm_segment_t		addr_limit;	/*
 						 * thread address space limit:
@@ -42,9 +40,7 @@ struct thread_info {
  */
 #define INIT_THREAD_INFO(tsk)			\
 {						\
-	.task		= &tsk,			\
 	.flags		= _TIF_FIXADE,		\
-	.cpu		= 0,			\
 	.preempt_count	= INIT_PREEMPT_COUNT,	\
 	.addr_limit	= KERNEL_DS,		\
 }
@@ -52,17 +48,9 @@ struct thread_info {
 #define init_thread_info	(init_thread_union.thread_info)
 #define init_stack		(init_thread_union.stack)
 
-/* How to get the thread information struct from C.  */
-register struct thread_info *__current_thread_info __asm__("$28");
-
 /* thread_info pointer for each CPU */
 extern unsigned long thread_info_ptr[NR_CPUS];
 
-static inline struct thread_info *current_thread_info(void)
-{
-	return __current_thread_info;
-}
-
 #endif /* !__ASSEMBLY__ */
 
 /* thread information allocation */
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index b682a77a0072..9af07a9fa2b6 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -93,10 +93,8 @@ void output_task_defines(void)
 void output_thread_info_defines(void)
 {
 	COMMENT("MIPS thread_info offsets.");
-	OFFSET(TI_TASK, thread_info, task);
 	OFFSET(TI_FLAGS, thread_info, flags);
 	OFFSET(TI_TP_VALUE, thread_info, tp_value);
-	OFFSET(TI_CPU, thread_info, cpu);
 	OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
 	OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
 	OFFSET(TI_REGS, thread_info, regs);
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 5a7e0dac8ada..6b71a1316a52 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -130,10 +130,11 @@ dtb_found:
 #endif
 
 	MTC0		zero, CP0_CONTEXT	# clear context register
-	PTR_LA		$28, init_thread_union
+	PTR_LA          $28, init_task
 	/* Set the SP after an empty pt_regs.  */
+	PTR_LA		t0, init_thread_union
 	PTR_LI		sp, _THREAD_SIZE - 32 - PT_SIZE
-	PTR_ADDU	sp, $28
+	PTR_ADDU	sp, t0
 	back_to_back_c0_hazard
 	set_saved_ti	$28, t0
 	PTR_SUBU	sp, 4 * SZREG		# init stack pointer
diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S
index 8f2d80b9b8a4..f3c8eefcf63c 100644
--- a/arch/mips/kernel/octeon_switch.S
+++ b/arch/mips/kernel/octeon_switch.S
@@ -18,8 +18,7 @@
 #include <asm/stackframe.h>
 
 /*
- * task_struct *resume(task_struct *prev, task_struct *next,
- *		       struct thread_info *next_ti)
+ * task_struct *resume(task_struct *prev, task_struct *next)
  */
 	.align	7
 	LEAF(resume)
@@ -71,7 +70,7 @@
 	 * The order of restoring the registers takes care of the race
 	 * updating $28, $29 and saved_ti without disabling ints.
 	 */
-	move	$28, a2
+	move	$28, a1
 	cpu_restore_nonscratch a1
 	set_saved_ti	$28, t0
 
diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S
index db8186ed9b24..32a68596df1d 100644
--- a/arch/mips/kernel/r2300_switch.S
+++ b/arch/mips/kernel/r2300_switch.S
@@ -27,8 +27,7 @@
 	.align	5
 
 /*
- * task_struct *resume(task_struct *prev, task_struct *next,
- *		       struct thread_info *next_ti)
+ * task_struct *resume(task_struct *prev, task_struct *next)
  */
 LEAF(resume)
 	mfc0	t1, CP0_STATUS
@@ -46,7 +45,7 @@ LEAF(resume)
 	 * The order of restoring the registers takes care of the race
 	 * updating $28, $29 and saved_ti without disabling ints.
 	 */
-	move	$28, a2
+	move	$28, a1
 	cpu_restore_nonscratch a1
 	set_saved_ti	$28, t0
 
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 6428904a34c7..c5b29aca6d31 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -21,8 +21,7 @@
 #include <asm/asmmacro.h>
 
 /*
- * task_struct *resume(task_struct *prev, task_struct *next,
- *		       struct thread_info *next_ti)
+ * task_struct *resume(task_struct *prev, task_struct *next)
  */
 	.align	5
 	LEAF(resume)
@@ -41,7 +40,7 @@
 	 * The order of restoring the registers takes care of the race
 	 * updating $28, $29 and saved_ti without disabling ints.
 	 */
-	move	$28, a2
+	move	$28, a1
 	cpu_restore_nonscratch a1
 	set_saved_ti	$28, t0
 
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index b93e6748f38d..bd9d893469e2 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -353,7 +353,7 @@ early_initcall(mips_smp_ipi_init);
  */
 asmlinkage void start_secondary(void)
 {
-	unsigned int cpu = current_thread_info()->cpu;
+	unsigned int cpu = current->cpu;
 
 	/* Stash this CPUs ID in CP0 for smp_processor_id() */
 #ifdef CONFIG_MIPS_PGD_C0_CONTEXT
@@ -436,7 +436,6 @@ void __init smp_cpus_done(unsigned int max_cpus)
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
 	init_new_context(current, &init_mm);
-	current_thread_info()->cpu = 0;
 	mp_ops->prepare_cpus(max_cpus);
 	set_cpu_sibling_map(0);
 	set_cpu_core_map(0);
diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S
index 2ff84f4b1717..5c0365973836 100644
--- a/arch/mips/lib/csum_partial.S
+++ b/arch/mips/lib/csum_partial.S
@@ -766,9 +766,8 @@ EXPORT_SYMBOL(csum_partial)
 	 *
 	 * Assumes src < THREAD_BUADDR($28)
 	 */
-	LOADK	t0, TI_TASK($28)
 	 li	t2, SHIFT_START
-	LOADK	t0, THREAD_BUADDR(t0)
+	LOADK	t0, THREAD_BUADDR($28)
 1:
 	LOADBU(t1, 0(src), .Ll_exc\@)
 	ADD	src, src, 1
@@ -781,9 +780,7 @@ EXPORT_SYMBOL(csum_partial)
 	bne	src, t0, 1b
 	.set	noreorder
 .Ll_exc\@:
-	LOADK	t0, TI_TASK($28)
-	 nop
-	LOADK	t0, THREAD_BUADDR(t0)	# t0 is just past last good address
+	LOADK	t0, THREAD_BUADDR($28)	# t0 is just past last good address
 	 nop
 	SUB	len, AT, t0		# len number of uncopied bytes
 	/*
diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S
index 03e3304d6ae5..5a2cf36dfba6 100644
--- a/arch/mips/lib/memcpy.S
+++ b/arch/mips/lib/memcpy.S
@@ -548,9 +548,7 @@
 	 *
 	 * Assumes src < THREAD_BUADDR($28)
 	 */
-	LOADK	t0, TI_TASK($28)
-	 nop
-	LOADK	t0, THREAD_BUADDR(t0)
+	LOADK	t0, THREAD_BUADDR($28)
 1:
 	LOADB(t1, 0(src), .Ll_exc\@)
 	ADD	src, src, 1
@@ -560,9 +558,7 @@
 	bne	src, t0, 1b
 	.set	noreorder
 .Ll_exc\@:
-	LOADK	t0, TI_TASK($28)
-	 nop
-	LOADK	t0, THREAD_BUADDR(t0)	# t0 is just past last good address
+	LOADK	t0, THREAD_BUADDR($28)	# t0 is just past last good address
 	 nop
 	SUB	len, AT, t0		# len number of uncopied bytes
 	jr	ra
diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S
index a1456664d6c2..34062b5a95e1 100644
--- a/arch/mips/lib/memset.S
+++ b/arch/mips/lib/memset.S
@@ -241,17 +241,15 @@
 	nop
 
 .Lfwd_fixup\@:
-	PTR_L		t0, TI_TASK($28)
 	andi		a2, 0x3f
-	LONG_L		t0, THREAD_BUADDR(t0)
+	LONG_L		t0, THREAD_BUADDR($28)
 	LONG_ADDU	a2, t1
 	jr		ra
 	LONG_SUBU	a2, t0
 
 .Lpartial_fixup\@:
-	PTR_L		t0, TI_TASK($28)
 	andi		a2, STORMASK
-	LONG_L		t0, THREAD_BUADDR(t0)
+	LONG_L		t0, THREAD_BUADDR($28)
 	LONG_ADDU	a2, t1
 	jr		ra
 	LONG_SUBU	a2, t0
-- 
2.7.4



[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux