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
set_current(struct task_struct * cur)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
get_current(void)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