Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.18-rc5 196 lines 4.2 kB view raw
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 11struct kernel_clone_args; 12struct ksignal; 13 14static inline void gcsb_dsync(void) 15{ 16 asm volatile(".inst 0xd503227f" : : : "memory"); 17} 18 19static 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 32static 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 41static 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 59static inline bool task_gcs_el0_enabled(struct task_struct *task) 60{ 61 return task->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE; 62} 63 64void gcs_set_el0_mode(struct task_struct *task); 65void gcs_free(struct task_struct *task); 66void gcs_preserve_current_state(void); 67unsigned long gcs_alloc_thread_stack(struct task_struct *tsk, 68 const struct kernel_clone_args *args); 69 70static 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 84static inline int gcssttr(unsigned long __user *addr, unsigned long val) 85{ 86 register unsigned long __user *_addr __asm__ ("x0") = addr; 87 register unsigned long _val __asm__ ("x1") = val; 88 int err = 0; 89 90 /* GCSSTTR x1, [x0] */ 91 asm volatile( 92 "1: .inst 0xd91f1c01\n" 93 "2: \n" 94 _ASM_EXTABLE_UACCESS_ERR(1b, 2b, %w0) 95 : "+r" (err) 96 : "rZ" (_val), "r" (_addr) 97 : "memory"); 98 99 return err; 100} 101 102static inline void put_user_gcs(unsigned long val, unsigned long __user *addr, 103 int *err) 104{ 105 int ret; 106 107 if (!access_ok((char __user *)addr, sizeof(u64))) { 108 *err = -EFAULT; 109 return; 110 } 111 112 uaccess_ttbr0_enable(); 113 ret = gcssttr(addr, val); 114 if (ret != 0) 115 *err = ret; 116 uaccess_ttbr0_disable(); 117} 118 119static inline void push_user_gcs(unsigned long val, int *err) 120{ 121 u64 gcspr = read_sysreg_s(SYS_GCSPR_EL0); 122 123 gcspr -= sizeof(u64); 124 put_user_gcs(val, (unsigned long __user *)gcspr, err); 125 if (!*err) 126 write_sysreg_s(gcspr, SYS_GCSPR_EL0); 127} 128 129/* 130 * Unlike put/push_user_gcs() above, get/pop_user_gsc() doesn't 131 * validate the GCS permission is set on the page being read. This 132 * differs from how the hardware works when it consumes data stored at 133 * GCSPR. Callers should ensure this is acceptable. 134 */ 135static inline u64 get_user_gcs(unsigned long __user *addr, int *err) 136{ 137 unsigned long ret; 138 u64 load = 0; 139 140 /* Ensure previous GCS operation are visible before we read the page */ 141 gcsb_dsync(); 142 ret = copy_from_user(&load, addr, sizeof(load)); 143 if (ret != 0) 144 *err = ret; 145 return load; 146} 147 148static inline u64 pop_user_gcs(int *err) 149{ 150 u64 gcspr = read_sysreg_s(SYS_GCSPR_EL0); 151 u64 read_val; 152 153 read_val = get_user_gcs((__force unsigned long __user *)gcspr, err); 154 if (!*err) 155 write_sysreg_s(gcspr + sizeof(u64), SYS_GCSPR_EL0); 156 157 return read_val; 158} 159 160#else 161 162static inline bool task_gcs_el0_enabled(struct task_struct *task) 163{ 164 return false; 165} 166 167static inline void gcs_set_el0_mode(struct task_struct *task) { } 168static inline void gcs_free(struct task_struct *task) { } 169static inline void gcs_preserve_current_state(void) { } 170static inline void put_user_gcs(unsigned long val, unsigned long __user *addr, 171 int *err) { } 172static inline void push_user_gcs(unsigned long val, int *err) { } 173 174static inline unsigned long gcs_alloc_thread_stack(struct task_struct *tsk, 175 const struct kernel_clone_args *args) 176{ 177 return -ENOTSUPP; 178} 179static inline int gcs_check_locked(struct task_struct *task, 180 unsigned long new_val) 181{ 182 return 0; 183} 184static inline u64 get_user_gcs(unsigned long __user *addr, int *err) 185{ 186 *err = -EFAULT; 187 return 0; 188} 189static inline u64 pop_user_gcs(int *err) 190{ 191 return 0; 192} 193 194#endif 195 196#endif