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 #ifdef CONFIG_RISCV_ISA_SUPM 32 REGSET_TAGGED_ADDR_CTRL, 33 #endif 34 }; 35 36 static int riscv_gpr_get(struct task_struct *target, 37 const struct user_regset *regset, 38 struct membuf to) 39 { 40 return membuf_write(&to, task_pt_regs(target), 41 sizeof(struct user_regs_struct)); 42 } 43 44 static int riscv_gpr_set(struct task_struct *target, 45 const struct user_regset *regset, 46 unsigned int pos, unsigned int count, 47 const void *kbuf, const void __user *ubuf) 48 { 49 struct pt_regs *regs; 50 51 regs = task_pt_regs(target); 52 return user_regset_copyin(&pos, &count, &kbuf, &ubuf, regs, 0, -1); 53 } 54 55 #ifdef CONFIG_FPU 56 static int riscv_fpr_get(struct task_struct *target, 57 const struct user_regset *regset, 58 struct membuf to) 59 { 60 struct __riscv_d_ext_state *fstate = &target->thread.fstate; 61 62 if (target == current) 63 fstate_save(current, task_pt_regs(current)); 64 65 membuf_write(&to, fstate, offsetof(struct __riscv_d_ext_state, fcsr)); 66 membuf_store(&to, fstate->fcsr); 67 return membuf_zero(&to, 4); // explicitly pad 68 } 69 70 static int riscv_fpr_set(struct task_struct *target, 71 const struct user_regset *regset, 72 unsigned int pos, unsigned int count, 73 const void *kbuf, const void __user *ubuf) 74 { 75 int ret; 76 struct __riscv_d_ext_state *fstate = &target->thread.fstate; 77 78 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fstate, 0, 79 offsetof(struct __riscv_d_ext_state, fcsr)); 80 if (!ret) { 81 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fstate, 0, 82 offsetof(struct __riscv_d_ext_state, fcsr) + 83 sizeof(fstate->fcsr)); 84 } 85 86 return ret; 87 } 88 #endif 89 90 #ifdef CONFIG_RISCV_ISA_V 91 static int riscv_vr_get(struct task_struct *target, 92 const struct user_regset *regset, 93 struct membuf to) 94 { 95 struct __riscv_v_ext_state *vstate = &target->thread.vstate; 96 struct __riscv_v_regset_state ptrace_vstate; 97 98 if (!riscv_v_vstate_query(task_pt_regs(target))) 99 return -EINVAL; 100 101 /* 102 * Ensure the vector registers have been saved to the memory before 103 * copying them to membuf. 104 */ 105 if (target == current) { 106 get_cpu_vector_context(); 107 riscv_v_vstate_save(¤t->thread.vstate, task_pt_regs(current)); 108 put_cpu_vector_context(); 109 } 110 111 ptrace_vstate.vstart = vstate->vstart; 112 ptrace_vstate.vl = vstate->vl; 113 ptrace_vstate.vtype = vstate->vtype; 114 ptrace_vstate.vcsr = vstate->vcsr; 115 ptrace_vstate.vlenb = vstate->vlenb; 116 117 /* Copy vector header from vstate. */ 118 membuf_write(&to, &ptrace_vstate, sizeof(struct __riscv_v_regset_state)); 119 120 /* Copy all the vector registers from vstate. */ 121 return membuf_write(&to, vstate->datap, riscv_v_vsize); 122 } 123 124 static int riscv_vr_set(struct task_struct *target, 125 const struct user_regset *regset, 126 unsigned int pos, unsigned int count, 127 const void *kbuf, const void __user *ubuf) 128 { 129 int ret; 130 struct __riscv_v_ext_state *vstate = &target->thread.vstate; 131 struct __riscv_v_regset_state ptrace_vstate; 132 133 if (!riscv_v_vstate_query(task_pt_regs(target))) 134 return -EINVAL; 135 136 /* Copy rest of the vstate except datap */ 137 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ptrace_vstate, 0, 138 sizeof(struct __riscv_v_regset_state)); 139 if (unlikely(ret)) 140 return ret; 141 142 if (vstate->vlenb != ptrace_vstate.vlenb) 143 return -EINVAL; 144 145 vstate->vstart = ptrace_vstate.vstart; 146 vstate->vl = ptrace_vstate.vl; 147 vstate->vtype = ptrace_vstate.vtype; 148 vstate->vcsr = ptrace_vstate.vcsr; 149 150 /* Copy all the vector registers. */ 151 pos = 0; 152 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vstate->datap, 153 0, riscv_v_vsize); 154 return ret; 155 } 156 157 static int riscv_vr_active(struct task_struct *target, const struct user_regset *regset) 158 { 159 if (!(has_vector() || has_xtheadvector())) 160 return -ENODEV; 161 162 if (!riscv_v_vstate_query(task_pt_regs(target))) 163 return 0; 164 165 return regset->n; 166 } 167 #endif 168 169 #ifdef CONFIG_RISCV_ISA_SUPM 170 static int tagged_addr_ctrl_get(struct task_struct *target, 171 const struct user_regset *regset, 172 struct membuf to) 173 { 174 long ctrl = get_tagged_addr_ctrl(target); 175 176 if (IS_ERR_VALUE(ctrl)) 177 return ctrl; 178 179 return membuf_write(&to, &ctrl, sizeof(ctrl)); 180 } 181 182 static int tagged_addr_ctrl_set(struct task_struct *target, 183 const struct user_regset *regset, 184 unsigned int pos, unsigned int count, 185 const void *kbuf, const void __user *ubuf) 186 { 187 int ret; 188 long ctrl; 189 190 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl, 0, -1); 191 if (ret) 192 return ret; 193 194 return set_tagged_addr_ctrl(target, ctrl); 195 } 196 #endif 197 198 static struct user_regset riscv_user_regset[] __ro_after_init = { 199 [REGSET_X] = { 200 USER_REGSET_NOTE_TYPE(PRSTATUS), 201 .n = ELF_NGREG, 202 .size = sizeof(elf_greg_t), 203 .align = sizeof(elf_greg_t), 204 .regset_get = riscv_gpr_get, 205 .set = riscv_gpr_set, 206 }, 207 #ifdef CONFIG_FPU 208 [REGSET_F] = { 209 USER_REGSET_NOTE_TYPE(PRFPREG), 210 .n = ELF_NFPREG, 211 .size = sizeof(elf_fpreg_t), 212 .align = sizeof(elf_fpreg_t), 213 .regset_get = riscv_fpr_get, 214 .set = riscv_fpr_set, 215 }, 216 #endif 217 #ifdef CONFIG_RISCV_ISA_V 218 [REGSET_V] = { 219 USER_REGSET_NOTE_TYPE(RISCV_VECTOR), 220 .align = 16, 221 .size = sizeof(__u32), 222 .regset_get = riscv_vr_get, 223 .set = riscv_vr_set, 224 .active = riscv_vr_active, 225 }, 226 #endif 227 #ifdef CONFIG_RISCV_ISA_SUPM 228 [REGSET_TAGGED_ADDR_CTRL] = { 229 USER_REGSET_NOTE_TYPE(RISCV_TAGGED_ADDR_CTRL), 230 .n = 1, 231 .size = sizeof(long), 232 .align = sizeof(long), 233 .regset_get = tagged_addr_ctrl_get, 234 .set = tagged_addr_ctrl_set, 235 }, 236 #endif 237 }; 238 239 static const struct user_regset_view riscv_user_native_view = { 240 .name = "riscv", 241 .e_machine = EM_RISCV, 242 .regsets = riscv_user_regset, 243 .n = ARRAY_SIZE(riscv_user_regset), 244 }; 245 246 #ifdef CONFIG_RISCV_ISA_V 247 void __init update_regset_vector_info(unsigned long size) 248 { 249 riscv_user_regset[REGSET_V].n = (size + sizeof(struct __riscv_v_regset_state)) / 250 sizeof(__u32); 251 } 252 #endif 253 254 struct pt_regs_offset { 255 const char *name; 256 int offset; 257 }; 258 259 #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)} 260 #define REG_OFFSET_END {.name = NULL, .offset = 0} 261 262 static const struct pt_regs_offset regoffset_table[] = { 263 REG_OFFSET_NAME(epc), 264 REG_OFFSET_NAME(ra), 265 REG_OFFSET_NAME(sp), 266 REG_OFFSET_NAME(gp), 267 REG_OFFSET_NAME(tp), 268 REG_OFFSET_NAME(t0), 269 REG_OFFSET_NAME(t1), 270 REG_OFFSET_NAME(t2), 271 REG_OFFSET_NAME(s0), 272 REG_OFFSET_NAME(s1), 273 REG_OFFSET_NAME(a0), 274 REG_OFFSET_NAME(a1), 275 REG_OFFSET_NAME(a2), 276 REG_OFFSET_NAME(a3), 277 REG_OFFSET_NAME(a4), 278 REG_OFFSET_NAME(a5), 279 REG_OFFSET_NAME(a6), 280 REG_OFFSET_NAME(a7), 281 REG_OFFSET_NAME(s2), 282 REG_OFFSET_NAME(s3), 283 REG_OFFSET_NAME(s4), 284 REG_OFFSET_NAME(s5), 285 REG_OFFSET_NAME(s6), 286 REG_OFFSET_NAME(s7), 287 REG_OFFSET_NAME(s8), 288 REG_OFFSET_NAME(s9), 289 REG_OFFSET_NAME(s10), 290 REG_OFFSET_NAME(s11), 291 REG_OFFSET_NAME(t3), 292 REG_OFFSET_NAME(t4), 293 REG_OFFSET_NAME(t5), 294 REG_OFFSET_NAME(t6), 295 REG_OFFSET_NAME(status), 296 REG_OFFSET_NAME(badaddr), 297 REG_OFFSET_NAME(cause), 298 REG_OFFSET_NAME(orig_a0), 299 REG_OFFSET_END, 300 }; 301 302 /** 303 * regs_query_register_offset() - query register offset from its name 304 * @name: the name of a register 305 * 306 * regs_query_register_offset() returns the offset of a register in struct 307 * pt_regs from its name. If the name is invalid, this returns -EINVAL; 308 */ 309 int regs_query_register_offset(const char *name) 310 { 311 const struct pt_regs_offset *roff; 312 313 for (roff = regoffset_table; roff->name != NULL; roff++) 314 if (!strcmp(roff->name, name)) 315 return roff->offset; 316 return -EINVAL; 317 } 318 319 /** 320 * regs_within_kernel_stack() - check the address in the stack 321 * @regs: pt_regs which contains kernel stack pointer. 322 * @addr: address which is checked. 323 * 324 * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). 325 * If @addr is within the kernel stack, it returns true. If not, returns false. 326 */ 327 static bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) 328 { 329 return (addr & ~(THREAD_SIZE - 1)) == 330 (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)); 331 } 332 333 /** 334 * regs_get_kernel_stack_nth() - get Nth entry of the stack 335 * @regs: pt_regs which contains kernel stack pointer. 336 * @n: stack entry number. 337 * 338 * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which 339 * is specified by @regs. If the @n th entry is NOT in the kernel stack, 340 * this returns 0. 341 */ 342 unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) 343 { 344 unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); 345 346 addr += n; 347 if (regs_within_kernel_stack(regs, (unsigned long)addr)) 348 return *addr; 349 else 350 return 0; 351 } 352 353 void ptrace_disable(struct task_struct *child) 354 { 355 } 356 357 long arch_ptrace(struct task_struct *child, long request, 358 unsigned long addr, unsigned long data) 359 { 360 long ret = -EIO; 361 362 switch (request) { 363 default: 364 ret = ptrace_request(child, request, addr, data); 365 break; 366 } 367 368 return ret; 369 } 370 371 #ifdef CONFIG_COMPAT 372 static int compat_riscv_gpr_get(struct task_struct *target, 373 const struct user_regset *regset, 374 struct membuf to) 375 { 376 struct compat_user_regs_struct cregs; 377 378 regs_to_cregs(&cregs, task_pt_regs(target)); 379 380 return membuf_write(&to, &cregs, 381 sizeof(struct compat_user_regs_struct)); 382 } 383 384 static int compat_riscv_gpr_set(struct task_struct *target, 385 const struct user_regset *regset, 386 unsigned int pos, unsigned int count, 387 const void *kbuf, const void __user *ubuf) 388 { 389 int ret; 390 struct compat_user_regs_struct cregs; 391 392 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &cregs, 0, -1); 393 394 cregs_to_regs(&cregs, task_pt_regs(target)); 395 396 return ret; 397 } 398 399 static const struct user_regset compat_riscv_user_regset[] = { 400 [REGSET_X] = { 401 USER_REGSET_NOTE_TYPE(PRSTATUS), 402 .n = ELF_NGREG, 403 .size = sizeof(compat_elf_greg_t), 404 .align = sizeof(compat_elf_greg_t), 405 .regset_get = compat_riscv_gpr_get, 406 .set = compat_riscv_gpr_set, 407 }, 408 #ifdef CONFIG_FPU 409 [REGSET_F] = { 410 USER_REGSET_NOTE_TYPE(PRFPREG), 411 .n = ELF_NFPREG, 412 .size = sizeof(elf_fpreg_t), 413 .align = sizeof(elf_fpreg_t), 414 .regset_get = riscv_fpr_get, 415 .set = riscv_fpr_set, 416 }, 417 #endif 418 }; 419 420 static const struct user_regset_view compat_riscv_user_native_view = { 421 .name = "riscv", 422 .e_machine = EM_RISCV, 423 .regsets = compat_riscv_user_regset, 424 .n = ARRAY_SIZE(compat_riscv_user_regset), 425 }; 426 427 long compat_arch_ptrace(struct task_struct *child, compat_long_t request, 428 compat_ulong_t caddr, compat_ulong_t cdata) 429 { 430 long ret = -EIO; 431 432 switch (request) { 433 default: 434 ret = compat_ptrace_request(child, request, caddr, cdata); 435 break; 436 } 437 438 return ret; 439 } 440 #else 441 static const struct user_regset_view compat_riscv_user_native_view = {}; 442 #endif /* CONFIG_COMPAT */ 443 444 const struct user_regset_view *task_user_regset_view(struct task_struct *task) 445 { 446 if (is_compat_thread(&task->thread_info)) 447 return &compat_riscv_user_native_view; 448 else 449 return &riscv_user_native_view; 450 } 451