1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright (C) 2023 ARM Ltd. 4 */ 5 #ifndef __ASM_GCS_H 6 #define __ASM_GCS_H 7 8 #include <asm/types.h> 9 #include <asm/uaccess.h> 10 11 struct kernel_clone_args; 12 struct ksignal; 13 14 static inline void gcsb_dsync(void) 15 { 16 asm volatile(".inst 0xd503227f" : : : "memory"); 17 } 18 19 static inline void gcsstr(u64 *addr, u64 val) 20 { 21 register u64 *_addr __asm__ ("x0") = addr; 22 register long _val __asm__ ("x1") = val; 23 24 /* GCSSTTR x1, x0 */ 25 asm volatile( 26 ".inst 0xd91f1c01\n" 27 : 28 : "rZ" (_val), "r" (_addr) 29 : "memory"); 30 } 31 32 static inline void gcsss1(u64 Xt) 33 { 34 asm volatile ( 35 "sys #3, C7, C7, #2, %0\n" 36 : 37 : "rZ" (Xt) 38 : "memory"); 39 } 40 41 static inline u64 gcsss2(void) 42 { 43 u64 Xt; 44 45 asm volatile( 46 "SYSL %0, #3, C7, C7, #3\n" 47 : "=r" (Xt) 48 : 49 : "memory"); 50 51 return Xt; 52 } 53 54 #define PR_SHADOW_STACK_SUPPORTED_STATUS_MASK \ 55 (PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_WRITE | PR_SHADOW_STACK_PUSH) 56 57 #ifdef CONFIG_ARM64_GCS 58 59 static inline bool task_gcs_el0_enabled(struct task_struct *task) 60 { 61 return current->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE; 62 } 63 64 void gcs_set_el0_mode(struct task_struct *task); 65 void gcs_free(struct task_struct *task); 66 void gcs_preserve_current_state(void); 67 unsigned long gcs_alloc_thread_stack(struct task_struct *tsk, 68 const struct kernel_clone_args *args); 69 70 static inline int gcs_check_locked(struct task_struct *task, 71 unsigned long new_val) 72 { 73 unsigned long cur_val = task->thread.gcs_el0_mode; 74 75 cur_val &= task->thread.gcs_el0_locked; 76 new_val &= task->thread.gcs_el0_locked; 77 78 if (cur_val != new_val) 79 return -EBUSY; 80 81 return 0; 82 } 83 84 #else 85 86 static inline bool task_gcs_el0_enabled(struct task_struct *task) 87 { 88 return false; 89 } 90 91 static inline void gcs_set_el0_mode(struct task_struct *task) { } 92 static inline void gcs_free(struct task_struct *task) { } 93 static inline void gcs_preserve_current_state(void) { } 94 static inline unsigned long gcs_alloc_thread_stack(struct task_struct *tsk, 95 const struct kernel_clone_args *args) 96 { 97 return -ENOTSUPP; 98 } 99 static inline int gcs_check_locked(struct task_struct *task, 100 unsigned long new_val) 101 { 102 return 0; 103 } 104 105 #endif 106 107 #endif 108