xref: /linux/arch/arm64/include/asm/gcs.h (revision c34e9ab9a612ee8b18273398ef75c207b01f516d)
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