linux-arch.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/7] ARM: support THREAD_INFO_IN_TASK
       [not found] <id:20210907220038.91021-1-keithpac@amazon.com>
@ 2021-09-08 19:05 ` Keith Packard
  2021-09-08 19:05   ` [PATCH v4 1/7] ARM: Pass cpu number to secondary_start_kernel Keith Packard
                     ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Keith Packard @ 2021-09-08 19:05 UTC (permalink / raw)
  To: linux-kernel
  Cc: Abbott Liu, Alexei Starovoitov, Andrew Morton, Andrii Nakryiko,
	Anshuman Khandual, Ard Biesheuvel, Arnd Bergmann, Ben Segall,
	Bjorn Andersson, bpf, Christoph Lameter, Daniel Borkmann,
	Daniel Bristot de Oliveira, Dennis Zhou, devicetree,
	Dietmar Eggemann, Florian Fainelli, Frank Rowand,
	Geert Uytterhoeven, Ingo Molnar, Jason Wang, Jens Axboe,
	Joe Perches, John Fastabend, Juri Lelli, Keith Packard, KP Singh,
	kvm, Linus Walleij, linux-arch, linux-arm-kernel, linux-mm,
	Manivannan Sadhasivam, Marc Zyngier, Martin KaFai Lau,
	Mel Gorman, Michael Ellerman, Michael S. Tsirkin, Miguel Ojeda,
	Mike Rapoport, netdev, Nick Desaulniers, Nick Desaulniers,
	Nicolas Pitre, Peter Zijlstra, Rob Herring, Russell King,
	Song Liu, Srikar Dronamraju, Steven Rostedt, Tejun Heo,
	Thomas Gleixner, Uwe Kleine-König, Valentin Schneider,
	Vincent Guittot, virtualization, Wolfram Sang (Renesas),
	YiFei Zhu, Yonghong Song

Placing thread_info in the kernel stack leaves it vulnerable to stack
overflow attacks. This short series addresses that by using the
existing THREAD_INFO_IN_TASK infrastructure.

This is the fourth version of this series, in this version the changes
are restricted to hardware which provides the TPIDRPRW register. This
register is repurposed from holding the per_cpu_offset value to
holding the 'current' value as that allows fetching this value
atomically so that it can be used in a preemptable context.

The series is broken into seven pieces:

 1) Change the secondary_start_kernel API to receive the cpu
    number. This avoids needing to be able to find this value independently in
    future patches.

 2) Change the secondary_start_kernel API to also receive the 'task'
    value. Passing the value to this function also avoids needing to
    be able to discover it independently.

 3) A cleanup which avoids assuming that THREAD_INFO_IN_TASK is not set.

 4) Patches across the kernel which ensure that linux/sched.h has been
    included whenever raw_smp_processor_id() is used.

 5) Disable the optimization storing per_cpu_offset in TPIDRPRW. This
    leaves the register free to hold 'current' instead.

 6) Use TPIDRPRW for 'current'. This is enabled for either CPU_V6K or
    CPU_V7, but not if CPU_V6 is also enabled.

 7) Enable THREAD_INFO_IN_TASK whenever TPIDRPRW is used to hold 'current'.

Signed-off-by: Keith Packard <keithpac@amazon.com>

Keith Packard (7):
  ARM: Pass cpu number to secondary_start_kernel
  ARM: Pass task to secondary_start_kernel
  ARM: Use smp_processor_id() in vfp_pm_suspend instead of ti->cpu
  Make sure task_struct is available for raw_smp_processor_id
  ARM: Stop using TPIDRPRW to hold per_cpu_offset
  ARM: Use TPIDRPRW for current
  ARM: Move thread_info into task_struct (v7 only)

 arch/arm/Kconfig                   |  5 +++
 arch/arm/include/asm/assembler.h   | 12 +++++++
 arch/arm/include/asm/current.h     | 54 ++++++++++++++++++++++++++++++
 arch/arm/include/asm/percpu.h      | 31 -----------------
 arch/arm/include/asm/smp.h         |  8 ++++-
 arch/arm/include/asm/thread_info.h | 12 ++++++-
 arch/arm/kernel/asm-offsets.c      |  4 +++
 arch/arm/kernel/entry-armv.S       |  8 +++++
 arch/arm/kernel/head-nommu.S       |  2 ++
 arch/arm/kernel/head.S             |  2 ++
 arch/arm/kernel/setup.c            | 14 +-------
 arch/arm/kernel/smp.c              | 16 +++++----
 arch/arm/mm/proc-v7-bugs.c         |  1 +
 arch/arm/vfp/vfpmodule.c           | 15 +++++++--
 drivers/vhost/vhost.c              |  1 +
 drivers/vhost/vhost.h              |  1 +
 include/asm-generic/irq_regs.h     |  1 +
 include/linux/of_address.h         |  1 +
 include/linux/random.h             |  1 +
 include/linux/topology.h           |  1 +
 init/calibrate.c                   |  1 +
 kernel/bpf/bpf_lru_list.h          |  1 +
 kernel/bpf/percpu_freelist.h       |  1 +
 kernel/sched/cpuacct.c             |  2 +-
 lib/irq_regs.c                     |  1 +
 25 files changed, 140 insertions(+), 56 deletions(-)
 create mode 100644 arch/arm/include/asm/current.h

-- 
2.33.0


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

* [PATCH v4 1/7] ARM: Pass cpu number to secondary_start_kernel
  2021-09-08 19:05 ` [PATCH v4 0/7] ARM: support THREAD_INFO_IN_TASK Keith Packard
@ 2021-09-08 19:05   ` Keith Packard
  2021-09-08 19:06   ` [PATCH v4 2/7] ARM: Pass task " Keith Packard
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Keith Packard @ 2021-09-08 19:05 UTC (permalink / raw)
  To: linux-kernel
  Cc: Abbott Liu, Alexei Starovoitov, Andrew Morton, Andrii Nakryiko,
	Anshuman Khandual, Ard Biesheuvel, Arnd Bergmann, Ben Segall,
	Bjorn Andersson, bpf, Christoph Lameter, Daniel Borkmann,
	Daniel Bristot de Oliveira, Dennis Zhou, devicetree,
	Dietmar Eggemann, Florian Fainelli, Frank Rowand,
	Geert Uytterhoeven, Ingo Molnar, Jason Wang, Jens Axboe,
	Joe Perches, John Fastabend, Juri Lelli, Keith Packard, KP Singh,
	kvm, Linus Walleij, linux-arch, linux-arm-kernel, linux-mm,
	Manivannan Sadhasivam, Marc Zyngier, Martin KaFai Lau,
	Mel Gorman, Michael Ellerman, Michael S. Tsirkin, Miguel Ojeda,
	Mike Rapoport, netdev, Nick Desaulniers, Nick Desaulniers,
	Nicolas Pitre, Peter Zijlstra, Rob Herring, Russell King,
	Song Liu, Srikar Dronamraju, Steven Rostedt, Tejun Heo,
	Thomas Gleixner, Uwe Kleine-König, Valentin Schneider,
	Vincent Guittot, virtualization, Wolfram Sang (Renesas),
	YiFei Zhu, Yonghong Song

Instead of pulling the CPU value out of the thread_info struct, pass
it as an argument. When first initializing secondary processors, this
is done by stashing the value in the secondary_data struct. When
restarting idle processors, the previous CPU value is passed.

Because the cpu is now known at the top of secondary_start_kernel, the
per_cpu_offset value can now be set at this point, instead of in
cpu_init where it was also incorrectly setting the per_cpu_offset for
the boot processor before that value had been computed.

Signed-off-by: Keith Packard <keithpac@amazon.com>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm/include/asm/smp.h   |  3 ++-
 arch/arm/kernel/head-nommu.S |  1 +
 arch/arm/kernel/head.S       |  1 +
 arch/arm/kernel/setup.c      |  6 ------
 arch/arm/kernel/smp.c        | 14 +++++++++-----
 5 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index 5d508f5d56c4..86a7fd721556 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.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(unsigned int cpu);
 
 
 /*
@@ -61,6 +61,7 @@ struct secondary_data {
 	};
 	unsigned long swapper_pg_dir;
 	void *stack;
+	unsigned int cpu;
 };
 extern struct secondary_data secondary_data;
 extern void secondary_startup(void);
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 0fc814bbc34b..5aa8ef42717f 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -114,6 +114,7 @@ ENTRY(secondary_startup)
 	add	r12, r12, r10
 	ret	r12
 1:	bl	__after_proc_init
+	ldr	r0, [r7, #16]			@ set up cpu number
 	ldr	sp, [r7, #12]			@ set up the stack pointer
 	mov	fp, #0
 	b	secondary_start_kernel
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 7f62c5eccdf3..0e541af738e2 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -394,6 +394,7 @@ ENDPROC(secondary_startup_arm)
 
 ENTRY(__secondary_switched)
 	ldr_l	r7, secondary_data + 12		@ get secondary_data.stack
+	ldr_l	r0, secondary_data + 16		@ get secondary_data.cpu
 	mov	sp, r7
 	mov	fp, #0
 	b	secondary_start_kernel
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 73ca7797b92f..ca0201635fac 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -532,12 +532,6 @@ void notrace cpu_init(void)
 		BUG();
 	}
 
-	/*
-	 * This only works on resume and secondary cores. For booting on the
-	 * boot cpu, smp_prepare_boot_cpu is called after percpu area setup.
-	 */
-	set_my_cpu_offset(per_cpu_offset(cpu));
-
 	cpu_proc_init();
 
 	/*
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 74679240a9d8..55cb1689a4b3 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -153,6 +153,7 @@ 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.cpu = cpu;
 	sync_cache_w(&secondary_data);
 
 	/*
@@ -373,11 +374,14 @@ void arch_cpu_idle_dead(void)
 	 * cpu initialisation.  There's some initialisation which needs
 	 * to be repeated to undo the effects of taking the CPU offline.
 	 */
-	__asm__("mov	sp, %0\n"
+	__asm__("mov	r0, %1\n"
+	"	mov	sp, %0\n"
 	"	mov	fp, #0\n"
 	"	b	secondary_start_kernel"
 		:
-		: "r" (task_stack_page(current) + THREAD_SIZE - 8));
+		: "r" (task_stack_page(current) + THREAD_SIZE - 8),
+		  "r" (cpu)
+		: "r0");
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
@@ -400,10 +404,11 @@ 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(unsigned int cpu)
 {
 	struct mm_struct *mm = &init_mm;
-	unsigned int cpu;
+
+	set_my_cpu_offset(per_cpu_offset(cpu));
 
 	secondary_biglittle_init();
 
@@ -420,7 +425,6 @@ 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();
 	mmgrab(mm);
 	current->active_mm = mm;
 	cpumask_set_cpu(cpu, mm_cpumask(mm));
-- 
2.33.0


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

* [PATCH v4 2/7] ARM: Pass task to secondary_start_kernel
  2021-09-08 19:05 ` [PATCH v4 0/7] ARM: support THREAD_INFO_IN_TASK Keith Packard
  2021-09-08 19:05   ` [PATCH v4 1/7] ARM: Pass cpu number to secondary_start_kernel Keith Packard
@ 2021-09-08 19:06   ` Keith Packard
  2021-09-08 19:06   ` [PATCH v4 3/7] ARM: Use smp_processor_id() in vfp_pm_suspend instead of ti->cpu Keith Packard
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Keith Packard @ 2021-09-08 19:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: Abbott Liu, Alexei Starovoitov, Andrew Morton, Andrii Nakryiko,
	Anshuman Khandual, Ard Biesheuvel, Arnd Bergmann, Ben Segall,
	Bjorn Andersson, bpf, Christoph Lameter, Daniel Borkmann,
	Daniel Bristot de Oliveira, Dennis Zhou, devicetree,
	Dietmar Eggemann, Florian Fainelli, Frank Rowand,
	Geert Uytterhoeven, Ingo Molnar, Jason Wang, Jens Axboe,
	Joe Perches, John Fastabend, Juri Lelli, Keith Packard, KP Singh,
	kvm, Linus Walleij, linux-arch, linux-arm-kernel, linux-mm,
	Manivannan Sadhasivam, Marc Zyngier, Martin KaFai Lau,
	Mel Gorman, Michael Ellerman, Michael S. Tsirkin, Miguel Ojeda,
	Mike Rapoport, netdev, Nick Desaulniers, Nick Desaulniers,
	Nicolas Pitre, Peter Zijlstra, Rob Herring, Russell King,
	Song Liu, Srikar Dronamraju, Steven Rostedt, Tejun Heo,
	Thomas Gleixner, Uwe Kleine-König, Valentin Schneider,
	Vincent Guittot, virtualization, Wolfram Sang (Renesas),
	YiFei Zhu, Yonghong Song

This avoids needing to compute the task pointer in this function,
allowing it to be used as the source of identification in the future.

Signed-off-by: Keith Packard <keithpac@amazon.com>
---
 arch/arm/include/asm/smp.h   | 3 ++-
 arch/arm/kernel/head-nommu.S | 1 +
 arch/arm/kernel/head.S       | 1 +
 arch/arm/kernel/smp.c        | 8 +++++---
 4 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index 86a7fd721556..d43b64635d77 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.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(unsigned int cpu);
+asmlinkage void secondary_start_kernel(unsigned int cpu, struct task_struct *task);
 
 
 /*
@@ -62,6 +62,7 @@ struct secondary_data {
 	unsigned long swapper_pg_dir;
 	void *stack;
 	unsigned int cpu;
+	struct task_struct *task;
 };
 extern struct secondary_data secondary_data;
 extern void secondary_startup(void);
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 5aa8ef42717f..218715c135ed 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -115,6 +115,7 @@ ENTRY(secondary_startup)
 	ret	r12
 1:	bl	__after_proc_init
 	ldr	r0, [r7, #16]			@ set up cpu number
+	ldr	r1, [r7, #20]			@ set up task pointer
 	ldr	sp, [r7, #12]			@ set up the stack pointer
 	mov	fp, #0
 	b	secondary_start_kernel
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 0e541af738e2..4a6cb0b0808b 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -395,6 +395,7 @@ ENDPROC(secondary_startup_arm)
 ENTRY(__secondary_switched)
 	ldr_l	r7, secondary_data + 12		@ get secondary_data.stack
 	ldr_l	r0, secondary_data + 16		@ get secondary_data.cpu
+	ldr_l	r1, secondary_data + 20		@ get secondary_data.task
 	mov	sp, r7
 	mov	fp, #0
 	b	secondary_start_kernel
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 55cb1689a4b3..5e999f1f1aea 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -154,6 +154,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
 	secondary_data.swapper_pg_dir = get_arch_pgd(swapper_pg_dir);
 #endif
 	secondary_data.cpu = cpu;
+	secondary_data.task = idle;
 	sync_cache_w(&secondary_data);
 
 	/*
@@ -375,13 +376,14 @@ void arch_cpu_idle_dead(void)
 	 * to be repeated to undo the effects of taking the CPU offline.
 	 */
 	__asm__("mov	r0, %1\n"
+	"	mov	r1, %2\n"
 	"	mov	sp, %0\n"
 	"	mov	fp, #0\n"
 	"	b	secondary_start_kernel"
 		:
 		: "r" (task_stack_page(current) + THREAD_SIZE - 8),
-		  "r" (cpu)
-		: "r0");
+		  "r" (cpu), "r" (current)
+		: "r0", "r1");
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
@@ -404,7 +406,7 @@ 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(unsigned int cpu)
+asmlinkage void secondary_start_kernel(unsigned int cpu, struct task_struct *task)
 {
 	struct mm_struct *mm = &init_mm;
 
-- 
2.33.0


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

* [PATCH v4 3/7] ARM: Use smp_processor_id() in vfp_pm_suspend instead of ti->cpu
  2021-09-08 19:05 ` [PATCH v4 0/7] ARM: support THREAD_INFO_IN_TASK Keith Packard
  2021-09-08 19:05   ` [PATCH v4 1/7] ARM: Pass cpu number to secondary_start_kernel Keith Packard
  2021-09-08 19:06   ` [PATCH v4 2/7] ARM: Pass task " Keith Packard
@ 2021-09-08 19:06   ` Keith Packard
  2021-09-08 19:06   ` [PATCH v4 4/7] Make sure task_struct is available for raw_smp_processor_id Keith Packard
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Keith Packard @ 2021-09-08 19:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: Abbott Liu, Alexei Starovoitov, Andrew Morton, Andrii Nakryiko,
	Anshuman Khandual, Ard Biesheuvel, Arnd Bergmann, Ben Segall,
	Bjorn Andersson, bpf, Christoph Lameter, Daniel Borkmann,
	Daniel Bristot de Oliveira, Dennis Zhou, devicetree,
	Dietmar Eggemann, Florian Fainelli, Frank Rowand,
	Geert Uytterhoeven, Ingo Molnar, Jason Wang, Jens Axboe,
	Joe Perches, John Fastabend, Juri Lelli, Keith Packard, KP Singh,
	kvm, Linus Walleij, linux-arch, linux-arm-kernel, linux-mm,
	Manivannan Sadhasivam, Marc Zyngier, Martin KaFai Lau,
	Mel Gorman, Michael Ellerman, Michael S. Tsirkin, Miguel Ojeda,
	Mike Rapoport, netdev, Nick Desaulniers, Nick Desaulniers,
	Nicolas Pitre, Peter Zijlstra, Rob Herring, Russell King,
	Song Liu, Srikar Dronamraju, Steven Rostedt, Tejun Heo,
	Thomas Gleixner, Uwe Kleine-König, Valentin Schneider,
	Vincent Guittot, virtualization, Wolfram Sang (Renesas),
	YiFei Zhu, Yonghong Song

These are equivalent when thread_info contains the CPU value, but when
THREAD_INFO_IN_TASK is enabled, cpu moves to task_struct. Using the macro
allows either.

Signed-off-by: Keith Packard <keithpac@amazon.com>
---
 arch/arm/vfp/vfpmodule.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 2cb355c1b5b7..d7a3818da671 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -458,16 +458,16 @@ static int vfp_pm_suspend(void)
 
 		/* disable, just in case */
 		fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
-	} else if (vfp_current_hw_state[ti->cpu]) {
+	} else if (vfp_current_hw_state[smp_processor_id()]) {
 #ifndef CONFIG_SMP
 		fmxr(FPEXC, fpexc | FPEXC_EN);
-		vfp_save_state(vfp_current_hw_state[ti->cpu], fpexc);
+		vfp_save_state(vfp_current_hw_state[smp_processor_id()], fpexc);
 		fmxr(FPEXC, fpexc);
 #endif
 	}
 
 	/* clear any information we had about last context state */
-	vfp_current_hw_state[ti->cpu] = NULL;
+	vfp_current_hw_state[smp_processor_id()] = NULL;
 
 	return 0;
 }
-- 
2.33.0


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

* [PATCH v4 4/7] Make sure task_struct is available for raw_smp_processor_id
  2021-09-08 19:05 ` [PATCH v4 0/7] ARM: support THREAD_INFO_IN_TASK Keith Packard
                     ` (2 preceding siblings ...)
  2021-09-08 19:06   ` [PATCH v4 3/7] ARM: Use smp_processor_id() in vfp_pm_suspend instead of ti->cpu Keith Packard
@ 2021-09-08 19:06   ` Keith Packard
  2021-09-10 20:20     ` Rob Herring
  2021-09-08 19:06   ` [PATCH v4 5/7] ARM: Stop using TPIDRPRW to hold per_cpu_offset Keith Packard
                     ` (2 subsequent siblings)
  6 siblings, 1 reply; 9+ messages in thread
From: Keith Packard @ 2021-09-08 19:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: Abbott Liu, Alexei Starovoitov, Andrew Morton, Andrii Nakryiko,
	Anshuman Khandual, Ard Biesheuvel, Arnd Bergmann, Ben Segall,
	Bjorn Andersson, bpf, Christoph Lameter, Daniel Borkmann,
	Daniel Bristot de Oliveira, Dennis Zhou, devicetree,
	Dietmar Eggemann, Florian Fainelli, Frank Rowand,
	Geert Uytterhoeven, Ingo Molnar, Jason Wang, Jens Axboe,
	Joe Perches, John Fastabend, Juri Lelli, Keith Packard, KP Singh,
	kvm, Linus Walleij, linux-arch, linux-arm-kernel, linux-mm,
	Manivannan Sadhasivam, Marc Zyngier, Martin KaFai Lau,
	Mel Gorman, Michael Ellerman, Michael S. Tsirkin, Miguel Ojeda,
	Mike Rapoport, netdev, Nick Desaulniers, Nick Desaulniers,
	Nicolas Pitre, Peter Zijlstra, Rob Herring, Russell King,
	Song Liu, Srikar Dronamraju, Steven Rostedt, Tejun Heo,
	Thomas Gleixner, Uwe Kleine-König, Valentin Schneider,
	Vincent Guittot, virtualization, Wolfram Sang (Renesas),
	YiFei Zhu, Yonghong Song

To allow architectures to use the 'cpu' field in task_struct for cpu
identification, the task_struct must be visible whereever the
raw_smp_processor_id macro is used. It would be simplest to include
linux/sched.h from the relevant asm/smp.h file, but that file is
included from linux/sched.h, and the recursive include ends up with
several declarations in the wrong order.

To avoid this, the PowerPC architecture code has this ugly hack:

	#define raw_smp_processor_id() \
		(*(unsigned int *)((void *)current + _TASK_CPU))

As an alternative, placing includes of linux/sched.h in a few files
that are used along with asm/smp.h means we can use the task_struct
field directly.

Signed-off-by: Keith Packard <keithpac@amazon.com>
---
 arch/arm/mm/proc-v7-bugs.c     | 1 +
 drivers/vhost/vhost.c          | 1 +
 drivers/vhost/vhost.h          | 1 +
 include/asm-generic/irq_regs.h | 1 +
 include/linux/of_address.h     | 1 +
 include/linux/random.h         | 1 +
 include/linux/topology.h       | 1 +
 init/calibrate.c               | 1 +
 kernel/bpf/bpf_lru_list.h      | 1 +
 kernel/bpf/percpu_freelist.h   | 1 +
 kernel/sched/cpuacct.c         | 2 +-
 lib/irq_regs.c                 | 1 +
 12 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mm/proc-v7-bugs.c b/arch/arm/mm/proc-v7-bugs.c
index 114c05ab4dd9..9ea078c619a7 100644
--- a/arch/arm/mm/proc-v7-bugs.c
+++ b/arch/arm/mm/proc-v7-bugs.c
@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <linux/sched.h>
 #include <linux/arm-smccc.h>
 #include <linux/kernel.h>
 #include <linux/smp.h>
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 5ccb0705beae..e5a073bb5b1e 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -10,6 +10,7 @@
  * Generic code for virtio server in host kernel.
  */
 
+#include <linux/sched.h>
 #include <linux/eventfd.h>
 #include <linux/vhost.h>
 #include <linux/uio.h>
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index b063324c7669..963d08ff2a62 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -2,6 +2,7 @@
 #ifndef _VHOST_H
 #define _VHOST_H
 
+#include <linux/sched.h>
 #include <linux/eventfd.h>
 #include <linux/vhost.h>
 #include <linux/mm.h>
diff --git a/include/asm-generic/irq_regs.h b/include/asm-generic/irq_regs.h
index 2e7c6e89d42e..ab4ca7ab362c 100644
--- a/include/asm-generic/irq_regs.h
+++ b/include/asm-generic/irq_regs.h
@@ -8,6 +8,7 @@
 #ifndef _ASM_GENERIC_IRQ_REGS_H
 #define _ASM_GENERIC_IRQ_REGS_H
 
+#include <linux/sched.h>
 #include <linux/percpu.h>
 
 /*
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 88bc943405cd..60c30168d48d 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __OF_ADDRESS_H
 #define __OF_ADDRESS_H
+#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/errno.h>
 #include <linux/of.h>
diff --git a/include/linux/random.h b/include/linux/random.h
index f45b8be3e3c4..0accd9277e95 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -7,6 +7,7 @@
 #ifndef _LINUX_RANDOM_H
 #define _LINUX_RANDOM_H
 
+#include <linux/sched.h>
 #include <linux/bug.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
diff --git a/include/linux/topology.h b/include/linux/topology.h
index 7634cd737061..4bd993bc9513 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -27,6 +27,7 @@
 #ifndef _LINUX_TOPOLOGY_H
 #define _LINUX_TOPOLOGY_H
 
+#include <linux/sched.h>
 #include <linux/arch_topology.h>
 #include <linux/cpumask.h>
 #include <linux/bitops.h>
diff --git a/init/calibrate.c b/init/calibrate.c
index f3831272f113..45002e27e385 100644
--- a/init/calibrate.c
+++ b/init/calibrate.c
@@ -10,6 +10,7 @@
 #include <linux/init.h>
 #include <linux/timex.h>
 #include <linux/smp.h>
+#include <linux/sched.h>
 #include <linux/percpu.h>
 
 unsigned long lpj_fine;
diff --git a/kernel/bpf/bpf_lru_list.h b/kernel/bpf/bpf_lru_list.h
index 6b12f06ee18c..5aed0c288c76 100644
--- a/kernel/bpf/bpf_lru_list.h
+++ b/kernel/bpf/bpf_lru_list.h
@@ -4,6 +4,7 @@
 #ifndef __BPF_LRU_LIST_H_
 #define __BPF_LRU_LIST_H_
 
+#include <linux/sched.h>
 #include <linux/list.h>
 #include <linux/spinlock_types.h>
 
diff --git a/kernel/bpf/percpu_freelist.h b/kernel/bpf/percpu_freelist.h
index 3c76553cfe57..3bc7a2bbe79b 100644
--- a/kernel/bpf/percpu_freelist.h
+++ b/kernel/bpf/percpu_freelist.h
@@ -3,6 +3,7 @@
  */
 #ifndef __PERCPU_FREELIST_H__
 #define __PERCPU_FREELIST_H__
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/percpu.h>
 
diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c
index 104a1bade14f..fb5f52e889a4 100644
--- a/kernel/sched/cpuacct.c
+++ b/kernel/sched/cpuacct.c
@@ -5,8 +5,8 @@
  * Based on the work by Paul Menage (menage@google.com) and Balbir Singh
  * (balbir@in.ibm.com).
  */
-#include <asm/irq_regs.h>
 #include "sched.h"
+#include <asm/irq_regs.h>
 
 /* Time spent by the tasks of the CPU accounting group executing in ... */
 enum cpuacct_stat_index {
diff --git a/lib/irq_regs.c b/lib/irq_regs.c
index 0d545a93070e..c9d8235f6444 100644
--- a/lib/irq_regs.c
+++ b/lib/irq_regs.c
@@ -5,6 +5,7 @@
  * Written by David Howells (dhowells@redhat.com)
  */
 #include <linux/export.h>
+#include <linux/sched.h>
 #include <linux/percpu.h>
 #include <asm/irq_regs.h>
 
-- 
2.33.0


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

* [PATCH v4 5/7] ARM: Stop using TPIDRPRW to hold per_cpu_offset
  2021-09-08 19:05 ` [PATCH v4 0/7] ARM: support THREAD_INFO_IN_TASK Keith Packard
                     ` (3 preceding siblings ...)
  2021-09-08 19:06   ` [PATCH v4 4/7] Make sure task_struct is available for raw_smp_processor_id Keith Packard
@ 2021-09-08 19:06   ` Keith Packard
  2021-09-08 19:06   ` [PATCH v4 6/7] ARM: Use TPIDRPRW for current Keith Packard
  2021-09-08 19:06   ` [PATCH v4 7/7] ARM: Move thread_info into task_struct (v7 only) Keith Packard
  6 siblings, 0 replies; 9+ messages in thread
From: Keith Packard @ 2021-09-08 19:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: Abbott Liu, Alexei Starovoitov, Andrew Morton, Andrii Nakryiko,
	Anshuman Khandual, Ard Biesheuvel, Arnd Bergmann, Ben Segall,
	Bjorn Andersson, bpf, Christoph Lameter, Daniel Borkmann,
	Daniel Bristot de Oliveira, Dennis Zhou, devicetree,
	Dietmar Eggemann, Florian Fainelli, Frank Rowand,
	Geert Uytterhoeven, Ingo Molnar, Jason Wang, Jens Axboe,
	Joe Perches, John Fastabend, Juri Lelli, Keith Packard, KP Singh,
	kvm, Linus Walleij, linux-arch, linux-arm-kernel, linux-mm,
	Manivannan Sadhasivam, Marc Zyngier, Martin KaFai Lau,
	Mel Gorman, Michael Ellerman, Michael S. Tsirkin, Miguel Ojeda,
	Mike Rapoport, netdev, Nick Desaulniers, Nick Desaulniers,
	Nicolas Pitre, Peter Zijlstra, Rob Herring, Russell King,
	Song Liu, Srikar Dronamraju, Steven Rostedt, Tejun Heo,
	Thomas Gleixner, Uwe Kleine-König, Valentin Schneider,
	Vincent Guittot, virtualization, Wolfram Sang (Renesas),
	YiFei Zhu, Yonghong Song

We're going to store TPIDRPRW here instead

Signed-off-by: Keith Packard <keithpac@amazon.com>
---
 arch/arm/include/asm/percpu.h | 31 -------------------------------
 arch/arm/kernel/setup.c       |  7 -------
 arch/arm/kernel/smp.c         |  3 ---
 3 files changed, 41 deletions(-)

diff --git a/arch/arm/include/asm/percpu.h b/arch/arm/include/asm/percpu.h
index e2fcb3cfd3de..eeafcd6a3e01 100644
--- a/arch/arm/include/asm/percpu.h
+++ b/arch/arm/include/asm/percpu.h
@@ -7,37 +7,6 @@
 
 register unsigned long current_stack_pointer asm ("sp");
 
-/*
- * Same as asm-generic/percpu.h, except that we store the per cpu offset
- * in the TPIDRPRW. TPIDRPRW only exists on V6K and V7
- */
-#if defined(CONFIG_SMP) && !defined(CONFIG_CPU_V6)
-static inline void set_my_cpu_offset(unsigned long off)
-{
-	/* Set TPIDRPRW */
-	asm volatile("mcr p15, 0, %0, c13, c0, 4" : : "r" (off) : "memory");
-}
-
-static inline unsigned long __my_cpu_offset(void)
-{
-	unsigned long off;
-
-	/*
-	 * Read TPIDRPRW.
-	 * We want to allow caching the value, so avoid using volatile and
-	 * instead use a fake stack read to hazard against barrier().
-	 */
-	asm("mrc p15, 0, %0, c13, c0, 4" : "=r" (off)
-		: "Q" (*(const unsigned long *)current_stack_pointer));
-
-	return off;
-}
-#define __my_cpu_offset __my_cpu_offset()
-#else
-#define set_my_cpu_offset(x)	do {} while(0)
-
-#endif /* CONFIG_SMP */
-
 #include <asm-generic/percpu.h>
 
 #endif /* _ASM_ARM_PERCPU_H_ */
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index ca0201635fac..d0dc60afe54f 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -590,13 +590,6 @@ void __init smp_setup_processor_id(void)
 	for (i = 1; i < nr_cpu_ids; ++i)
 		cpu_logical_map(i) = i == cpu ? 0 : i;
 
-	/*
-	 * clear __my_cpu_offset on boot CPU to avoid hang caused by
-	 * using percpu variable early, for example, lockdep will
-	 * access percpu variable inside lock_release
-	 */
-	set_my_cpu_offset(0);
-
 	pr_info("Booting Linux on physical CPU 0x%x\n", mpidr);
 }
 
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 5e999f1f1aea..8ccf10b34f08 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -410,8 +410,6 @@ asmlinkage void secondary_start_kernel(unsigned int cpu, struct task_struct *tas
 {
 	struct mm_struct *mm = &init_mm;
 
-	set_my_cpu_offset(per_cpu_offset(cpu));
-
 	secondary_biglittle_init();
 
 	/*
@@ -495,7 +493,6 @@ 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()));
 }
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
-- 
2.33.0


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

* [PATCH v4 6/7] ARM: Use TPIDRPRW for current
  2021-09-08 19:05 ` [PATCH v4 0/7] ARM: support THREAD_INFO_IN_TASK Keith Packard
                     ` (4 preceding siblings ...)
  2021-09-08 19:06   ` [PATCH v4 5/7] ARM: Stop using TPIDRPRW to hold per_cpu_offset Keith Packard
@ 2021-09-08 19:06   ` Keith Packard
  2021-09-08 19:06   ` [PATCH v4 7/7] ARM: Move thread_info into task_struct (v7 only) Keith Packard
  6 siblings, 0 replies; 9+ messages in thread
From: Keith Packard @ 2021-09-08 19:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: Abbott Liu, Alexei Starovoitov, Andrew Morton, Andrii Nakryiko,
	Anshuman Khandual, Ard Biesheuvel, Arnd Bergmann, Ben Segall,
	Bjorn Andersson, bpf, Christoph Lameter, Daniel Borkmann,
	Daniel Bristot de Oliveira, Dennis Zhou, devicetree,
	Dietmar Eggemann, Florian Fainelli, Frank Rowand,
	Geert Uytterhoeven, Ingo Molnar, Jason Wang, Jens Axboe,
	Joe Perches, John Fastabend, Juri Lelli, Keith Packard, KP Singh,
	kvm, Linus Walleij, linux-arch, linux-arm-kernel, linux-mm,
	Manivannan Sadhasivam, Marc Zyngier, Martin KaFai Lau,
	Mel Gorman, Michael Ellerman, Michael S. Tsirkin, Miguel Ojeda,
	Mike Rapoport, netdev, Nick Desaulniers, Nick Desaulniers,
	Nicolas Pitre, Peter Zijlstra, Rob Herring, Russell King,
	Song Liu, Srikar Dronamraju, Steven Rostedt, Tejun Heo,
	Thomas Gleixner, Uwe Kleine-König, Valentin Schneider,
	Vincent Guittot, virtualization, Wolfram Sang (Renesas),
	YiFei Zhu, Yonghong Song

Store current task pointer in CPU thread ID register TPIDRPRW so that
accessing it doesn't depend on being able to locate thread_info off of
the kernel stack pointer.

Signed-off-by: Keith Packard <keithpac@amazon.com>
---
 arch/arm/Kconfig                 |  4 +++
 arch/arm/include/asm/assembler.h |  8 +++++
 arch/arm/include/asm/current.h   | 54 ++++++++++++++++++++++++++++++++
 arch/arm/kernel/entry-armv.S     |  4 +++
 arch/arm/kernel/setup.c          |  1 +
 arch/arm/kernel/smp.c            |  1 +
 6 files changed, 72 insertions(+)
 create mode 100644 arch/arm/include/asm/current.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 24804f11302d..414fe23fd5ac 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1172,6 +1172,10 @@ config SMP_ON_UP
 
 	  If you don't know what to do here, say Y.
 
+config CURRENT_POINTER_IN_TPIDRPRW
+	def_bool y
+	depends on (CPU_V6K || CPU_V7) && !CPU_V6
+
 config ARM_CPU_TOPOLOGY
 	bool "Support cpu topology definition"
 	depends on SMP && CPU_V7
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index e2b1fd558bf3..ea12fe3bb589 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -209,6 +209,14 @@
 	mov	\rd, \rd, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT
 	.endm
 
+/*
+ * Set current task_info
+ * @src: Source register containing task_struct pointer
+ */
+	.macro	set_current src : req
+	mcr	p15, 0, \src, c13, c0, 4
+	.endm
+
 /*
  * Increment/decrement the preempt count.
  */
diff --git a/arch/arm/include/asm/current.h b/arch/arm/include/asm/current.h
new file mode 100644
index 000000000000..ec25737855e5
--- /dev/null
+++ b/arch/arm/include/asm/current.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright © 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Author Keith Packard <keithpac@amazon.com>
+ */
+
+#ifndef _ASM_ARM_CURRENT_H_
+#define _ASM_ARM_CURRENT_H_
+
+#ifndef __ASSEMBLY__
+
+register unsigned long current_stack_pointer asm ("sp");
+
+/*
+ * Same as asm-generic/current.h, except that we store current
+ * in TPIDRPRW. TPIDRPRW only exists on V6K and V7
+ */
+#ifdef CONFIG_CURRENT_POINTER_IN_TPIDRPRW
+
+struct task_struct;
+
+static inline void set_current(struct task_struct *tsk)
+{
+	/* Set TPIDRPRW */
+	asm volatile("mcr p15, 0, %0, c13, c0, 4" : : "r" (tsk) : "memory");
+}
+
+static __always_inline struct task_struct *get_current(void)
+{
+	struct task_struct *tsk;
+
+	/*
+	 * Read TPIDRPRW.
+	 * We want to allow caching the value, so avoid using volatile and
+	 * instead use a fake stack read to hazard against barrier().
+	 */
+	asm("mrc p15, 0, %0, c13, c0, 4" : "=r" (tsk)
+		: "Q" (*(const unsigned long *)current_stack_pointer));
+
+	return tsk;
+}
+#define current get_current()
+#else
+
+#define set_current(tsk) do {} while (0)
+
+#include <asm-generic/current.h>
+
+#endif /* CONFIG_SMP */
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_ARM_CURRENT_H_ */
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 0ea8529a4872..db3947ee9c3e 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -761,6 +761,10 @@ ENTRY(__switch_to)
 	ldr	r6, [r2, #TI_CPU_DOMAIN]
 #endif
 	switch_tls r1, r4, r5, r3, r7
+#ifdef CONFIG_CURRENT_POINTER_IN_TPIDRPRW
+	ldr	r7, [r2, #TI_TASK]
+	set_current r7
+#endif
 #if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP)
 	ldr	r7, [r2, #TI_TASK]
 	ldr	r8, =__stack_chk_guard
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index d0dc60afe54f..2fdf8c31d6c9 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -586,6 +586,7 @@ void __init smp_setup_processor_id(void)
 	u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0;
 	u32 cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
 
+	set_current(&init_task);
 	cpu_logical_map(0) = cpu;
 	for (i = 1; i < nr_cpu_ids; ++i)
 		cpu_logical_map(i) = i == cpu ? 0 : i;
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 8ccf10b34f08..09771916442a 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -410,6 +410,7 @@ asmlinkage void secondary_start_kernel(unsigned int cpu, struct task_struct *tas
 {
 	struct mm_struct *mm = &init_mm;
 
+	set_current(task);
 	secondary_biglittle_init();
 
 	/*
-- 
2.33.0


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

* [PATCH v4 7/7] ARM: Move thread_info into task_struct (v7 only)
  2021-09-08 19:05 ` [PATCH v4 0/7] ARM: support THREAD_INFO_IN_TASK Keith Packard
                     ` (5 preceding siblings ...)
  2021-09-08 19:06   ` [PATCH v4 6/7] ARM: Use TPIDRPRW for current Keith Packard
@ 2021-09-08 19:06   ` Keith Packard
  6 siblings, 0 replies; 9+ messages in thread
From: Keith Packard @ 2021-09-08 19:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: Abbott Liu, Alexei Starovoitov, Andrew Morton, Andrii Nakryiko,
	Anshuman Khandual, Ard Biesheuvel, Arnd Bergmann, Ben Segall,
	Bjorn Andersson, bpf, Christoph Lameter, Daniel Borkmann,
	Daniel Bristot de Oliveira, Dennis Zhou, devicetree,
	Dietmar Eggemann, Florian Fainelli, Frank Rowand,
	Geert Uytterhoeven, Ingo Molnar, Jason Wang, Jens Axboe,
	Joe Perches, John Fastabend, Juri Lelli, Keith Packard, KP Singh,
	kvm, Linus Walleij, linux-arch, linux-arm-kernel, linux-mm,
	Manivannan Sadhasivam, Marc Zyngier, Martin KaFai Lau,
	Mel Gorman, Michael Ellerman, Michael S. Tsirkin, Miguel Ojeda,
	Mike Rapoport, netdev, Nick Desaulniers, Nick Desaulniers,
	Nicolas Pitre, Peter Zijlstra, Rob Herring, Russell King,
	Song Liu, Srikar Dronamraju, Steven Rostedt, Tejun Heo,
	Thomas Gleixner, Uwe Kleine-König, Valentin Schneider,
	Vincent Guittot, virtualization, Wolfram Sang (Renesas),
	YiFei Zhu, Yonghong Song

This avoids many stack overflow attacks which modified the thread_info
structure by moving that into the task_struct as is done is almost all
other architectures.

This also involved removing the 'cpu' member from the thread_info
struct and using the one added to the task_struct instead by the
THREAD_INFO_IN_TASK code.

This code is currently enabled only for v7 hardware as most other ARM
architectures do not have the TPIDRPRW register that is used to
store the current value. It could probably be enabled for v6k
architectures as well, but I haven't tested that.

With the TPIDRPRW register, the kernel can identify the current
cpu. Without that register, there's a circular dependency between the
current cpu and 'current' — know one and you can find the
other. Leaving the thread_info in the kernel stack lets you find the
cpu number independently.

Signed-off-by: Keith Packard <keithpac@amazon.com>
---
 arch/arm/Kconfig                   |  1 +
 arch/arm/include/asm/assembler.h   |  4 ++++
 arch/arm/include/asm/smp.h         |  4 ++++
 arch/arm/include/asm/thread_info.h | 12 +++++++++++-
 arch/arm/kernel/asm-offsets.c      |  4 ++++
 arch/arm/kernel/entry-armv.S       |  4 ++++
 arch/arm/vfp/vfpmodule.c           |  9 +++++++++
 7 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 414fe23fd5ac..5846b4f5444b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -128,6 +128,7 @@ config ARM
 	select RTC_LIB
 	select SET_FS
 	select SYS_SUPPORTS_APM_EMULATION
+	select THREAD_INFO_IN_TASK if CURRENT_POINTER_IN_TPIDRPRW
 	# Above selects are sorted alphabetically; please add new ones
 	# according to that.  Thanks.
 	help
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index ea12fe3bb589..b23d2b87184a 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -203,10 +203,14 @@
  * Get current thread_info.
  */
 	.macro	get_thread_info, rd
+#ifdef CONFIG_THREAD_INFO_IN_TASK
+	mrc	p15, 0, \rd, c13, c0, 4
+#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
 
 /*
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index d43b64635d77..beb3872645d9 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -15,7 +15,11 @@
 # error "<asm/smp.h> included in non-SMP build"
 #endif
 
+#ifdef CONFIG_THREAD_INFO_IN_TASK
+#define raw_smp_processor_id() (current->cpu)
+#else
 #define raw_smp_processor_id() (current_thread_info()->cpu)
+#endif
 
 struct seq_file;
 
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 70d4cbc49ae1..6b67703ca16a 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -55,8 +55,10 @@ struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	int			preempt_count;	/* 0 => preemptable, <0 => bug */
 	mm_segment_t		addr_limit;	/* address limit */
+#ifndef CONFIG_THREAD_INFO_IN_TASK
 	struct task_struct	*task;		/* main task structure */
 	__u32			cpu;		/* cpu */
+#endif
 	__u32			cpu_domain;	/* cpu domain */
 #ifdef CONFIG_STACKPROTECTOR_PER_TASK
 	unsigned long		stack_canary;
@@ -75,14 +77,21 @@ struct thread_info {
 #endif
 };
 
+#ifdef CONFIG_THREAD_INFO_IN_TASK
+#define INIT_THREAD_INFO_TASK(tsk)
+#else
+#define INIT_THREAD_INFO_TASK(tsk) .task = &tsk,
+#endif
+
 #define INIT_THREAD_INFO(tsk)						\
 {									\
-	.task		= &tsk,						\
+	INIT_THREAD_INFO_TASK(tsk)					\
 	.flags		= 0,						\
 	.preempt_count	= INIT_PREEMPT_COUNT,				\
 	.addr_limit	= KERNEL_DS,					\
 }
 
+#ifndef CONFIG_THREAD_INFO_IN_TASK
 /*
  * how to get the thread information struct from C
  */
@@ -93,6 +102,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))
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 70993af22d80..2a6745f7423e 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -44,8 +44,12 @@ int main(void)
   DEFINE(TI_FLAGS,		offsetof(struct thread_info, flags));
   DEFINE(TI_PREEMPT,		offsetof(struct thread_info, preempt_count));
   DEFINE(TI_ADDR_LIMIT,		offsetof(struct thread_info, addr_limit));
+#ifdef CONFIG_THREAD_INFO_IN_TASK
+  DEFINE(TI_CPU,		offsetof(struct task_struct, cpu));
+#else
   DEFINE(TI_TASK,		offsetof(struct thread_info, task));
   DEFINE(TI_CPU,		offsetof(struct thread_info, cpu));
+#endif
   DEFINE(TI_CPU_DOMAIN,		offsetof(struct thread_info, cpu_domain));
   DEFINE(TI_CPU_SAVE,		offsetof(struct thread_info, cpu_context));
   DEFINE(TI_USED_CP,		offsetof(struct thread_info, used_cp));
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index db3947ee9c3e..5ae687c8c7b8 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -762,9 +762,13 @@ ENTRY(__switch_to)
 #endif
 	switch_tls r1, r4, r5, r3, r7
 #ifdef CONFIG_CURRENT_POINTER_IN_TPIDRPRW
+#ifdef CONFIG_THREAD_INFO_IN_TASK
+	set_current r2
+#else
 	ldr	r7, [r2, #TI_TASK]
 	set_current r7
 #endif
+#endif
 #if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP)
 	ldr	r7, [r2, #TI_TASK]
 	ldr	r8, =__stack_chk_guard
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index d7a3818da671..84a691da59fa 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -158,7 +158,12 @@ static void vfp_thread_copy(struct thread_info *thread)
  */
 static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
 {
+#ifdef CONFIG_THREAD_INFO_IN_TASK
+	struct task_struct *tsk = v;
+	struct thread_info *thread = &tsk->thread_info;
+#else
 	struct thread_info *thread = v;
+#endif
 	u32 fpexc;
 #ifdef CONFIG_SMP
 	unsigned int cpu;
@@ -169,7 +174,11 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
 		fpexc = fmrx(FPEXC);
 
 #ifdef CONFIG_SMP
+#ifdef CONFIG_THREAD_INFO_IN_TASK
+		cpu = tsk->cpu;
+#else
 		cpu = thread->cpu;
+#endif
 
 		/*
 		 * On SMP, if VFP is enabled, save the old state in
-- 
2.33.0


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

* Re: [PATCH v4 4/7] Make sure task_struct is available for raw_smp_processor_id
  2021-09-08 19:06   ` [PATCH v4 4/7] Make sure task_struct is available for raw_smp_processor_id Keith Packard
@ 2021-09-10 20:20     ` Rob Herring
  0 siblings, 0 replies; 9+ messages in thread
From: Rob Herring @ 2021-09-10 20:20 UTC (permalink / raw)
  To: Keith Packard
  Cc: linux-kernel, Abbott Liu, Alexei Starovoitov, Andrew Morton,
	Andrii Nakryiko, Anshuman Khandual, Ard Biesheuvel,
	Arnd Bergmann, Ben Segall, Bjorn Andersson, bpf,
	Christoph Lameter, Daniel Borkmann, Daniel Bristot de Oliveira,
	Dennis Zhou, devicetree, Dietmar Eggemann, Florian Fainelli,
	Frank Rowand, Geert Uytterhoeven, Ingo Molnar, Jason Wang,
	Jens Axboe, Joe Perches, John Fastabend, Juri Lelli, KP Singh,
	kvm, Linus Walleij, linux-arch, linux-arm-kernel, linux-mm,
	Manivannan Sadhasivam, Marc Zyngier, Martin KaFai Lau,
	Mel Gorman, Michael Ellerman, Michael S. Tsirkin, Miguel Ojeda,
	Mike Rapoport, netdev, Nick Desaulniers, Nick Desaulniers,
	Nicolas Pitre, Peter Zijlstra, Russell King, Song Liu,
	Srikar Dronamraju, Steven Rostedt, Tejun Heo, Thomas Gleixner,
	Uwe Kleine-König, Valentin Schneider, Vincent Guittot,
	virtualization, Wolfram Sang (Renesas),
	YiFei Zhu, Yonghong Song

On Wed, Sep 08, 2021 at 12:06:02PM -0700, Keith Packard wrote:
> To allow architectures to use the 'cpu' field in task_struct for cpu
> identification, the task_struct must be visible whereever the
> raw_smp_processor_id macro is used. It would be simplest to include
> linux/sched.h from the relevant asm/smp.h file, but that file is
> included from linux/sched.h, and the recursive include ends up with
> several declarations in the wrong order.
> 
> To avoid this, the PowerPC architecture code has this ugly hack:
> 
> 	#define raw_smp_processor_id() \
> 		(*(unsigned int *)((void *)current + _TASK_CPU))
> 
> As an alternative, placing includes of linux/sched.h in a few files
> that are used along with asm/smp.h means we can use the task_struct
> field directly.
> 
> Signed-off-by: Keith Packard <keithpac@amazon.com>
> ---
>  arch/arm/mm/proc-v7-bugs.c     | 1 +
>  drivers/vhost/vhost.c          | 1 +
>  drivers/vhost/vhost.h          | 1 +
>  include/asm-generic/irq_regs.h | 1 +
>  include/linux/of_address.h     | 1 +

Where does the DT code use raw_smp_processor_id()? The header itself 
certainly doesn't and the headers should only include what the headers 
use directly.

In general this seems pretty terrible pulling in all of sched.h (and 
then everything else it includes) for just raw_smp_processor_id().

>  include/linux/random.h         | 1 +
>  include/linux/topology.h       | 1 +
>  init/calibrate.c               | 1 +
>  kernel/bpf/bpf_lru_list.h      | 1 +
>  kernel/bpf/percpu_freelist.h   | 1 +
>  kernel/sched/cpuacct.c         | 2 +-
>  lib/irq_regs.c                 | 1 +
>  12 files changed, 12 insertions(+), 1 deletion(-)

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

end of thread, other threads:[~2021-09-10 20:21 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <id:20210907220038.91021-1-keithpac@amazon.com>
2021-09-08 19:05 ` [PATCH v4 0/7] ARM: support THREAD_INFO_IN_TASK Keith Packard
2021-09-08 19:05   ` [PATCH v4 1/7] ARM: Pass cpu number to secondary_start_kernel Keith Packard
2021-09-08 19:06   ` [PATCH v4 2/7] ARM: Pass task " Keith Packard
2021-09-08 19:06   ` [PATCH v4 3/7] ARM: Use smp_processor_id() in vfp_pm_suspend instead of ti->cpu Keith Packard
2021-09-08 19:06   ` [PATCH v4 4/7] Make sure task_struct is available for raw_smp_processor_id Keith Packard
2021-09-10 20:20     ` Rob Herring
2021-09-08 19:06   ` [PATCH v4 5/7] ARM: Stop using TPIDRPRW to hold per_cpu_offset Keith Packard
2021-09-08 19:06   ` [PATCH v4 6/7] ARM: Use TPIDRPRW for current Keith Packard
2021-09-08 19:06   ` [PATCH v4 7/7] ARM: Move thread_info into task_struct (v7 only) Keith Packard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).