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