1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) 4 */ 5 6 #include <linux/ptrace.h> 7 #include <linux/sched/task_stack.h> 8 #include <linux/regset.h> 9 #include <linux/unistd.h> 10 #include <linux/elf.h> 11 12 #define CREATE_TRACE_POINTS 13 #include <trace/events/syscalls.h> 14 15 struct pt_regs_offset { 16 const char *name; 17 int offset; 18 }; 19 20 #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)} 21 #define REG_OFFSET_END {.name = NULL, .offset = 0} 22 23 #ifdef CONFIG_ISA_ARCOMPACT 24 static const struct pt_regs_offset regoffset_table[] = { 25 REG_OFFSET_NAME(bta), 26 REG_OFFSET_NAME(lp_start), 27 REG_OFFSET_NAME(lp_end), 28 REG_OFFSET_NAME(lp_count), 29 REG_OFFSET_NAME(status32), 30 REG_OFFSET_NAME(ret), 31 REG_OFFSET_NAME(blink), 32 REG_OFFSET_NAME(fp), 33 REG_OFFSET_NAME(r26), 34 REG_OFFSET_NAME(r12), 35 REG_OFFSET_NAME(r11), 36 REG_OFFSET_NAME(r10), 37 REG_OFFSET_NAME(r9), 38 REG_OFFSET_NAME(r8), 39 REG_OFFSET_NAME(r7), 40 REG_OFFSET_NAME(r6), 41 REG_OFFSET_NAME(r5), 42 REG_OFFSET_NAME(r4), 43 REG_OFFSET_NAME(r3), 44 REG_OFFSET_NAME(r2), 45 REG_OFFSET_NAME(r1), 46 REG_OFFSET_NAME(r0), 47 REG_OFFSET_NAME(sp), 48 REG_OFFSET_NAME(orig_r0), 49 REG_OFFSET_NAME(ecr), 50 REG_OFFSET_END, 51 }; 52 53 #else 54 55 static const struct pt_regs_offset regoffset_table[] = { 56 REG_OFFSET_NAME(orig_r0), 57 REG_OFFSET_NAME(ecr), 58 REG_OFFSET_NAME(bta), 59 REG_OFFSET_NAME(r26), 60 REG_OFFSET_NAME(fp), 61 REG_OFFSET_NAME(sp), 62 REG_OFFSET_NAME(r12), 63 REG_OFFSET_NAME(r30), 64 #ifdef CONFIG_ARC_HAS_ACCL_REGS 65 REG_OFFSET_NAME(r58), 66 REG_OFFSET_NAME(r59), 67 #endif 68 #ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS 69 REG_OFFSET_NAME(DSP_CTRL), 70 #endif 71 REG_OFFSET_NAME(r0), 72 REG_OFFSET_NAME(r1), 73 REG_OFFSET_NAME(r2), 74 REG_OFFSET_NAME(r3), 75 REG_OFFSET_NAME(r4), 76 REG_OFFSET_NAME(r5), 77 REG_OFFSET_NAME(r6), 78 REG_OFFSET_NAME(r7), 79 REG_OFFSET_NAME(r8), 80 REG_OFFSET_NAME(r9), 81 REG_OFFSET_NAME(r10), 82 REG_OFFSET_NAME(r11), 83 REG_OFFSET_NAME(blink), 84 REG_OFFSET_NAME(lp_end), 85 REG_OFFSET_NAME(lp_start), 86 REG_OFFSET_NAME(lp_count), 87 REG_OFFSET_NAME(ei), 88 REG_OFFSET_NAME(ldi), 89 REG_OFFSET_NAME(jli), 90 REG_OFFSET_NAME(ret), 91 REG_OFFSET_NAME(status32), 92 REG_OFFSET_END, 93 }; 94 #endif 95 96 static struct callee_regs *task_callee_regs(struct task_struct *tsk) 97 { 98 struct callee_regs *tmp = (struct callee_regs *)tsk->thread.callee_reg; 99 return tmp; 100 } 101 102 static int genregs_get(struct task_struct *target, 103 const struct user_regset *regset, 104 struct membuf to) 105 { 106 const struct pt_regs *ptregs = task_pt_regs(target); 107 const struct callee_regs *cregs = task_callee_regs(target); 108 unsigned int stop_pc_val; 109 110 membuf_zero(&to, 4); // pad 111 membuf_store(&to, ptregs->bta); 112 membuf_store(&to, ptregs->lp_start); 113 membuf_store(&to, ptregs->lp_end); 114 membuf_store(&to, ptregs->lp_count); 115 membuf_store(&to, ptregs->status32); 116 membuf_store(&to, ptregs->ret); 117 membuf_store(&to, ptregs->blink); 118 membuf_store(&to, ptregs->fp); 119 membuf_store(&to, ptregs->r26); // gp 120 membuf_store(&to, ptregs->r12); 121 membuf_store(&to, ptregs->r11); 122 membuf_store(&to, ptregs->r10); 123 membuf_store(&to, ptregs->r9); 124 membuf_store(&to, ptregs->r8); 125 membuf_store(&to, ptregs->r7); 126 membuf_store(&to, ptregs->r6); 127 membuf_store(&to, ptregs->r5); 128 membuf_store(&to, ptregs->r4); 129 membuf_store(&to, ptregs->r3); 130 membuf_store(&to, ptregs->r2); 131 membuf_store(&to, ptregs->r1); 132 membuf_store(&to, ptregs->r0); 133 membuf_store(&to, ptregs->sp); 134 membuf_zero(&to, 4); // pad2 135 membuf_store(&to, cregs->r25); 136 membuf_store(&to, cregs->r24); 137 membuf_store(&to, cregs->r23); 138 membuf_store(&to, cregs->r22); 139 membuf_store(&to, cregs->r21); 140 membuf_store(&to, cregs->r20); 141 membuf_store(&to, cregs->r19); 142 membuf_store(&to, cregs->r18); 143 membuf_store(&to, cregs->r17); 144 membuf_store(&to, cregs->r16); 145 membuf_store(&to, cregs->r15); 146 membuf_store(&to, cregs->r14); 147 membuf_store(&to, cregs->r13); 148 membuf_store(&to, target->thread.fault_address); // efa 149 150 if (in_brkpt_trap(ptregs)) { 151 stop_pc_val = target->thread.fault_address; 152 pr_debug("\t\tstop_pc (brk-pt)\n"); 153 } else { 154 stop_pc_val = ptregs->ret; 155 pr_debug("\t\tstop_pc (others)\n"); 156 } 157 158 return membuf_store(&to, stop_pc_val); // stop_pc 159 } 160 161 static int genregs_set(struct task_struct *target, 162 const struct user_regset *regset, 163 unsigned int pos, unsigned int count, 164 const void *kbuf, const void __user *ubuf) 165 { 166 const struct pt_regs *ptregs = task_pt_regs(target); 167 const struct callee_regs *cregs = task_callee_regs(target); 168 int ret = 0; 169 170 #define REG_IN_CHUNK(FIRST, NEXT, PTR) \ 171 if (!ret) \ 172 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \ 173 (void *)(PTR), \ 174 offsetof(struct user_regs_struct, FIRST), \ 175 offsetof(struct user_regs_struct, NEXT)); 176 177 #define REG_IN_ONE(LOC, PTR) \ 178 if (!ret) \ 179 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \ 180 (void *)(PTR), \ 181 offsetof(struct user_regs_struct, LOC), \ 182 offsetof(struct user_regs_struct, LOC) + 4); 183 184 #define REG_IGNORE_ONE(LOC) \ 185 if (!ret) \ 186 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, \ 187 offsetof(struct user_regs_struct, LOC), \ 188 offsetof(struct user_regs_struct, LOC) + 4); 189 190 REG_IGNORE_ONE(pad); 191 192 REG_IN_ONE(scratch.bta, &ptregs->bta); 193 REG_IN_ONE(scratch.lp_start, &ptregs->lp_start); 194 REG_IN_ONE(scratch.lp_end, &ptregs->lp_end); 195 REG_IN_ONE(scratch.lp_count, &ptregs->lp_count); 196 197 REG_IGNORE_ONE(scratch.status32); 198 199 REG_IN_ONE(scratch.ret, &ptregs->ret); 200 REG_IN_ONE(scratch.blink, &ptregs->blink); 201 REG_IN_ONE(scratch.fp, &ptregs->fp); 202 REG_IN_ONE(scratch.gp, &ptregs->r26); 203 REG_IN_ONE(scratch.r12, &ptregs->r12); 204 REG_IN_ONE(scratch.r11, &ptregs->r11); 205 REG_IN_ONE(scratch.r10, &ptregs->r10); 206 REG_IN_ONE(scratch.r9, &ptregs->r9); 207 REG_IN_ONE(scratch.r8, &ptregs->r8); 208 REG_IN_ONE(scratch.r7, &ptregs->r7); 209 REG_IN_ONE(scratch.r6, &ptregs->r6); 210 REG_IN_ONE(scratch.r5, &ptregs->r5); 211 REG_IN_ONE(scratch.r4, &ptregs->r4); 212 REG_IN_ONE(scratch.r3, &ptregs->r3); 213 REG_IN_ONE(scratch.r2, &ptregs->r2); 214 REG_IN_ONE(scratch.r1, &ptregs->r1); 215 REG_IN_ONE(scratch.r0, &ptregs->r0); 216 REG_IN_ONE(scratch.sp, &ptregs->sp); 217 218 REG_IGNORE_ONE(pad2); 219 220 REG_IN_ONE(callee.r25, &cregs->r25); 221 REG_IN_ONE(callee.r24, &cregs->r24); 222 REG_IN_ONE(callee.r23, &cregs->r23); 223 REG_IN_ONE(callee.r22, &cregs->r22); 224 REG_IN_ONE(callee.r21, &cregs->r21); 225 REG_IN_ONE(callee.r20, &cregs->r20); 226 REG_IN_ONE(callee.r19, &cregs->r19); 227 REG_IN_ONE(callee.r18, &cregs->r18); 228 REG_IN_ONE(callee.r17, &cregs->r17); 229 REG_IN_ONE(callee.r16, &cregs->r16); 230 REG_IN_ONE(callee.r15, &cregs->r15); 231 REG_IN_ONE(callee.r14, &cregs->r14); 232 REG_IN_ONE(callee.r13, &cregs->r13); 233 234 REG_IGNORE_ONE(efa); /* efa update invalid */ 235 REG_IGNORE_ONE(stop_pc); /* PC updated via @ret */ 236 237 return ret; 238 } 239 240 #ifdef CONFIG_ISA_ARCV2 241 static int arcv2regs_get(struct task_struct *target, 242 const struct user_regset *regset, 243 struct membuf to) 244 { 245 const struct pt_regs *regs = task_pt_regs(target); 246 247 if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS)) 248 /* 249 * itemized copy not needed like above as layout of regs (r30,r58,r59) 250 * is exactly same in kernel (pt_regs) and userspace (user_regs_arcv2) 251 */ 252 return membuf_write(&to, ®s->r30, sizeof(struct user_regs_arcv2)); 253 254 255 membuf_write(&to, ®s->r30, 4); /* r30 only */ 256 return membuf_zero(&to, sizeof(struct user_regs_arcv2) - 4); 257 } 258 259 static int arcv2regs_set(struct task_struct *target, 260 const struct user_regset *regset, 261 unsigned int pos, unsigned int count, 262 const void *kbuf, const void __user *ubuf) 263 { 264 const struct pt_regs *regs = task_pt_regs(target); 265 int ret, copy_sz; 266 267 if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS)) 268 copy_sz = sizeof(struct user_regs_arcv2); 269 else 270 copy_sz = 4; /* r30 only */ 271 272 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, (void *)®s->r30, 273 0, copy_sz); 274 275 return ret; 276 } 277 278 #endif 279 280 enum arc_getset { 281 REGSET_CMN, 282 REGSET_ARCV2, 283 }; 284 285 static const struct user_regset arc_regsets[] = { 286 [REGSET_CMN] = { 287 .core_note_type = NT_PRSTATUS, 288 .n = ELF_NGREG, 289 .size = sizeof(unsigned long), 290 .align = sizeof(unsigned long), 291 .regset_get = genregs_get, 292 .set = genregs_set, 293 }, 294 #ifdef CONFIG_ISA_ARCV2 295 [REGSET_ARCV2] = { 296 .core_note_type = NT_ARC_V2, 297 .n = ELF_ARCV2REG, 298 .size = sizeof(unsigned long), 299 .align = sizeof(unsigned long), 300 .regset_get = arcv2regs_get, 301 .set = arcv2regs_set, 302 }, 303 #endif 304 }; 305 306 static const struct user_regset_view user_arc_view = { 307 .name = "arc", 308 .e_machine = EM_ARC_INUSE, 309 .regsets = arc_regsets, 310 .n = ARRAY_SIZE(arc_regsets) 311 }; 312 313 const struct user_regset_view *task_user_regset_view(struct task_struct *task) 314 { 315 return &user_arc_view; 316 } 317 318 void ptrace_disable(struct task_struct *child) 319 { 320 } 321 322 long arch_ptrace(struct task_struct *child, long request, 323 unsigned long addr, unsigned long data) 324 { 325 int ret = -EIO; 326 327 pr_debug("REQ=%ld: ADDR =0x%lx, DATA=0x%lx)\n", request, addr, data); 328 329 switch (request) { 330 case PTRACE_GET_THREAD_AREA: 331 ret = put_user(task_thread_info(child)->thr_ptr, 332 (unsigned long __user *)data); 333 break; 334 default: 335 ret = ptrace_request(child, request, addr, data); 336 break; 337 } 338 339 return ret; 340 } 341 342 asmlinkage int syscall_trace_enter(struct pt_regs *regs) 343 { 344 if (test_thread_flag(TIF_SYSCALL_TRACE)) 345 if (ptrace_report_syscall_entry(regs)) 346 return ULONG_MAX; 347 348 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS 349 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) 350 trace_sys_enter(regs, syscall_get_nr(current, regs)); 351 #endif 352 353 return regs->r8; 354 } 355 356 asmlinkage void syscall_trace_exit(struct pt_regs *regs) 357 { 358 if (test_thread_flag(TIF_SYSCALL_TRACE)) 359 ptrace_report_syscall_exit(regs, 0); 360 361 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS 362 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) 363 trace_sys_exit(regs, regs_return_value(regs)); 364 #endif 365 } 366 367 int regs_query_register_offset(const char *name) 368 { 369 const struct pt_regs_offset *roff; 370 371 for (roff = regoffset_table; roff->name != NULL; roff++) 372 if (!strcmp(roff->name, name)) 373 return roff->offset; 374 return -EINVAL; 375 } 376 377 const char *regs_query_register_name(unsigned int offset) 378 { 379 const struct pt_regs_offset *roff; 380 for (roff = regoffset_table; roff->name != NULL; roff++) 381 if (roff->offset == offset) 382 return roff->name; 383 return NULL; 384 } 385 386 bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) 387 { 388 return (addr & ~(THREAD_SIZE - 1)) == 389 (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)); 390 } 391 392 unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) 393 { 394 unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); 395 396 addr += n; 397 if (regs_within_kernel_stack(regs, (unsigned long)addr)) 398 return *addr; 399 else 400 return 0; 401 } 402