diff mbox

[RFC,2/3] arm: make cpu a percpu variable

Message ID 20180315170859.93893-3-zsm@chromium.org (mailing list archive)
State New, archived
Headers show

Commit Message

Zubin Mithra March 15, 2018, 5:08 p.m. UTC
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.

Earlier raw_smp_processor_id() was current_thread_info()->cpu :-
	mov	r3, sp
	bic     r3, r3, #8128
	bic     r3, r3, #63
	ldr     r0, [r3, #16]

Now it is *raw_cpu_ptr(&cpu_number) :-
	movw	r3, #57344
	movt	r3, #32917
	mrc	15, 0, r0, cr13, cr0, {4}
	ldr	r0, [r3, r0]

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

Comments

Mark Rutland March 15, 2018, 6:06 p.m. UTC | #1
On Thu, Mar 15, 2018 at 05:08:58PM +0000, Zubin Mithra wrote:
> 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.
> 
> Earlier raw_smp_processor_id() was current_thread_info()->cpu :-
> 	mov	r3, sp
> 	bic     r3, r3, #8128
> 	bic     r3, r3, #63
> 	ldr     r0, [r3, #16]
> 
> Now it is *raw_cpu_ptr(&cpu_number) :-
> 	movw	r3, #57344
> 	movt	r3, #32917
> 	mrc	15, 0, r0, cr13, cr0, {4}
> 	ldr	r0, [r3, r0]

It's probably worth noting that with the thread_info moved off of the
stack, were we to use that to get at the cpu number, this would require
a similar sequence to the raw_cpu_ptr() code here.

This might make more sense after a patch using a register for the
thread_info (which would also allow for having separate IRQ stacks).

> 
> Signed-off-by: Zubin Mithra <zsm@chromium.org>
> ---
>  arch/arm/include/asm/cputype.h | 3 +++
>  arch/arm/include/asm/smp.h     | 3 ++-
>  arch/arm/kernel/setup.c        | 2 +-
>  arch/arm/kernel/smp.c          | 5 +++--
>  arch/arm/kernel/topology.c     | 5 +++++
>  5 files changed, 14 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
> index cb546425da8a..10148c7af12f 100644
> --- a/arch/arm/include/asm/cputype.h
> +++ b/arch/arm/include/asm/cputype.h
> @@ -2,6 +2,9 @@
>  #ifndef __ASM_ARM_CPUTYPE_H
>  #define __ASM_ARM_CPUTYPE_H
>  
> +#include <asm/percpu.h>
> +DECLARE_PER_CPU(int, cpu_number);
> +

Why isn't this defined in <asm/smp.h>, as we do on arm64?

> --- a/arch/arm/include/asm/smp.h
> +++ b/arch/arm/include/asm/smp.h
> @@ -18,7 +18,8 @@
>  # error "<asm/smp.h> included in non-SMP build"
>  #endif
>  
> -#define raw_smp_processor_id() (current_thread_info()->cpu)
> +#include <asm/cputype.h>
> +#define raw_smp_processor_id() (*raw_cpu_ptr(&cpu_number))

It might be worth dragging the comment along from arm64, explaining why
we must use *raw_cpu_ptr(), and not this_cpu_read(), etc.

> --- a/arch/arm/kernel/topology.c
> +++ b/arch/arm/kernel/topology.c
> @@ -30,6 +30,9 @@
>  #include <asm/cputype.h>
>  #include <asm/topology.h>
>  
> +DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number);
> +EXPORT_PER_CPU_SYMBOL(cpu_number);

Why not in smp.c, as with arm64?

> +
>  /*
>   * cpu capacity scale management
>   */
> @@ -310,6 +313,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;

Likewise, why isn't this in smp_prepare_cpus() in smp.c?

This isn't toplogy related, so it would be better placed there.

Thanks,
Mark.
diff mbox

Patch

diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index cb546425da8a..10148c7af12f 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -2,6 +2,9 @@ 
 #ifndef __ASM_ARM_CPUTYPE_H
 #define __ASM_ARM_CPUTYPE_H
 
+#include <asm/percpu.h>
+DECLARE_PER_CPU(int, cpu_number);
+
 #include <linux/stringify.h>
 #include <linux/kernel.h>
 
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index 709a55989cb0..7e7b198174d6 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -18,7 +18,8 @@ 
 # error "<asm/smp.h> included in non-SMP build"
 #endif
 
-#define raw_smp_processor_id() (current_thread_info()->cpu)
+#include <asm/cputype.h>
+#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 fc40a2b40595..6323b4d80306 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 2da087926ebe..9584a52eb156 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -372,7 +372,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));
@@ -436,7 +437,7 @@  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)
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index 24ac3cab411d..34b2136deab6 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -30,6 +30,9 @@ 
 #include <asm/cputype.h>
 #include <asm/topology.h>
 
+DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number);
+EXPORT_PER_CPU_SYMBOL(cpu_number);
+
 /*
  * cpu capacity scale management
  */
@@ -310,6 +313,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;