Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
0004  */
0005 
0006 #include <linux/ptrace.h>
0007 #include <linux/sched/task_stack.h>
0008 #include <linux/regset.h>
0009 #include <linux/unistd.h>
0010 #include <linux/elf.h>
0011 
0012 #define CREATE_TRACE_POINTS
0013 #include <trace/events/syscalls.h>
0014 
0015 struct pt_regs_offset {
0016     const char *name;
0017     int offset;
0018 };
0019 
0020 #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
0021 #define REG_OFFSET_END {.name = NULL, .offset = 0}
0022 
0023 #ifdef CONFIG_ISA_ARCOMPACT
0024 static const struct pt_regs_offset regoffset_table[] = {
0025     REG_OFFSET_NAME(bta),
0026     REG_OFFSET_NAME(lp_start),
0027     REG_OFFSET_NAME(lp_end),
0028     REG_OFFSET_NAME(lp_count),
0029     REG_OFFSET_NAME(status32),
0030     REG_OFFSET_NAME(ret),
0031     REG_OFFSET_NAME(blink),
0032     REG_OFFSET_NAME(fp),
0033     REG_OFFSET_NAME(r26),
0034     REG_OFFSET_NAME(r12),
0035     REG_OFFSET_NAME(r11),
0036     REG_OFFSET_NAME(r10),
0037     REG_OFFSET_NAME(r9),
0038     REG_OFFSET_NAME(r8),
0039     REG_OFFSET_NAME(r7),
0040     REG_OFFSET_NAME(r6),
0041     REG_OFFSET_NAME(r5),
0042     REG_OFFSET_NAME(r4),
0043     REG_OFFSET_NAME(r3),
0044     REG_OFFSET_NAME(r2),
0045     REG_OFFSET_NAME(r1),
0046     REG_OFFSET_NAME(r0),
0047     REG_OFFSET_NAME(sp),
0048     REG_OFFSET_NAME(orig_r0),
0049     REG_OFFSET_NAME(event),
0050     REG_OFFSET_NAME(user_r25),
0051     REG_OFFSET_END,
0052 };
0053 
0054 #else
0055 
0056 static const struct pt_regs_offset regoffset_table[] = {
0057     REG_OFFSET_NAME(orig_r0),
0058     REG_OFFSET_NAME(event),
0059     REG_OFFSET_NAME(bta),
0060     REG_OFFSET_NAME(user_r25),
0061     REG_OFFSET_NAME(r26),
0062     REG_OFFSET_NAME(fp),
0063     REG_OFFSET_NAME(sp),
0064     REG_OFFSET_NAME(r12),
0065     REG_OFFSET_NAME(r30),
0066 #ifdef CONFIG_ARC_HAS_ACCL_REGS
0067     REG_OFFSET_NAME(r58),
0068     REG_OFFSET_NAME(r59),
0069 #endif
0070 #ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS
0071     REG_OFFSET_NAME(DSP_CTRL),
0072 #endif
0073     REG_OFFSET_NAME(r0),
0074     REG_OFFSET_NAME(r1),
0075     REG_OFFSET_NAME(r2),
0076     REG_OFFSET_NAME(r3),
0077     REG_OFFSET_NAME(r4),
0078     REG_OFFSET_NAME(r5),
0079     REG_OFFSET_NAME(r6),
0080     REG_OFFSET_NAME(r7),
0081     REG_OFFSET_NAME(r8),
0082     REG_OFFSET_NAME(r9),
0083     REG_OFFSET_NAME(r10),
0084     REG_OFFSET_NAME(r11),
0085     REG_OFFSET_NAME(blink),
0086     REG_OFFSET_NAME(lp_end),
0087     REG_OFFSET_NAME(lp_start),
0088     REG_OFFSET_NAME(lp_count),
0089     REG_OFFSET_NAME(ei),
0090     REG_OFFSET_NAME(ldi),
0091     REG_OFFSET_NAME(jli),
0092     REG_OFFSET_NAME(ret),
0093     REG_OFFSET_NAME(status32),
0094     REG_OFFSET_END,
0095 };
0096 #endif
0097 
0098 static struct callee_regs *task_callee_regs(struct task_struct *tsk)
0099 {
0100     struct callee_regs *tmp = (struct callee_regs *)tsk->thread.callee_reg;
0101     return tmp;
0102 }
0103 
0104 static int genregs_get(struct task_struct *target,
0105                const struct user_regset *regset,
0106                struct membuf to)
0107 {
0108     const struct pt_regs *ptregs = task_pt_regs(target);
0109     const struct callee_regs *cregs = task_callee_regs(target);
0110     unsigned int stop_pc_val;
0111 
0112     membuf_zero(&to, 4);    // pad
0113     membuf_store(&to, ptregs->bta);
0114     membuf_store(&to, ptregs->lp_start);
0115     membuf_store(&to, ptregs->lp_end);
0116     membuf_store(&to, ptregs->lp_count);
0117     membuf_store(&to, ptregs->status32);
0118     membuf_store(&to, ptregs->ret);
0119     membuf_store(&to, ptregs->blink);
0120     membuf_store(&to, ptregs->fp);
0121     membuf_store(&to, ptregs->r26); // gp
0122     membuf_store(&to, ptregs->r12);
0123     membuf_store(&to, ptregs->r11);
0124     membuf_store(&to, ptregs->r10);
0125     membuf_store(&to, ptregs->r9);
0126     membuf_store(&to, ptregs->r8);
0127     membuf_store(&to, ptregs->r7);
0128     membuf_store(&to, ptregs->r6);
0129     membuf_store(&to, ptregs->r5);
0130     membuf_store(&to, ptregs->r4);
0131     membuf_store(&to, ptregs->r3);
0132     membuf_store(&to, ptregs->r2);
0133     membuf_store(&to, ptregs->r1);
0134     membuf_store(&to, ptregs->r0);
0135     membuf_store(&to, ptregs->sp);
0136     membuf_zero(&to, 4);    // pad2
0137     membuf_store(&to, cregs->r25);
0138     membuf_store(&to, cregs->r24);
0139     membuf_store(&to, cregs->r23);
0140     membuf_store(&to, cregs->r22);
0141     membuf_store(&to, cregs->r21);
0142     membuf_store(&to, cregs->r20);
0143     membuf_store(&to, cregs->r19);
0144     membuf_store(&to, cregs->r18);
0145     membuf_store(&to, cregs->r17);
0146     membuf_store(&to, cregs->r16);
0147     membuf_store(&to, cregs->r15);
0148     membuf_store(&to, cregs->r14);
0149     membuf_store(&to, cregs->r13);
0150     membuf_store(&to, target->thread.fault_address); // efa
0151 
0152     if (in_brkpt_trap(ptregs)) {
0153         stop_pc_val = target->thread.fault_address;
0154         pr_debug("\t\tstop_pc (brk-pt)\n");
0155     } else {
0156         stop_pc_val = ptregs->ret;
0157         pr_debug("\t\tstop_pc (others)\n");
0158     }
0159 
0160     return membuf_store(&to, stop_pc_val); // stop_pc
0161 }
0162 
0163 static int genregs_set(struct task_struct *target,
0164                const struct user_regset *regset,
0165                unsigned int pos, unsigned int count,
0166                const void *kbuf, const void __user *ubuf)
0167 {
0168     const struct pt_regs *ptregs = task_pt_regs(target);
0169     const struct callee_regs *cregs = task_callee_regs(target);
0170     int ret = 0;
0171 
0172 #define REG_IN_CHUNK(FIRST, NEXT, PTR)  \
0173     if (!ret)           \
0174         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
0175             (void *)(PTR), \
0176             offsetof(struct user_regs_struct, FIRST), \
0177             offsetof(struct user_regs_struct, NEXT));
0178 
0179 #define REG_IN_ONE(LOC, PTR)        \
0180     if (!ret)           \
0181         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
0182             (void *)(PTR), \
0183             offsetof(struct user_regs_struct, LOC), \
0184             offsetof(struct user_regs_struct, LOC) + 4);
0185 
0186 #define REG_IGNORE_ONE(LOC)     \
0187     if (!ret)           \
0188         ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, \
0189             offsetof(struct user_regs_struct, LOC), \
0190             offsetof(struct user_regs_struct, LOC) + 4);
0191 
0192     REG_IGNORE_ONE(pad);
0193 
0194     REG_IN_ONE(scratch.bta, &ptregs->bta);
0195     REG_IN_ONE(scratch.lp_start, &ptregs->lp_start);
0196     REG_IN_ONE(scratch.lp_end, &ptregs->lp_end);
0197     REG_IN_ONE(scratch.lp_count, &ptregs->lp_count);
0198 
0199     REG_IGNORE_ONE(scratch.status32);
0200 
0201     REG_IN_ONE(scratch.ret, &ptregs->ret);
0202     REG_IN_ONE(scratch.blink, &ptregs->blink);
0203     REG_IN_ONE(scratch.fp, &ptregs->fp);
0204     REG_IN_ONE(scratch.gp, &ptregs->r26);
0205     REG_IN_ONE(scratch.r12, &ptregs->r12);
0206     REG_IN_ONE(scratch.r11, &ptregs->r11);
0207     REG_IN_ONE(scratch.r10, &ptregs->r10);
0208     REG_IN_ONE(scratch.r9, &ptregs->r9);
0209     REG_IN_ONE(scratch.r8, &ptregs->r8);
0210     REG_IN_ONE(scratch.r7, &ptregs->r7);
0211     REG_IN_ONE(scratch.r6, &ptregs->r6);
0212     REG_IN_ONE(scratch.r5, &ptregs->r5);
0213     REG_IN_ONE(scratch.r4, &ptregs->r4);
0214     REG_IN_ONE(scratch.r3, &ptregs->r3);
0215     REG_IN_ONE(scratch.r2, &ptregs->r2);
0216     REG_IN_ONE(scratch.r1, &ptregs->r1);
0217     REG_IN_ONE(scratch.r0, &ptregs->r0);
0218     REG_IN_ONE(scratch.sp, &ptregs->sp);
0219 
0220     REG_IGNORE_ONE(pad2);
0221 
0222     REG_IN_ONE(callee.r25, &cregs->r25);
0223     REG_IN_ONE(callee.r24, &cregs->r24);
0224     REG_IN_ONE(callee.r23, &cregs->r23);
0225     REG_IN_ONE(callee.r22, &cregs->r22);
0226     REG_IN_ONE(callee.r21, &cregs->r21);
0227     REG_IN_ONE(callee.r20, &cregs->r20);
0228     REG_IN_ONE(callee.r19, &cregs->r19);
0229     REG_IN_ONE(callee.r18, &cregs->r18);
0230     REG_IN_ONE(callee.r17, &cregs->r17);
0231     REG_IN_ONE(callee.r16, &cregs->r16);
0232     REG_IN_ONE(callee.r15, &cregs->r15);
0233     REG_IN_ONE(callee.r14, &cregs->r14);
0234     REG_IN_ONE(callee.r13, &cregs->r13);
0235 
0236     REG_IGNORE_ONE(efa);            /* efa update invalid */
0237     REG_IGNORE_ONE(stop_pc);        /* PC updated via @ret */
0238 
0239     return ret;
0240 }
0241 
0242 #ifdef CONFIG_ISA_ARCV2
0243 static int arcv2regs_get(struct task_struct *target,
0244                const struct user_regset *regset,
0245                struct membuf to)
0246 {
0247     const struct pt_regs *regs = task_pt_regs(target);
0248 
0249     if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS))
0250         /*
0251          * itemized copy not needed like above as layout of regs (r30,r58,r59)
0252          * is exactly same in kernel (pt_regs) and userspace (user_regs_arcv2)
0253          */
0254         return membuf_write(&to, &regs->r30, sizeof(struct user_regs_arcv2));
0255 
0256 
0257     membuf_write(&to, &regs->r30, 4); /* r30 only */
0258     return membuf_zero(&to, sizeof(struct user_regs_arcv2) - 4);
0259 }
0260 
0261 static int arcv2regs_set(struct task_struct *target,
0262                const struct user_regset *regset,
0263                unsigned int pos, unsigned int count,
0264                const void *kbuf, const void __user *ubuf)
0265 {
0266     const struct pt_regs *regs = task_pt_regs(target);
0267     int ret, copy_sz;
0268 
0269     if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS))
0270         copy_sz = sizeof(struct user_regs_arcv2);
0271     else
0272         copy_sz = 4;    /* r30 only */
0273 
0274     ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, (void *)&regs->r30,
0275                   0, copy_sz);
0276 
0277     return ret;
0278 }
0279 
0280 #endif
0281 
0282 enum arc_getset {
0283     REGSET_CMN,
0284     REGSET_ARCV2,
0285 };
0286 
0287 static const struct user_regset arc_regsets[] = {
0288     [REGSET_CMN] = {
0289            .core_note_type = NT_PRSTATUS,
0290            .n = ELF_NGREG,
0291            .size = sizeof(unsigned long),
0292            .align = sizeof(unsigned long),
0293            .regset_get = genregs_get,
0294            .set = genregs_set,
0295     },
0296 #ifdef CONFIG_ISA_ARCV2
0297     [REGSET_ARCV2] = {
0298            .core_note_type = NT_ARC_V2,
0299            .n = ELF_ARCV2REG,
0300            .size = sizeof(unsigned long),
0301            .align = sizeof(unsigned long),
0302            .regset_get = arcv2regs_get,
0303            .set = arcv2regs_set,
0304     },
0305 #endif
0306 };
0307 
0308 static const struct user_regset_view user_arc_view = {
0309     .name       = "arc",
0310     .e_machine  = EM_ARC_INUSE,
0311     .regsets    = arc_regsets,
0312     .n      = ARRAY_SIZE(arc_regsets)
0313 };
0314 
0315 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
0316 {
0317     return &user_arc_view;
0318 }
0319 
0320 void ptrace_disable(struct task_struct *child)
0321 {
0322 }
0323 
0324 long arch_ptrace(struct task_struct *child, long request,
0325          unsigned long addr, unsigned long data)
0326 {
0327     int ret = -EIO;
0328 
0329     pr_debug("REQ=%ld: ADDR =0x%lx, DATA=0x%lx)\n", request, addr, data);
0330 
0331     switch (request) {
0332     case PTRACE_GET_THREAD_AREA:
0333         ret = put_user(task_thread_info(child)->thr_ptr,
0334                    (unsigned long __user *)data);
0335         break;
0336     default:
0337         ret = ptrace_request(child, request, addr, data);
0338         break;
0339     }
0340 
0341     return ret;
0342 }
0343 
0344 asmlinkage int syscall_trace_entry(struct pt_regs *regs)
0345 {
0346     if (test_thread_flag(TIF_SYSCALL_TRACE))
0347         if (ptrace_report_syscall_entry(regs))
0348             return ULONG_MAX;
0349 
0350 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
0351     if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
0352         trace_sys_enter(regs, syscall_get_nr(current, regs));
0353 #endif
0354 
0355     return regs->r8;
0356 }
0357 
0358 asmlinkage void syscall_trace_exit(struct pt_regs *regs)
0359 {
0360     if (test_thread_flag(TIF_SYSCALL_TRACE))
0361         ptrace_report_syscall_exit(regs, 0);
0362 
0363 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
0364     if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
0365         trace_sys_exit(regs, regs_return_value(regs));
0366 #endif
0367 }
0368 
0369 int regs_query_register_offset(const char *name)
0370 {
0371     const struct pt_regs_offset *roff;
0372 
0373     for (roff = regoffset_table; roff->name != NULL; roff++)
0374         if (!strcmp(roff->name, name))
0375             return roff->offset;
0376     return -EINVAL;
0377 }
0378 
0379 const char *regs_query_register_name(unsigned int offset)
0380 {
0381     const struct pt_regs_offset *roff;
0382     for (roff = regoffset_table; roff->name != NULL; roff++)
0383         if (roff->offset == offset)
0384             return roff->name;
0385     return NULL;
0386 }
0387 
0388 bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
0389 {
0390     return (addr & ~(THREAD_SIZE - 1))  ==
0391         (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1));
0392 }
0393 
0394 unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
0395 {
0396     unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
0397 
0398     addr += n;
0399     if (regs_within_kernel_stack(regs, (unsigned long)addr))
0400         return *addr;
0401     else
0402         return 0;
0403 }