1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright 2010 Tilera Corporation. All Rights Reserved. 4 * Copyright 2015 Regents of the University of California 5 * Copyright 2017 SiFive 6 * 7 * Copied from arch/tile/kernel/ptrace.c 8 */ 9 10 #include <asm/vector.h> 11 #include <asm/ptrace.h> 12 #include <asm/syscall.h> 13 #include <asm/thread_info.h> 14 #include <asm/switch_to.h> 15 #include <linux/audit.h> 16 #include <linux/compat.h> 17 #include <linux/ptrace.h> 18 #include <linux/elf.h> 19 #include <linux/regset.h> 20 #include <linux/sched.h> 21 #include <linux/sched/task_stack.h> 22 23 enum riscv_regset { 24 REGSET_X, 25 #ifdef CONFIG_FPU 26 REGSET_F, 27 #endif 28 #ifdef CONFIG_RISCV_ISA_V 29 REGSET_V, 30 #endif 31 }; 32 33 static int riscv_gpr_get(struct task_struct *target, 34 const struct user_regset *regset, 35 struct membuf to) 36 { 37 return membuf_write(&to, task_pt_regs(target), 38 sizeof(struct user_regs_struct)); 39 } 40 41 static int riscv_gpr_set(struct task_struct *target, 42 const struct user_regset *regset, 43 unsigned int pos, unsigned int count, 44 const void *kbuf, const void __user *ubuf) 45 { 46 struct pt_regs *regs; 47 48 regs = task_pt_regs(target); 49 return user_regset_copyin(&pos, &count, &kbuf, &ubuf, regs, 0, -1); 50 } 51 52 #ifdef CONFIG_FPU 53 static int riscv_fpr_get(struct task_struct *target, 54 const struct user_regset *regset, 55 struct membuf to) 56 { 57 struct __riscv_d_ext_state *fstate = &target->thread.fstate; 58 59 if (target == current) 60 fstate_save(current, task_pt_regs(current)); 61 62 membuf_write(&to, fstate, offsetof(struct __riscv_d_ext_state, fcsr)); 63 membuf_store(&to, fstate->fcsr); 64 return membuf_zero(&to, 4); // explicitly pad 65 } 66 67 static int riscv_fpr_set(struct task_struct *target, 68 const struct user_regset *regset, 69 unsigned int pos, unsigned int count, 70 const void *kbuf, const void __user *ubuf) 71 { 72 int ret; 73 struct __riscv_d_ext_state *fstate = &target->thread.fstate; 74 75 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fstate, 0, 76 offsetof(struct __riscv_d_ext_state, fcsr)); 77 if (!ret) { 78 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fstate, 0, 79 offsetof(struct __riscv_d_ext_state, fcsr) + 80 sizeof(fstate->fcsr)); 81 } 82 83 return ret; 84 } 85 #endif 86 87 #ifdef CONFIG_RISCV_ISA_V 88 static int riscv_vr_get(struct task_struct *target, 89 const struct user_regset *regset, 90 struct membuf to) 91 { 92 struct __riscv_v_ext_state *vstate = &target->thread.vstate; 93 struct __riscv_v_regset_state ptrace_vstate; 94 95 if (!riscv_v_vstate_query(task_pt_regs(target))) 96 return -EINVAL; 97 98 /* 99 * Ensure the vector registers have been saved to the memory before 100 * copying them to membuf. 101 */ 102 if (target == current) 103 riscv_v_vstate_save(current, task_pt_regs(current)); 104 105 ptrace_vstate.vstart = vstate->vstart; 106 ptrace_vstate.vl = vstate->vl; 107 ptrace_vstate.vtype = vstate->vtype; 108 ptrace_vstate.vcsr = vstate->vcsr; 109 ptrace_vstate.vlenb = vstate->vlenb; 110 111 /* Copy vector header from vstate. */ 112 membuf_write(&to, &ptrace_vstate, sizeof(struct __riscv_v_regset_state)); 113 114 /* Copy all the vector registers from vstate. */ 115 return membuf_write(&to, vstate->datap, riscv_v_vsize); 116 } 117 118 static int riscv_vr_set(struct task_struct *target, 119 const struct user_regset *regset, 120 unsigned int pos, unsigned int count, 121 const void *kbuf, const void __user *ubuf) 122 { 123 int ret; 124 struct __riscv_v_ext_state *vstate = &target->thread.vstate; 125 struct __riscv_v_regset_state ptrace_vstate; 126 127 if (!riscv_v_vstate_query(task_pt_regs(target))) 128 return -EINVAL; 129 130 /* Copy rest of the vstate except datap */ 131 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ptrace_vstate, 0, 132 sizeof(struct __riscv_v_regset_state)); 133 if (unlikely(ret)) 134 return ret; 135 136 if (vstate->vlenb != ptrace_vstate.vlenb) 137 return -EINVAL; 138 139 vstate->vstart = ptrace_vstate.vstart; 140 vstate->vl = ptrace_vstate.vl; 141 vstate->vtype = ptrace_vstate.vtype; 142 vstate->vcsr = ptrace_vstate.vcsr; 143 144 /* Copy all the vector registers. */ 145 pos = 0; 146 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vstate->datap, 147 0, riscv_v_vsize); 148 return ret; 149 } 150 #endif 151 152 static const struct user_regset riscv_user_regset[] = { 153 [REGSET_X] = { 154 .core_note_type = NT_PRSTATUS, 155 .n = ELF_NGREG, 156 .size = sizeof(elf_greg_t), 157 .align = sizeof(elf_greg_t), 158 .regset_get = riscv_gpr_get, 159 .set = riscv_gpr_set, 160 }, 161 #ifdef CONFIG_FPU 162 [REGSET_F] = { 163 .core_note_type = NT_PRFPREG, 164 .n = ELF_NFPREG, 165 .size = sizeof(elf_fpreg_t), 166 .align = sizeof(elf_fpreg_t), 167 .regset_get = riscv_fpr_get, 168 .set = riscv_fpr_set, 169 }, 170 #endif 171 #ifdef CONFIG_RISCV_ISA_V 172 [REGSET_V] = { 173 .core_note_type = NT_RISCV_VECTOR, 174 .align = 16, 175 .n = ((32 * RISCV_MAX_VLENB) + 176 sizeof(struct __riscv_v_regset_state)) / sizeof(__u32), 177 .size = sizeof(__u32), 178 .regset_get = riscv_vr_get, 179 .set = riscv_vr_set, 180 }, 181 #endif 182 }; 183 184 static const struct user_regset_view riscv_user_native_view = { 185 .name = "riscv", 186 .e_machine = EM_RISCV, 187 .regsets = riscv_user_regset, 188 .n = ARRAY_SIZE(riscv_user_regset), 189 }; 190 191 struct pt_regs_offset { 192 const char *name; 193 int offset; 194 }; 195 196 #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)} 197 #define REG_OFFSET_END {.name = NULL, .offset = 0} 198 199 static const struct pt_regs_offset regoffset_table[] = { 200 REG_OFFSET_NAME(epc), 201 REG_OFFSET_NAME(ra), 202 REG_OFFSET_NAME(sp), 203 REG_OFFSET_NAME(gp), 204 REG_OFFSET_NAME(tp), 205 REG_OFFSET_NAME(t0), 206 REG_OFFSET_NAME(t1), 207 REG_OFFSET_NAME(t2), 208 REG_OFFSET_NAME(s0), 209 REG_OFFSET_NAME(s1), 210 REG_OFFSET_NAME(a0), 211 REG_OFFSET_NAME(a1), 212 REG_OFFSET_NAME(a2), 213 REG_OFFSET_NAME(a3), 214 REG_OFFSET_NAME(a4), 215 REG_OFFSET_NAME(a5), 216 REG_OFFSET_NAME(a6), 217 REG_OFFSET_NAME(a7), 218 REG_OFFSET_NAME(s2), 219 REG_OFFSET_NAME(s3), 220 REG_OFFSET_NAME(s4), 221 REG_OFFSET_NAME(s5), 222 REG_OFFSET_NAME(s6), 223 REG_OFFSET_NAME(s7), 224 REG_OFFSET_NAME(s8), 225 REG_OFFSET_NAME(s9), 226 REG_OFFSET_NAME(s10), 227 REG_OFFSET_NAME(s11), 228 REG_OFFSET_NAME(t3), 229 REG_OFFSET_NAME(t4), 230 REG_OFFSET_NAME(t5), 231 REG_OFFSET_NAME(t6), 232 REG_OFFSET_NAME(status), 233 REG_OFFSET_NAME(badaddr), 234 REG_OFFSET_NAME(cause), 235 REG_OFFSET_NAME(orig_a0), 236 REG_OFFSET_END, 237 }; 238 239 /** 240 * regs_query_register_offset() - query register offset from its name 241 * @name: the name of a register 242 * 243 * regs_query_register_offset() returns the offset of a register in struct 244 * pt_regs from its name. If the name is invalid, this returns -EINVAL; 245 */ 246 int regs_query_register_offset(const char *name) 247 { 248 const struct pt_regs_offset *roff; 249 250 for (roff = regoffset_table; roff->name != NULL; roff++) 251 if (!strcmp(roff->name, name)) 252 return roff->offset; 253 return -EINVAL; 254 } 255 256 /** 257 * regs_within_kernel_stack() - check the address in the stack 258 * @regs: pt_regs which contains kernel stack pointer. 259 * @addr: address which is checked. 260 * 261 * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). 262 * If @addr is within the kernel stack, it returns true. If not, returns false. 263 */ 264 static bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) 265 { 266 return (addr & ~(THREAD_SIZE - 1)) == 267 (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)); 268 } 269 270 /** 271 * regs_get_kernel_stack_nth() - get Nth entry of the stack 272 * @regs: pt_regs which contains kernel stack pointer. 273 * @n: stack entry number. 274 * 275 * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which 276 * is specified by @regs. If the @n th entry is NOT in the kernel stack, 277 * this returns 0. 278 */ 279 unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) 280 { 281 unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); 282 283 addr += n; 284 if (regs_within_kernel_stack(regs, (unsigned long)addr)) 285 return *addr; 286 else 287 return 0; 288 } 289 290 void ptrace_disable(struct task_struct *child) 291 { 292 } 293 294 long arch_ptrace(struct task_struct *child, long request, 295 unsigned long addr, unsigned long data) 296 { 297 long ret = -EIO; 298 299 switch (request) { 300 default: 301 ret = ptrace_request(child, request, addr, data); 302 break; 303 } 304 305 return ret; 306 } 307 308 #ifdef CONFIG_COMPAT 309 static int compat_riscv_gpr_get(struct task_struct *target, 310 const struct user_regset *regset, 311 struct membuf to) 312 { 313 struct compat_user_regs_struct cregs; 314 315 regs_to_cregs(&cregs, task_pt_regs(target)); 316 317 return membuf_write(&to, &cregs, 318 sizeof(struct compat_user_regs_struct)); 319 } 320 321 static int compat_riscv_gpr_set(struct task_struct *target, 322 const struct user_regset *regset, 323 unsigned int pos, unsigned int count, 324 const void *kbuf, const void __user *ubuf) 325 { 326 int ret; 327 struct compat_user_regs_struct cregs; 328 329 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &cregs, 0, -1); 330 331 cregs_to_regs(&cregs, task_pt_regs(target)); 332 333 return ret; 334 } 335 336 static const struct user_regset compat_riscv_user_regset[] = { 337 [REGSET_X] = { 338 .core_note_type = NT_PRSTATUS, 339 .n = ELF_NGREG, 340 .size = sizeof(compat_elf_greg_t), 341 .align = sizeof(compat_elf_greg_t), 342 .regset_get = compat_riscv_gpr_get, 343 .set = compat_riscv_gpr_set, 344 }, 345 #ifdef CONFIG_FPU 346 [REGSET_F] = { 347 .core_note_type = NT_PRFPREG, 348 .n = ELF_NFPREG, 349 .size = sizeof(elf_fpreg_t), 350 .align = sizeof(elf_fpreg_t), 351 .regset_get = riscv_fpr_get, 352 .set = riscv_fpr_set, 353 }, 354 #endif 355 }; 356 357 static const struct user_regset_view compat_riscv_user_native_view = { 358 .name = "riscv", 359 .e_machine = EM_RISCV, 360 .regsets = compat_riscv_user_regset, 361 .n = ARRAY_SIZE(compat_riscv_user_regset), 362 }; 363 364 long compat_arch_ptrace(struct task_struct *child, compat_long_t request, 365 compat_ulong_t caddr, compat_ulong_t cdata) 366 { 367 long ret = -EIO; 368 369 switch (request) { 370 default: 371 ret = compat_ptrace_request(child, request, caddr, cdata); 372 break; 373 } 374 375 return ret; 376 } 377 #endif /* CONFIG_COMPAT */ 378 379 const struct user_regset_view *task_user_regset_view(struct task_struct *task) 380 { 381 #ifdef CONFIG_COMPAT 382 if (test_tsk_thread_flag(task, TIF_32BIT)) 383 return &compat_riscv_user_native_view; 384 else 385 #endif 386 return &riscv_user_native_view; 387 } 388