xref: /openbmc/linux/arch/arm/include/asm/current.h (revision aa74c44b)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (c) 2021 Keith Packard <keithp@keithp.com>
4  * Copyright (c) 2021 Google, LLC <ardb@kernel.org>
5  */
6 
7 #ifndef _ASM_ARM_CURRENT_H
8 #define _ASM_ARM_CURRENT_H
9 
10 #ifndef __ASSEMBLY__
11 
12 struct task_struct;
13 
14 static inline void set_current(struct task_struct *cur)
15 {
16 	if (!IS_ENABLED(CONFIG_CURRENT_POINTER_IN_TPIDRURO))
17 		return;
18 
19 	/* Set TPIDRURO */
20 	asm("mcr p15, 0, %0, c13, c0, 3" :: "r"(cur) : "memory");
21 }
22 
23 #ifdef CONFIG_CURRENT_POINTER_IN_TPIDRURO
24 
25 static inline struct task_struct *get_current(void)
26 {
27 	struct task_struct *cur;
28 
29 #if __has_builtin(__builtin_thread_pointer) && \
30     !(defined(CONFIG_THUMB2_KERNEL) && \
31       defined(CONFIG_CC_IS_CLANG) && CONFIG_CLANG_VERSION < 130001)
32 	/*
33 	 * Use the __builtin helper when available - this results in better
34 	 * code, especially when using GCC in combination with the per-task
35 	 * stack protector, as the compiler will recognize that it needs to
36 	 * load the TLS register only once in every function.
37 	 *
38 	 * Clang < 13.0.1 gets this wrong for Thumb2 builds:
39 	 * https://github.com/ClangBuiltLinux/linux/issues/1485
40 	 */
41 	cur = __builtin_thread_pointer();
42 #else
43 	asm("mrc p15, 0, %0, c13, c0, 3" : "=r"(cur));
44 #endif
45 	return cur;
46 }
47 
48 #define current get_current()
49 #else
50 #include <asm-generic/current.h>
51 #endif /* CONFIG_CURRENT_POINTER_IN_TPIDRURO */
52 
53 #endif /* __ASSEMBLY__ */
54 
55 #endif /* _ASM_ARM_CURRENT_H */
56