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 #endif 157 158 #ifdef CONFIG_RISCV_ISA_SUPM 159 static int tagged_addr_ctrl_get(struct task_struct *target, 160 const struct user_regset *regset, 161 struct membuf to) 162 { 163 long ctrl = get_tagged_addr_ctrl(target); 164 165 if (IS_ERR_VALUE(ctrl)) 166 return ctrl; 167 168 return membuf_write(&to, &ctrl, sizeof(ctrl)); 169 } 170 171 static int tagged_addr_ctrl_set(struct task_struct *target, 172 const struct user_regset *regset, 173 unsigned int pos, unsigned int count, 174 const void *kbuf, const void __user *ubuf) 175 { 176 int ret; 177 long ctrl; 178 179 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl, 0, -1); 180 if (ret) 181 return ret; 182 183 return set_tagged_addr_ctrl(target, ctrl); 184 } 185 #endif 186 187 static const struct user_regset riscv_user_regset[] = { 188 [REGSET_X] = { 189 .core_note_type = NT_PRSTATUS, 190 .n = ELF_NGREG, 191 .size = sizeof(elf_greg_t), 192 .align = sizeof(elf_greg_t), 193 .regset_get = riscv_gpr_get, 194 .set = riscv_gpr_set, 195 }, 196 #ifdef CONFIG_FPU 197 [REGSET_F] = { 198 .core_note_type = NT_PRFPREG, 199 .n = ELF_NFPREG, 200 .size = sizeof(elf_fpreg_t), 201 .align = sizeof(elf_fpreg_t), 202 .regset_get = riscv_fpr_get, 203 .set = riscv_fpr_set, 204 }, 205 #endif 206 #ifdef CONFIG_RISCV_ISA_V 207 [REGSET_V] = { 208 .core_note_type = NT_RISCV_VECTOR, 209 .align = 16, 210 .n = ((32 * RISCV_MAX_VLENB) + 211 sizeof(struct __riscv_v_regset_state)) / sizeof(__u32), 212 .size = sizeof(__u32), 213 .regset_get = riscv_vr_get, 214 .set = riscv_vr_set, 215 }, 216 #endif 217 #ifdef CONFIG_RISCV_ISA_SUPM 218 [REGSET_TAGGED_ADDR_CTRL] = { 219 .core_note_type = NT_RISCV_TAGGED_ADDR_CTRL, 220 .n = 1, 221 .size = sizeof(long), 222 .align = sizeof(long), 223 .regset_get = tagged_addr_ctrl_get, 224 .set = tagged_addr_ctrl_set, 225 }, 226 #endif 227 }; 228 229 static const struct user_regset_view riscv_user_native_view = { 230 .name = "riscv", 231 .e_machine = EM_RISCV, 232 .regsets = riscv_user_regset, 233 .n = ARRAY_SIZE(riscv_user_regset), 234 }; 235 236 struct pt_regs_offset { 237 const char *name; 238 int offset; 239 }; 240 241 #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)} 242 #define REG_OFFSET_END {.name = NULL, .offset = 0} 243 244 static const struct pt_regs_offset regoffset_table[] = { 245 REG_OFFSET_NAME(epc), 246 REG_OFFSET_NAME(ra), 247 REG_OFFSET_NAME(sp), 248 REG_OFFSET_NAME(gp), 249 REG_OFFSET_NAME(tp), 250 REG_OFFSET_NAME(t0), 251 REG_OFFSET_NAME(t1), 252 REG_OFFSET_NAME(t2), 253 REG_OFFSET_NAME(s0), 254 REG_OFFSET_NAME(s1), 255 REG_OFFSET_NAME(a0), 256 REG_OFFSET_NAME(a1), 257 REG_OFFSET_NAME(a2), 258 REG_OFFSET_NAME(a3), 259 REG_OFFSET_NAME(a4), 260 REG_OFFSET_NAME(a5), 261 REG_OFFSET_NAME(a6), 262 REG_OFFSET_NAME(a7), 263 REG_OFFSET_NAME(s2), 264 REG_OFFSET_NAME(s3), 265 REG_OFFSET_NAME(s4), 266 REG_OFFSET_NAME(s5), 267 REG_OFFSET_NAME(s6), 268 REG_OFFSET_NAME(s7), 269 REG_OFFSET_NAME(s8), 270 REG_OFFSET_NAME(s9), 271 REG_OFFSET_NAME(s10), 272 REG_OFFSET_NAME(s11), 273 REG_OFFSET_NAME(t3), 274 REG_OFFSET_NAME(t4), 275 REG_OFFSET_NAME(t5), 276 REG_OFFSET_NAME(t6), 277 REG_OFFSET_NAME(status), 278 REG_OFFSET_NAME(badaddr), 279 REG_OFFSET_NAME(cause), 280 REG_OFFSET_NAME(orig_a0), 281 REG_OFFSET_END, 282 }; 283 284 /** 285 * regs_query_register_offset() - query register offset from its name 286 * @name: the name of a register 287 * 288 * regs_query_register_offset() returns the offset of a register in struct 289 * pt_regs from its name. If the name is invalid, this returns -EINVAL; 290 */ 291 int regs_query_register_offset(const char *name) 292 { 293 const struct pt_regs_offset *roff; 294 295 for (roff = regoffset_table; roff->name != NULL; roff++) 296 if (!strcmp(roff->name, name)) 297 return roff->offset; 298 return -EINVAL; 299 } 300 301 /** 302 * regs_within_kernel_stack() - check the address in the stack 303 * @regs: pt_regs which contains kernel stack pointer. 304 * @addr: address which is checked. 305 * 306 * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). 307 * If @addr is within the kernel stack, it returns true. If not, returns false. 308 */ 309 static bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) 310 { 311 return (addr & ~(THREAD_SIZE - 1)) == 312 (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)); 313 } 314 315 /** 316 * regs_get_kernel_stack_nth() - get Nth entry of the stack 317 * @regs: pt_regs which contains kernel stack pointer. 318 * @n: stack entry number. 319 * 320 * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which 321 * is specified by @regs. If the @n th entry is NOT in the kernel stack, 322 * this returns 0. 323 */ 324 unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) 325 { 326 unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); 327 328 addr += n; 329 if (regs_within_kernel_stack(regs, (unsigned long)addr)) 330 return *addr; 331 else 332 return 0; 333 } 334 335 void ptrace_disable(struct task_struct *child) 336 { 337 } 338 339 long arch_ptrace(struct task_struct *child, long request, 340 unsigned long addr, unsigned long data) 341 { 342 long ret = -EIO; 343 344 switch (request) { 345 default: 346 ret = ptrace_request(child, request, addr, data); 347 break; 348 } 349 350 return ret; 351 } 352 353 #ifdef CONFIG_COMPAT 354 static int compat_riscv_gpr_get(struct task_struct *target, 355 const struct user_regset *regset, 356 struct membuf to) 357 { 358 struct compat_user_regs_struct cregs; 359 360 regs_to_cregs(&cregs, task_pt_regs(target)); 361 362 return membuf_write(&to, &cregs, 363 sizeof(struct compat_user_regs_struct)); 364 } 365 366 static int compat_riscv_gpr_set(struct task_struct *target, 367 const struct user_regset *regset, 368 unsigned int pos, unsigned int count, 369 const void *kbuf, const void __user *ubuf) 370 { 371 int ret; 372 struct compat_user_regs_struct cregs; 373 374 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &cregs, 0, -1); 375 376 cregs_to_regs(&cregs, task_pt_regs(target)); 377 378 return ret; 379 } 380 381 static const struct user_regset compat_riscv_user_regset[] = { 382 [REGSET_X] = { 383 .core_note_type = NT_PRSTATUS, 384 .n = ELF_NGREG, 385 .size = sizeof(compat_elf_greg_t), 386 .align = sizeof(compat_elf_greg_t), 387 .regset_get = compat_riscv_gpr_get, 388 .set = compat_riscv_gpr_set, 389 }, 390 #ifdef CONFIG_FPU 391 [REGSET_F] = { 392 .core_note_type = NT_PRFPREG, 393 .n = ELF_NFPREG, 394 .size = sizeof(elf_fpreg_t), 395 .align = sizeof(elf_fpreg_t), 396 .regset_get = riscv_fpr_get, 397 .set = riscv_fpr_set, 398 }, 399 #endif 400 }; 401 402 static const struct user_regset_view compat_riscv_user_native_view = { 403 .name = "riscv", 404 .e_machine = EM_RISCV, 405 .regsets = compat_riscv_user_regset, 406 .n = ARRAY_SIZE(compat_riscv_user_regset), 407 }; 408 409 long compat_arch_ptrace(struct task_struct *child, compat_long_t request, 410 compat_ulong_t caddr, compat_ulong_t cdata) 411 { 412 long ret = -EIO; 413 414 switch (request) { 415 default: 416 ret = compat_ptrace_request(child, request, caddr, cdata); 417 break; 418 } 419 420 return ret; 421 } 422 #else 423 static const struct user_regset_view compat_riscv_user_native_view = {}; 424 #endif /* CONFIG_COMPAT */ 425 426 const struct user_regset_view *task_user_regset_view(struct task_struct *task) 427 { 428 if (is_compat_thread(&task->thread_info)) 429 return &compat_riscv_user_native_view; 430 else 431 return &riscv_user_native_view; 432 } 433