All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC v2 0/4] arm: Moving thread_info into task_struct
@ 2018-06-18 15:30 Zubin Mithra
  2018-06-18 15:30 ` [RFC v2 1/4] arm: Store address of thread_info in sp^ Zubin Mithra
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Zubin Mithra @ 2018-06-18 15:30 UTC (permalink / raw)
  To: linux-arm-kernel

These are a set of preparatory patches for moving the thread_info
into task_struct for ARM. The patches that perform that actual move
are not implemented yet.

These patches have only been tested on QEMU using the following boards.
- versatilepb
- vexpress-a9

[v2 changes]
- Add a patch that stores thread_info in sp^

Zubin Mithra (4):
  arm: Store address of thread_info in sp^
  arm: factor out current_stack_pointer
  arm: make cpu a percpu variable
  arm: add refcounting for task stacks

 arch/arm/include/asm/assembler.h     | 27 ++++++++++++++++++++++-----
 arch/arm/include/asm/percpu.h        |  2 ++
 arch/arm/include/asm/smp.h           | 11 ++++++++++-
 arch/arm/include/asm/stack_pointer.h |  9 +++++++++
 arch/arm/include/asm/switch_to.h     | 11 +++++++++++
 arch/arm/include/asm/thread_info.h   | 19 ++++++++++++-------
 arch/arm/kernel/entry-armv.S         |  5 ++++-
 arch/arm/kernel/entry-common.S       |  2 ++
 arch/arm/kernel/head-common.S        |  2 ++
 arch/arm/kernel/head.S               |  1 +
 arch/arm/kernel/process.c            | 21 +++++++++++++++------
 arch/arm/kernel/return_address.c     |  1 +
 arch/arm/kernel/setup.c              |  2 +-
 arch/arm/kernel/smp.c                | 13 +++++++++++--
 arch/arm/kernel/stacktrace.c         |  8 ++++++++
 arch/arm/kernel/topology.c           |  2 ++
 arch/arm/kernel/traps.c              | 13 +++++++++++--
 arch/arm/kernel/unwind.c             |  1 +
 18 files changed, 125 insertions(+), 25 deletions(-)
 create mode 100644 arch/arm/include/asm/stack_pointer.h

-- 
2.18.0.rc1.244.gcf134e6275-goog

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC v2 1/4] arm: Store address of thread_info in sp^
  2018-06-18 15:30 [RFC v2 0/4] arm: Moving thread_info into task_struct Zubin Mithra
@ 2018-06-18 15:30 ` Zubin Mithra
  2018-06-26  9:10   ` Ard Biesheuvel
  2018-06-26  9:24   ` Russell King - ARM Linux
  2018-06-18 15:30 ` [RFC v2 2/4] arm: factor out current_stack_pointer Zubin Mithra
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 9+ messages in thread
From: Zubin Mithra @ 2018-06-18 15:30 UTC (permalink / raw)
  To: linux-arm-kernel

There is a need to store thread_info in a register so that subsequent
patches can move thread_info into task_struct. This would also
facilitate having separate IRQ stacks.

Banked register sp is an unused scratch register in EL1 context. We can
utilize this register for stashing the current thread_info.

The macro save_ti_sp_usr is used to stash the address of thread_info
into sp^. The macro get_thread_info is modified to retrieve thread_info
from sp^. Additionally, upon context switch, sp^ is set to current's
thread_info by using set_sp_usr.

Signed-off-by: Zubin Mithra <zsm@chromium.org>
---
 arch/arm/include/asm/assembler.h   | 27 ++++++++++++++++++++++-----
 arch/arm/include/asm/switch_to.h   | 11 +++++++++++
 arch/arm/include/asm/thread_info.h | 14 ++++++++++++--
 arch/arm/kernel/entry-armv.S       |  5 ++++-
 arch/arm/kernel/entry-common.S     |  2 ++
 arch/arm/kernel/head-common.S      |  2 ++
 arch/arm/kernel/head.S             |  1 +
 7 files changed, 54 insertions(+), 8 deletions(-)

diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 0cd4dccbae78..be18a364f590 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -205,11 +205,28 @@
 /*
  * Get current thread_info.
  */
-	.macro	get_thread_info, rd
- 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
+	.macro get_thread_info, rd
+	sub sp, #4
+	stm sp, {sp}^
+	pop {\rd}
+	.endm
+
+	.macro save_ti_sp_usr, tmp, restore=0
+	.if \restore
+	push	{\tmp}
+	.endif
+
+ ARM(	mov	\tmp, sp, lsr #THREAD_SIZE_ORDER + PAGE_SHIFT	)
+ THUMB(	mov	\tmp, sp			)
+ THUMB(	lsr	\tmp, \tmp, #THREAD_SIZE_ORDER + PAGE_SHIFT	)
+	mov	\tmp, \tmp, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT
+	push	{\tmp}
+	ldm	sp, {sp}^
+	add	sp, 4
+
+	.if \restore
+	pop	{\tmp}
+	.endif
 	.endm
 
 /*
diff --git a/arch/arm/include/asm/switch_to.h b/arch/arm/include/asm/switch_to.h
index d3e937dcee4d..5b4572f78cf4 100644
--- a/arch/arm/include/asm/switch_to.h
+++ b/arch/arm/include/asm/switch_to.h
@@ -16,6 +16,16 @@
 #define __complete_pending_tlbi()
 #endif
 
+static inline void set_sp_usr(unsigned long ti)
+{
+       asm volatile(
+		"push {%0}\n"
+		"ldm sp, {sp}^\n"
+		"add sp, #4\n"
+		:: "r"(ti)
+       );
+}
+
 /*
  * switch_to(prev, next) should switch from task `prev' to `next'
  * `prev' will never be the same as `next'.  schedule() itself
@@ -27,6 +37,7 @@ extern struct task_struct *__switch_to(struct task_struct *, struct thread_info
 do {									\
 	__complete_pending_tlbi();					\
 	last = __switch_to(prev,task_thread_info(prev), task_thread_info(next));	\
+	set_sp_usr(current_stack_pointer & ~(THREAD_SIZE - 1));		\
 } while (0)
 
 #endif /* __ASM_ARM_SWITCH_TO_H */
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index e71cc35de163..4a351e0aba0e 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -80,6 +80,7 @@ struct thread_info {
  */
 register unsigned long current_stack_pointer asm ("sp");
 
+
 /*
  * how to get the thread information struct from C
  */
@@ -87,8 +88,17 @@ static inline struct thread_info *current_thread_info(void) __attribute_const__;
 
 static inline struct thread_info *current_thread_info(void)
 {
-	return (struct thread_info *)
-		(current_stack_pointer & ~(THREAD_SIZE - 1));
+	unsigned long ti;
+
+	asm volatile(
+		"sub sp, #4\n"
+		"stm sp, {sp}^\n"
+		"ldr %0, [sp]\n"
+		"add sp, #4\n"
+		: "=r" (ti)
+	);
+
+	return (struct thread_info *)ti;
 }
 
 #define thread_saved_pc(tsk)	\
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 179a9f6bd1e3..af79f9053530 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -181,7 +181,8 @@ ENDPROC(__und_invalid)
 	@
 	stmia	r7, {r2 - r6}
 
-	get_thread_info tsk
+	save_ti_sp_usr tsk restore=0
+
 	ldr	r0, [tsk, #TI_ADDR_LIMIT]
 	mov	r1, #TASK_SIZE
 	str	r1, [tsk, #TI_ADDR_LIMIT]
@@ -411,6 +412,8 @@ ENDPROC(__fiq_abt)
 	uaccess_disable ip
 	.endif
 
+	save_ti_sp_usr tsk restore=0
+
 	@ Enable the alignment trap while in kernel mode
  ATRAP(	teq	r8, r7)
  ATRAP( mcrne	p15, 0, r8, c1, c0, 0)
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 106a1466518d..0dbeaccebf62 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -149,6 +149,7 @@ ENDPROC(ret_to_user)
  * This is how we return from a fork.
  */
 ENTRY(ret_from_fork)
+	save_ti_sp_usr	tsk
 	bl	schedule_tail
 	cmp	r5, #0
 	movne	r0, r4
@@ -185,6 +186,7 @@ ENTRY(vector_swi)
 	asm_trace_hardirqs_on save=0
 	enable_irq_notrace
 	ct_user_exit save=0
+	save_ti_sp_usr tsk
 
 	/*
 	 * Get the system call number.
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 6e0375e7db05..84e649144a32 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -109,6 +109,8 @@ __mmap_switched:
 	mov	r1, #0
 	bl	memset				@ clear .bss
 
+	save_ti_sp_usr r9
+
 	ldmia	r4, {r0, r1, r2, r3}
 	str	r9, [r0]			@ Save processor ID
 	str	r7, [r1]			@ Save machine type
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 6b1148cafffd..66bba1b27d2c 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -418,6 +418,7 @@ ENDPROC(secondary_startup_arm)
 ENTRY(__secondary_switched)
 	ldr	sp, [r7, #12]			@ get secondary_data.stack
 	mov	fp, #0
+	save_ti_sp_usr r0
 	b	secondary_start_kernel
 ENDPROC(__secondary_switched)
 
-- 
2.18.0.rc1.244.gcf134e6275-goog

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC v2 2/4] arm: factor out current_stack_pointer
  2018-06-18 15:30 [RFC v2 0/4] arm: Moving thread_info into task_struct Zubin Mithra
  2018-06-18 15:30 ` [RFC v2 1/4] arm: Store address of thread_info in sp^ Zubin Mithra
@ 2018-06-18 15:30 ` Zubin Mithra
  2018-06-18 15:30 ` [RFC v2 3/4] arm: make cpu a percpu variable Zubin Mithra
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Zubin Mithra @ 2018-06-18 15:30 UTC (permalink / raw)
  To: linux-arm-kernel

Multiple header files that rely on current_stack_pointer do not have the
necessary include <asm/thread_info.h>, and are thus fragile to changes
in the header soup.

Subsequent patches will affect the header soup such that including
<asm/thread_info.h> will result in a circular header include. Factor
current_stack_pointer into its own header and have all the users include
this header explicitly.

Signed-off-by: Zubin Mithra <zsm@chromium.org>
---
 arch/arm/include/asm/percpu.h        | 2 ++
 arch/arm/include/asm/stack_pointer.h | 9 +++++++++
 arch/arm/include/asm/thread_info.h   | 7 +------
 arch/arm/kernel/return_address.c     | 1 +
 arch/arm/kernel/stacktrace.c         | 1 +
 arch/arm/kernel/unwind.c             | 1 +
 6 files changed, 15 insertions(+), 6 deletions(-)
 create mode 100644 arch/arm/include/asm/stack_pointer.h

diff --git a/arch/arm/include/asm/percpu.h b/arch/arm/include/asm/percpu.h
index a89b4076cde4..6a19e634d0cf 100644
--- a/arch/arm/include/asm/percpu.h
+++ b/arch/arm/include/asm/percpu.h
@@ -16,6 +16,8 @@
 #ifndef _ASM_ARM_PERCPU_H_
 #define _ASM_ARM_PERCPU_H_
 
+#include <asm/stack_pointer.h>
+
 /*
  * Same as asm-generic/percpu.h, except that we store the per cpu offset
  * in the TPIDRPRW. TPIDRPRW only exists on V6K and V7
diff --git a/arch/arm/include/asm/stack_pointer.h b/arch/arm/include/asm/stack_pointer.h
new file mode 100644
index 000000000000..5a6a8c6d9208
--- /dev/null
+++ b/arch/arm/include/asm/stack_pointer.h
@@ -0,0 +1,9 @@
+#ifndef __ASM_STACK_POINTER_H
+#define __ASM_STACK_POINTER_H
+
+/*
+ * how to get the current stack pointer in C
+ */
+register unsigned long current_stack_pointer asm ("sp");
+
+#endif
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 4a351e0aba0e..61fa0379ea85 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -25,6 +25,7 @@
 struct task_struct;
 
 #include <asm/types.h>
+#include <asm/stack_pointer.h>
 
 typedef unsigned long mm_segment_t;
 
@@ -75,12 +76,6 @@ struct thread_info {
 	.addr_limit	= KERNEL_DS,					\
 }
 
-/*
- * how to get the current stack pointer in C
- */
-register unsigned long current_stack_pointer asm ("sp");
-
-
 /*
  * how to get the thread information struct from C
  */
diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c
index 36ed35073289..d76e64250816 100644
--- a/arch/arm/kernel/return_address.c
+++ b/arch/arm/kernel/return_address.c
@@ -14,6 +14,7 @@
 #if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
 #include <linux/sched.h>
 
+#include <asm/stack_pointer.h>
 #include <asm/stacktrace.h>
 
 struct return_address_data {
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
index a56e7c856ab5..d519b8e0797f 100644
--- a/arch/arm/kernel/stacktrace.c
+++ b/arch/arm/kernel/stacktrace.c
@@ -4,6 +4,7 @@
 #include <linux/stacktrace.h>
 
 #include <asm/sections.h>
+#include <asm/stack_pointer.h>
 #include <asm/stacktrace.h>
 #include <asm/traps.h>
 
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c
index 0bee233fef9a..860f8ac187e0 100644
--- a/arch/arm/kernel/unwind.c
+++ b/arch/arm/kernel/unwind.c
@@ -45,6 +45,7 @@
 #include <linux/spinlock.h>
 #include <linux/list.h>
 
+#include <asm/stack_pointer.h>
 #include <asm/stacktrace.h>
 #include <asm/traps.h>
 #include <asm/unwind.h>
-- 
2.18.0.rc1.244.gcf134e6275-goog

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC v2 3/4] arm: make cpu a percpu variable
  2018-06-18 15:30 [RFC v2 0/4] arm: Moving thread_info into task_struct Zubin Mithra
  2018-06-18 15:30 ` [RFC v2 1/4] arm: Store address of thread_info in sp^ Zubin Mithra
  2018-06-18 15:30 ` [RFC v2 2/4] arm: factor out current_stack_pointer Zubin Mithra
@ 2018-06-18 15:30 ` Zubin Mithra
  2018-06-18 15:30 ` [RFC v2 4/4] arm: add refcounting for task stacks Zubin Mithra
  2018-06-26  9:14 ` [RFC v2 0/4] arm: Moving thread_info into task_struct Russell King - ARM Linux
  4 siblings, 0 replies; 9+ messages in thread
From: Zubin Mithra @ 2018-06-18 15:30 UTC (permalink / raw)
  To: linux-arm-kernel

Without CONFIG_THREAD_INFO_IN_TASK, core code maintains thread_info::cpu
and arch specific code can use this to build raw_smp_processor_id().
With CONFIG_THREAD_INFO_IN_TASK, core code maintains task_struct::cpu
and arch specific code cannot access this due to header file circular
dependency.

Instead, we can maintain a percpu variable containing the cpu number.

This also means that cpu numbers obtained using smp_processor_id cannot
be used to set_my_cpu_offset. Use task_cpu(current) instead to get the
cpu in those cases.

Without any patches in this patchset, raw_smp_processor_id() was :-
	mov     r3, sp
	bic     r3, r3, #8128
	bic     r3, r3, #63
	ldr     r0, [r3, #16]

When thread_info is stored in sp^ as per the first patch in this series,
it becomes :-
	sub	sp, sp, #4
	stmia	sp, {sp}^
	ldr	r2, [sp]
	add	sp, sp, #4
	ldr	r2, [r2, #16]

Finally, when cpu is made a percpu variable and fetched using
raw_cpu_ptr() :-
	movw	r2, #4096	; 0x1000
	movt	r2, #32918	; 0x8096
	mrc	15, 0, r0, cr13, cr0, {4}
	ldr	r2, [r2, r0]

Note that once the thread_info is moved off of the stack, the sequence
of instructions used to fetch the cpu number would be the third sequence
using raw_cpu_ptr().

Signed-off-by: Zubin Mithra <zsm@chromium.org>
---
 arch/arm/include/asm/smp.h | 11 ++++++++++-
 arch/arm/kernel/setup.c    |  2 +-
 arch/arm/kernel/smp.c      | 13 +++++++++++--
 arch/arm/kernel/topology.c |  2 ++
 4 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index 709a55989cb0..cf366dd6e9f1 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -10,6 +10,8 @@
 #ifndef __ASM_ARM_SMP_H
 #define __ASM_ARM_SMP_H
 
+#include <asm/percpu.h>
+
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/thread_info.h>
@@ -18,7 +20,14 @@
 # error "<asm/smp.h> included in non-SMP build"
 #endif
 
-#define raw_smp_processor_id() (current_thread_info()->cpu)
+DECLARE_PER_CPU(int, cpu_number);
+
+/*
+ * to avoid implicit writes to preempt_count, compiler barriers in
+ * preempt_enable_notrace and preempt_disable_notrace, use *raw_cpu_ptr
+ * instead of this_cpu_read.
+ */
+#define raw_smp_processor_id() (*raw_cpu_ptr(&cpu_number))
 
 struct seq_file;
 
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 35ca494c028c..be3f5603dcac 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -521,7 +521,7 @@ static void __init elf_hwcap_fixup(void)
 void notrace cpu_init(void)
 {
 #ifndef CONFIG_CPU_V7M
-	unsigned int cpu = smp_processor_id();
+	unsigned int cpu = task_cpu(current);
 	struct stack *stk = &stacks[cpu];
 
 	if (cpu >= NR_CPUS) {
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 0978282d5fc2..dbb1eabf7912 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -54,6 +54,9 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/ipi.h>
 
+DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number);
+EXPORT_PER_CPU_SYMBOL(cpu_number);
+
 /*
  * as from 2.5, kernels no longer have an init_tasks structure
  * so we need some other way of telling a new secondary core
@@ -372,7 +375,8 @@ asmlinkage void secondary_start_kernel(void)
 	 * All kernel threads share the same mm context; grab a
 	 * reference and switch to it.
 	 */
-	cpu = smp_processor_id();
+	cpu = task_cpu(current);
+	set_my_cpu_offset(per_cpu_offset(cpu));
 	mmgrab(mm);
 	current->active_mm = mm;
 	cpumask_set_cpu(cpu, mm_cpumask(mm));
@@ -439,15 +443,20 @@ void __init smp_cpus_done(unsigned int max_cpus)
 
 void __init smp_prepare_boot_cpu(void)
 {
-	set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
+	set_my_cpu_offset(per_cpu_offset(task_cpu(current)));
 }
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
 	unsigned int ncores = num_possible_cpus();
+	unsigned int cpu;
 
 	init_cpu_topology();
 
+	for_each_possible_cpu(cpu) {
+		per_cpu(cpu_number, cpu) = cpu;
+	}
+
 	smp_store_cpu_info(smp_processor_id());
 
 	/*
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index 24ac3cab411d..6e05217106ac 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -310,6 +310,8 @@ void __init init_cpu_topology(void)
 	for_each_possible_cpu(cpu) {
 		struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]);
 
+		per_cpu(cpu_number, cpu) = cpu;
+
 		cpu_topo->thread_id = -1;
 		cpu_topo->core_id =  -1;
 		cpu_topo->socket_id = -1;
-- 
2.18.0.rc1.244.gcf134e6275-goog

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC v2 4/4] arm: add refcounting for task stacks
  2018-06-18 15:30 [RFC v2 0/4] arm: Moving thread_info into task_struct Zubin Mithra
                   ` (2 preceding siblings ...)
  2018-06-18 15:30 ` [RFC v2 3/4] arm: make cpu a percpu variable Zubin Mithra
@ 2018-06-18 15:30 ` Zubin Mithra
  2018-06-26  9:27   ` Russell King - ARM Linux
  2018-06-26  9:14 ` [RFC v2 0/4] arm: Moving thread_info into task_struct Russell King - ARM Linux
  4 siblings, 1 reply; 9+ messages in thread
From: Zubin Mithra @ 2018-06-18 15:30 UTC (permalink / raw)
  To: linux-arm-kernel

When CONFIG_THREAD_INFO_IN_TASK is enabled, thread stacks may be freed
before a stack is destroyed. This patch adds in refcounting to ensure
freed stacks are not used. If CONFIG_THREAD_INFO_IN_TASK is not used, no
refcounting is performed.

Signed-off-by: Zubin Mithra <zsm@chromium.org>
---
 arch/arm/kernel/process.c    | 21 +++++++++++++++------
 arch/arm/kernel/stacktrace.c |  7 +++++++
 arch/arm/kernel/traps.c      | 13 +++++++++++--
 3 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 225d1c58d2de..588003e25a75 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -297,7 +297,7 @@ EXPORT_SYMBOL(dump_fpu);
 unsigned long get_wchan(struct task_struct *p)
 {
 	struct stackframe frame;
-	unsigned long stack_page;
+	unsigned long stack_page, ret = 0;
 	int count = 0;
 	if (!p || p == current || p->state == TASK_RUNNING)
 		return 0;
@@ -306,16 +306,25 @@ unsigned long get_wchan(struct task_struct *p)
 	frame.sp = thread_saved_sp(p);
 	frame.lr = 0;			/* recovered from the stack */
 	frame.pc = thread_saved_pc(p);
-	stack_page = (unsigned long)task_stack_page(p);
+
+	stack_page = (unsigned long)try_get_task_stack(p);
+	if (!stack_page)
+		return 0;
+
 	do {
 		if (frame.sp < stack_page ||
 		    frame.sp >= stack_page + THREAD_SIZE ||
 		    unwind_frame(&frame) < 0)
-			return 0;
-		if (!in_sched_functions(frame.pc))
-			return frame.pc;
+			goto out;
+		if (!in_sched_functions(frame.pc)) {
+			ret = frame.pc;
+			goto out;
+		}
 	} while (count ++ < 16);
-	return 0;
+
+out:
+	put_task_stack(p);
+	return ret;
 }
 
 unsigned long arch_randomize_brk(struct mm_struct *mm)
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
index d519b8e0797f..ff20d5941724 100644
--- a/arch/arm/kernel/stacktrace.c
+++ b/arch/arm/kernel/stacktrace.c
@@ -1,6 +1,7 @@
 #include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/sched/debug.h>
+#include <linux/sched/task_stack.h>
 #include <linux/stacktrace.h>
 
 #include <asm/sections.h>
@@ -105,6 +106,9 @@ static noinline void __save_stack_trace(struct task_struct *tsk,
 	struct stack_trace_data data;
 	struct stackframe frame;
 
+	if (!try_get_task_stack(tsk))
+		return;
+
 	data.trace = trace;
 	data.skip = trace->skip;
 	data.no_sched_functions = nosched;
@@ -118,6 +122,7 @@ static noinline void __save_stack_trace(struct task_struct *tsk,
 		 */
 		if (trace->nr_entries < trace->max_entries)
 			trace->entries[trace->nr_entries++] = ULONG_MAX;
+		put_task_stack(tsk);
 		return;
 #else
 		frame.fp = thread_saved_fp(tsk);
@@ -137,6 +142,8 @@ static noinline void __save_stack_trace(struct task_struct *tsk,
 	walk_stackframe(&frame, save_trace, &data);
 	if (trace->nr_entries < trace->max_entries)
 		trace->entries[trace->nr_entries++] = ULONG_MAX;
+
+	put_task_stack(tsk);
 }
 
 void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index badf02ca3693..ec128854016a 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -217,6 +217,9 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
 	if (!tsk)
 		tsk = current;
 
+	if (!try_get_task_stack(tsk))
+		return;
+
 	if (regs) {
 		fp = frame_pointer(regs);
 		mode = processor_mode(regs);
@@ -240,6 +243,8 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
 
 	if (ok)
 		c_backtrace(fp, mode);
+
+	put_task_stack(tsk);
 }
 #endif
 
@@ -285,8 +290,12 @@ static int __die(const char *str, int err, struct pt_regs *regs)
 		 TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), end_of_stack(tsk));
 
 	if (!user_mode(regs) || in_interrupt()) {
-		dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp,
-			 THREAD_SIZE + (unsigned long)task_stack_page(tsk));
+		unsigned long stack_page = try_get_task_stack(tsk);
+		if (stack_page) {
+			dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp,
+				 THREAD_SIZE + stack_page);
+			put_task_stack(tsk);
+		}
 		dump_backtrace(regs, tsk);
 		dump_instr(KERN_EMERG, regs);
 	}
-- 
2.18.0.rc1.244.gcf134e6275-goog

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC v2 1/4] arm: Store address of thread_info in sp^
  2018-06-18 15:30 ` [RFC v2 1/4] arm: Store address of thread_info in sp^ Zubin Mithra
@ 2018-06-26  9:10   ` Ard Biesheuvel
  2018-06-26  9:24   ` Russell King - ARM Linux
  1 sibling, 0 replies; 9+ messages in thread
From: Ard Biesheuvel @ 2018-06-26  9:10 UTC (permalink / raw)
  To: linux-arm-kernel

On 18 June 2018 at 17:30, Zubin Mithra <zsm@chromium.org> wrote:
> There is a need to store thread_info in a register so that subsequent
> patches can move thread_info into task_struct. This would also
> facilitate having separate IRQ stacks.
>
> Banked register sp is an unused scratch register in EL1 context. We can
> utilize this register for stashing the current thread_info.
>
> The macro save_ti_sp_usr is used to stash the address of thread_info
> into sp^. The macro get_thread_info is modified to retrieve thread_info
> from sp^. Additionally, upon context switch, sp^ is set to current's
> thread_info by using set_sp_usr.
>
> Signed-off-by: Zubin Mithra <zsm@chromium.org>
> ---
>  arch/arm/include/asm/assembler.h   | 27 ++++++++++++++++++++++-----
>  arch/arm/include/asm/switch_to.h   | 11 +++++++++++
>  arch/arm/include/asm/thread_info.h | 14 ++++++++++++--
>  arch/arm/kernel/entry-armv.S       |  5 ++++-
>  arch/arm/kernel/entry-common.S     |  2 ++
>  arch/arm/kernel/head-common.S      |  2 ++
>  arch/arm/kernel/head.S             |  1 +
>  7 files changed, 54 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
> index 0cd4dccbae78..be18a364f590 100644
> --- a/arch/arm/include/asm/assembler.h
> +++ b/arch/arm/include/asm/assembler.h
> @@ -205,11 +205,28 @@
>  /*
>   * Get current thread_info.
>   */
> -       .macro  get_thread_info, rd
> - 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
> +       .macro get_thread_info, rd
> +       sub sp, #4
> +       stm sp, {sp}^
> +       pop {\rd}
> +       .endm
> +
> +       .macro save_ti_sp_usr, tmp, restore=0
> +       .if \restore
> +       push    {\tmp}
> +       .endif
> +
> + ARM(  mov     \tmp, sp, lsr #THREAD_SIZE_ORDER + PAGE_SHIFT   )
> + THUMB(        mov     \tmp, sp                        )
> + THUMB(        lsr     \tmp, \tmp, #THREAD_SIZE_ORDER + PAGE_SHIFT     )
> +       mov     \tmp, \tmp, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT
> +       push    {\tmp}
> +       ldm     sp, {sp}^
> +       add     sp, 4
> +
> +       .if \restore
> +       pop     {\tmp}
> +       .endif
>         .endm
>

Sadly, ldm/stm rN, {sp}^ only work in ARM mode, so these changes break
the Thumb-2 build. Note that ARMv7-M cores are Thumb2 only, so you
can't really work around it by switching to ARM mode and back either.

>  /*
> diff --git a/arch/arm/include/asm/switch_to.h b/arch/arm/include/asm/switch_to.h
> index d3e937dcee4d..5b4572f78cf4 100644
> --- a/arch/arm/include/asm/switch_to.h
> +++ b/arch/arm/include/asm/switch_to.h
> @@ -16,6 +16,16 @@
>  #define __complete_pending_tlbi()
>  #endif
>
> +static inline void set_sp_usr(unsigned long ti)
> +{
> +       asm volatile(
> +               "push {%0}\n"
> +               "ldm sp, {sp}^\n"
> +               "add sp, #4\n"
> +               :: "r"(ti)
> +       );
> +}
> +
>  /*
>   * switch_to(prev, next) should switch from task `prev' to `next'
>   * `prev' will never be the same as `next'.  schedule() itself
> @@ -27,6 +37,7 @@ extern struct task_struct *__switch_to(struct task_struct *, struct thread_info
>  do {                                                                   \
>         __complete_pending_tlbi();                                      \
>         last = __switch_to(prev,task_thread_info(prev), task_thread_info(next));        \
> +       set_sp_usr(current_stack_pointer & ~(THREAD_SIZE - 1));         \
>  } while (0)
>
>  #endif /* __ASM_ARM_SWITCH_TO_H */
> diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
> index e71cc35de163..4a351e0aba0e 100644
> --- a/arch/arm/include/asm/thread_info.h
> +++ b/arch/arm/include/asm/thread_info.h
> @@ -80,6 +80,7 @@ struct thread_info {
>   */
>  register unsigned long current_stack_pointer asm ("sp");
>
> +
>  /*
>   * how to get the thread information struct from C
>   */
> @@ -87,8 +88,17 @@ static inline struct thread_info *current_thread_info(void) __attribute_const__;
>
>  static inline struct thread_info *current_thread_info(void)
>  {
> -       return (struct thread_info *)
> -               (current_stack_pointer & ~(THREAD_SIZE - 1));
> +       unsigned long ti;
> +
> +       asm volatile(
> +               "sub sp, #4\n"
> +               "stm sp, {sp}^\n"
> +               "ldr %0, [sp]\n"
> +               "add sp, #4\n"
> +               : "=r" (ti)
> +       );
> +
> +       return (struct thread_info *)ti;
>  }
>
>  #define thread_saved_pc(tsk)   \
> diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
> index 179a9f6bd1e3..af79f9053530 100644
> --- a/arch/arm/kernel/entry-armv.S
> +++ b/arch/arm/kernel/entry-armv.S
> @@ -181,7 +181,8 @@ ENDPROC(__und_invalid)
>         @
>         stmia   r7, {r2 - r6}
>
> -       get_thread_info tsk
> +       save_ti_sp_usr tsk restore=0
> +
>         ldr     r0, [tsk, #TI_ADDR_LIMIT]
>         mov     r1, #TASK_SIZE
>         str     r1, [tsk, #TI_ADDR_LIMIT]
> @@ -411,6 +412,8 @@ ENDPROC(__fiq_abt)
>         uaccess_disable ip
>         .endif
>
> +       save_ti_sp_usr tsk restore=0
> +
>         @ Enable the alignment trap while in kernel mode
>   ATRAP(        teq     r8, r7)
>   ATRAP( mcrne  p15, 0, r8, c1, c0, 0)
> diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
> index 106a1466518d..0dbeaccebf62 100644
> --- a/arch/arm/kernel/entry-common.S
> +++ b/arch/arm/kernel/entry-common.S
> @@ -149,6 +149,7 @@ ENDPROC(ret_to_user)
>   * This is how we return from a fork.
>   */
>  ENTRY(ret_from_fork)
> +       save_ti_sp_usr  tsk
>         bl      schedule_tail
>         cmp     r5, #0
>         movne   r0, r4
> @@ -185,6 +186,7 @@ ENTRY(vector_swi)
>         asm_trace_hardirqs_on save=0
>         enable_irq_notrace
>         ct_user_exit save=0
> +       save_ti_sp_usr tsk
>
>         /*
>          * Get the system call number.
> diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
> index 6e0375e7db05..84e649144a32 100644
> --- a/arch/arm/kernel/head-common.S
> +++ b/arch/arm/kernel/head-common.S
> @@ -109,6 +109,8 @@ __mmap_switched:
>         mov     r1, #0
>         bl      memset                          @ clear .bss
>
> +       save_ti_sp_usr r9
> +
>         ldmia   r4, {r0, r1, r2, r3}
>         str     r9, [r0]                        @ Save processor ID
>         str     r7, [r1]                        @ Save machine type
> diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
> index 6b1148cafffd..66bba1b27d2c 100644
> --- a/arch/arm/kernel/head.S
> +++ b/arch/arm/kernel/head.S
> @@ -418,6 +418,7 @@ ENDPROC(secondary_startup_arm)
>  ENTRY(__secondary_switched)
>         ldr     sp, [r7, #12]                   @ get secondary_data.stack
>         mov     fp, #0
> +       save_ti_sp_usr r0
>         b       secondary_start_kernel
>  ENDPROC(__secondary_switched)
>
> --
> 2.18.0.rc1.244.gcf134e6275-goog
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC v2 0/4] arm: Moving thread_info into task_struct
  2018-06-18 15:30 [RFC v2 0/4] arm: Moving thread_info into task_struct Zubin Mithra
                   ` (3 preceding siblings ...)
  2018-06-18 15:30 ` [RFC v2 4/4] arm: add refcounting for task stacks Zubin Mithra
@ 2018-06-26  9:14 ` Russell King - ARM Linux
  4 siblings, 0 replies; 9+ messages in thread
From: Russell King - ARM Linux @ 2018-06-26  9:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jun 18, 2018 at 08:30:49AM -0700, Zubin Mithra wrote:
> These are a set of preparatory patches for moving the thread_info
> into task_struct for ARM. The patches that perform that actual move
> are not implemented yet.

You don't explain why this is desirable or even wanted in your covering
message.  You need to do that rather than expecting that everyone knows
why you want these changes.

> These patches have only been tested on QEMU using the following boards.
> - versatilepb
> - vexpress-a9
> 
> [v2 changes]
> - Add a patch that stores thread_info in sp^
> 
> Zubin Mithra (4):
>   arm: Store address of thread_info in sp^
>   arm: factor out current_stack_pointer
>   arm: make cpu a percpu variable
>   arm: add refcounting for task stacks
> 
>  arch/arm/include/asm/assembler.h     | 27 ++++++++++++++++++++++-----
>  arch/arm/include/asm/percpu.h        |  2 ++
>  arch/arm/include/asm/smp.h           | 11 ++++++++++-
>  arch/arm/include/asm/stack_pointer.h |  9 +++++++++
>  arch/arm/include/asm/switch_to.h     | 11 +++++++++++
>  arch/arm/include/asm/thread_info.h   | 19 ++++++++++++-------
>  arch/arm/kernel/entry-armv.S         |  5 ++++-
>  arch/arm/kernel/entry-common.S       |  2 ++
>  arch/arm/kernel/head-common.S        |  2 ++
>  arch/arm/kernel/head.S               |  1 +
>  arch/arm/kernel/process.c            | 21 +++++++++++++++------
>  arch/arm/kernel/return_address.c     |  1 +
>  arch/arm/kernel/setup.c              |  2 +-
>  arch/arm/kernel/smp.c                | 13 +++++++++++--
>  arch/arm/kernel/stacktrace.c         |  8 ++++++++
>  arch/arm/kernel/topology.c           |  2 ++
>  arch/arm/kernel/traps.c              | 13 +++++++++++--
>  arch/arm/kernel/unwind.c             |  1 +
>  18 files changed, 125 insertions(+), 25 deletions(-)
>  create mode 100644 arch/arm/include/asm/stack_pointer.h
> 
> -- 
> 2.18.0.rc1.244.gcf134e6275-goog
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC v2 1/4] arm: Store address of thread_info in sp^
  2018-06-18 15:30 ` [RFC v2 1/4] arm: Store address of thread_info in sp^ Zubin Mithra
  2018-06-26  9:10   ` Ard Biesheuvel
@ 2018-06-26  9:24   ` Russell King - ARM Linux
  1 sibling, 0 replies; 9+ messages in thread
From: Russell King - ARM Linux @ 2018-06-26  9:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jun 18, 2018 at 08:30:50AM -0700, Zubin Mithra wrote:
> There is a need to store thread_info in a register so that subsequent
> patches can move thread_info into task_struct. This would also
> facilitate having separate IRQ stacks.
> 
> Banked register sp is an unused scratch register in EL1 context. We can
> utilize this register for stashing the current thread_info.
> 
> The macro save_ti_sp_usr is used to stash the address of thread_info
> into sp^. The macro get_thread_info is modified to retrieve thread_info
> from sp^. Additionally, upon context switch, sp^ is set to current's
> thread_info by using set_sp_usr.
> 
> Signed-off-by: Zubin Mithra <zsm@chromium.org>
> ---
>  arch/arm/include/asm/assembler.h   | 27 ++++++++++++++++++++++-----
>  arch/arm/include/asm/switch_to.h   | 11 +++++++++++
>  arch/arm/include/asm/thread_info.h | 14 ++++++++++++--
>  arch/arm/kernel/entry-armv.S       |  5 ++++-
>  arch/arm/kernel/entry-common.S     |  2 ++
>  arch/arm/kernel/head-common.S      |  2 ++
>  arch/arm/kernel/head.S             |  1 +
>  7 files changed, 54 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
> index 0cd4dccbae78..be18a364f590 100644
> --- a/arch/arm/include/asm/assembler.h
> +++ b/arch/arm/include/asm/assembler.h
> @@ -205,11 +205,28 @@
>  /*
>   * Get current thread_info.
>   */
> -	.macro	get_thread_info, rd
> - 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
> +	.macro get_thread_info, rd
> +	sub sp, #4
> +	stm sp, {sp}^

What isn't mentioned in the ARM ARM is that you need at least one
instruction here that does not access any of the banked registers.
Ditto for ldm rn, {...}^ form.

Have you done performance analysis of this patch?

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC v2 4/4] arm: add refcounting for task stacks
  2018-06-18 15:30 ` [RFC v2 4/4] arm: add refcounting for task stacks Zubin Mithra
@ 2018-06-26  9:27   ` Russell King - ARM Linux
  0 siblings, 0 replies; 9+ messages in thread
From: Russell King - ARM Linux @ 2018-06-26  9:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jun 18, 2018 at 08:30:53AM -0700, Zubin Mithra wrote:
> @@ -285,8 +290,12 @@ static int __die(const char *str, int err, struct pt_regs *regs)
>  		 TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), end_of_stack(tsk));
>  
>  	if (!user_mode(regs) || in_interrupt()) {
> -		dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp,
> -			 THREAD_SIZE + (unsigned long)task_stack_page(tsk));
> +		unsigned long stack_page = try_get_task_stack(tsk);
> +		if (stack_page) {
> +			dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp,
> +				 THREAD_SIZE + stack_page);
> +			put_task_stack(tsk);
> +		}

This one can't - we're running in the context of the task, and so the
stack pages are in use by the CPU in this very function.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-06-26  9:27 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-18 15:30 [RFC v2 0/4] arm: Moving thread_info into task_struct Zubin Mithra
2018-06-18 15:30 ` [RFC v2 1/4] arm: Store address of thread_info in sp^ Zubin Mithra
2018-06-26  9:10   ` Ard Biesheuvel
2018-06-26  9:24   ` Russell King - ARM Linux
2018-06-18 15:30 ` [RFC v2 2/4] arm: factor out current_stack_pointer Zubin Mithra
2018-06-18 15:30 ` [RFC v2 3/4] arm: make cpu a percpu variable Zubin Mithra
2018-06-18 15:30 ` [RFC v2 4/4] arm: add refcounting for task stacks Zubin Mithra
2018-06-26  9:27   ` Russell King - ARM Linux
2018-06-26  9:14 ` [RFC v2 0/4] arm: Moving thread_info into task_struct Russell King - ARM Linux

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.