Skip to content

Commit 7158627

Browse files
wildea01ctmarinas
authored andcommitted
arm64: percpu: implement optimised pcpu access using tpidr_el1
This patch implements optimised percpu variable accesses using the el1 r/w thread register (tpidr_el1) along the same lines as arch/arm/. Signed-off-by: Will Deacon <[email protected]> Signed-off-by: Catalin Marinas <[email protected]>
1 parent 66aa8d6 commit 7158627

File tree

4 files changed

+55
-3
lines changed

4 files changed

+55
-3
lines changed

arch/arm64/include/asm/Kbuild

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ generic-y += mman.h
2626
generic-y += msgbuf.h
2727
generic-y += mutex.h
2828
generic-y += pci.h
29-
generic-y += percpu.h
3029
generic-y += poll.h
3130
generic-y += posix_types.h
3231
generic-y += resource.h

arch/arm64/include/asm/percpu.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (C) 2013 ARM Ltd.
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License version 2 as
6+
* published by the Free Software Foundation.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU General Public License
14+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
*/
16+
#ifndef __ASM_PERCPU_H
17+
#define __ASM_PERCPU_H
18+
19+
static inline void set_my_cpu_offset(unsigned long off)
20+
{
21+
asm volatile("msr tpidr_el1, %0" :: "r" (off) : "memory");
22+
}
23+
24+
static inline unsigned long __my_cpu_offset(void)
25+
{
26+
unsigned long off;
27+
register unsigned long *sp asm ("sp");
28+
29+
/*
30+
* We want to allow caching the value, so avoid using volatile and
31+
* instead use a fake stack read to hazard against barrier().
32+
*/
33+
asm("mrs %0, tpidr_el1" : "=r" (off) : "Q" (*sp));
34+
35+
return off;
36+
}
37+
#define __my_cpu_offset __my_cpu_offset()
38+
39+
#include <asm-generic/percpu.h>
40+
41+
#endif /* __ASM_PERCPU_H */

arch/arm64/kernel/setup.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,16 @@ void __init early_print(const char *str, ...)
108108
printk("%s", buf);
109109
}
110110

111+
void __init smp_setup_processor_id(void)
112+
{
113+
/*
114+
* clear __my_cpu_offset on boot CPU to avoid hang caused by
115+
* using percpu variable early, for example, lockdep will
116+
* access percpu variable inside lock_release
117+
*/
118+
set_my_cpu_offset(0);
119+
}
120+
111121
bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
112122
{
113123
return phys_id == cpu_logical_map(cpu);

arch/arm64/kernel/smp.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,6 @@ asmlinkage void secondary_start_kernel(void)
122122
struct mm_struct *mm = &init_mm;
123123
unsigned int cpu = smp_processor_id();
124124

125-
printk("CPU%u: Booted secondary processor\n", cpu);
126-
127125
/*
128126
* All kernel threads share the same mm context; grab a
129127
* reference and switch to it.
@@ -132,6 +130,9 @@ asmlinkage void secondary_start_kernel(void)
132130
current->active_mm = mm;
133131
cpumask_set_cpu(cpu, mm_cpumask(mm));
134132

133+
set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
134+
printk("CPU%u: Booted secondary processor\n", cpu);
135+
135136
/*
136137
* TTBR0 is only used for the identity mapping at this stage. Make it
137138
* point to zero page to avoid speculatively fetching new entries.
@@ -271,6 +272,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
271272

272273
void __init smp_prepare_boot_cpu(void)
273274
{
275+
set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
274276
}
275277

276278
static void (*smp_cross_call)(const struct cpumask *, unsigned int);

0 commit comments

Comments
 (0)