0001
0002
0003
0004 #include <linux/audit.h>
0005 #include <linux/elf.h>
0006 #include <linux/errno.h>
0007 #include <linux/kernel.h>
0008 #include <linux/mm.h>
0009 #include <linux/ptrace.h>
0010 #include <linux/regset.h>
0011 #include <linux/sched.h>
0012 #include <linux/sched/task_stack.h>
0013 #include <linux/signal.h>
0014 #include <linux/smp.h>
0015 #include <linux/uaccess.h>
0016 #include <linux/user.h>
0017
0018 #include <asm/thread_info.h>
0019 #include <asm/page.h>
0020 #include <asm/processor.h>
0021 #include <asm/asm-offsets.h>
0022
0023 #include <abi/regdef.h>
0024 #include <abi/ckmmu.h>
0025
0026 #define CREATE_TRACE_POINTS
0027 #include <trace/events/syscalls.h>
0028
0029
0030 #define TRACE_MODE_SI (1 << 14)
0031 #define TRACE_MODE_RUN 0
0032 #define TRACE_MODE_MASK ~(0x3 << 14)
0033
0034
0035
0036
0037 static void singlestep_disable(struct task_struct *tsk)
0038 {
0039 struct pt_regs *regs;
0040
0041 regs = task_pt_regs(tsk);
0042 regs->sr = (regs->sr & TRACE_MODE_MASK) | TRACE_MODE_RUN;
0043
0044
0045 regs->sr |= BIT(6);
0046 }
0047
0048 static void singlestep_enable(struct task_struct *tsk)
0049 {
0050 struct pt_regs *regs;
0051
0052 regs = task_pt_regs(tsk);
0053 regs->sr = (regs->sr & TRACE_MODE_MASK) | TRACE_MODE_SI;
0054
0055
0056 regs->sr &= ~BIT(6);
0057 }
0058
0059
0060
0061
0062 void user_enable_single_step(struct task_struct *child)
0063 {
0064 singlestep_enable(child);
0065 }
0066
0067 void user_disable_single_step(struct task_struct *child)
0068 {
0069 singlestep_disable(child);
0070 }
0071
0072 enum csky_regset {
0073 REGSET_GPR,
0074 REGSET_FPR,
0075 };
0076
0077 static int gpr_get(struct task_struct *target,
0078 const struct user_regset *regset,
0079 struct membuf to)
0080 {
0081 struct pt_regs *regs = task_pt_regs(target);
0082
0083
0084 regs->tls = task_thread_info(target)->tp_value;
0085
0086 return membuf_write(&to, regs, sizeof(*regs));
0087 }
0088
0089 static int gpr_set(struct task_struct *target,
0090 const struct user_regset *regset,
0091 unsigned int pos, unsigned int count,
0092 const void *kbuf, const void __user *ubuf)
0093 {
0094 int ret;
0095 struct pt_regs regs;
0096
0097 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®s, 0, -1);
0098 if (ret)
0099 return ret;
0100
0101
0102 regs.sr = (regs.sr & BIT(0)) | (task_pt_regs(target)->sr & ~BIT(0));
0103 #ifdef CONFIG_CPU_HAS_HILO
0104 regs.dcsr = task_pt_regs(target)->dcsr;
0105 #endif
0106 task_thread_info(target)->tp_value = regs.tls;
0107
0108 *task_pt_regs(target) = regs;
0109
0110 return 0;
0111 }
0112
0113 static int fpr_get(struct task_struct *target,
0114 const struct user_regset *regset,
0115 struct membuf to)
0116 {
0117 struct user_fp *regs = (struct user_fp *)&target->thread.user_fp;
0118
0119 #if defined(CONFIG_CPU_HAS_FPUV2) && !defined(CONFIG_CPU_HAS_VDSP)
0120 int i;
0121 struct user_fp tmp = *regs;
0122
0123 for (i = 0; i < 16; i++) {
0124 tmp.vr[i*4] = regs->vr[i*2];
0125 tmp.vr[i*4 + 1] = regs->vr[i*2 + 1];
0126 }
0127
0128 for (i = 0; i < 32; i++)
0129 tmp.vr[64 + i] = regs->vr[32 + i];
0130
0131 return membuf_write(&to, &tmp, sizeof(tmp));
0132 #else
0133 return membuf_write(&to, regs, sizeof(*regs));
0134 #endif
0135 }
0136
0137 static int fpr_set(struct task_struct *target,
0138 const struct user_regset *regset,
0139 unsigned int pos, unsigned int count,
0140 const void *kbuf, const void __user *ubuf)
0141 {
0142 int ret;
0143 struct user_fp *regs = (struct user_fp *)&target->thread.user_fp;
0144
0145 #if defined(CONFIG_CPU_HAS_FPUV2) && !defined(CONFIG_CPU_HAS_VDSP)
0146 int i;
0147 struct user_fp tmp;
0148
0149 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tmp, 0, -1);
0150
0151 *regs = tmp;
0152
0153 for (i = 0; i < 16; i++) {
0154 regs->vr[i*2] = tmp.vr[i*4];
0155 regs->vr[i*2 + 1] = tmp.vr[i*4 + 1];
0156 }
0157
0158 for (i = 0; i < 32; i++)
0159 regs->vr[32 + i] = tmp.vr[64 + i];
0160 #else
0161 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, regs, 0, -1);
0162 #endif
0163
0164 return ret;
0165 }
0166
0167 static const struct user_regset csky_regsets[] = {
0168 [REGSET_GPR] = {
0169 .core_note_type = NT_PRSTATUS,
0170 .n = sizeof(struct pt_regs) / sizeof(u32),
0171 .size = sizeof(u32),
0172 .align = sizeof(u32),
0173 .regset_get = gpr_get,
0174 .set = gpr_set,
0175 },
0176 [REGSET_FPR] = {
0177 .core_note_type = NT_PRFPREG,
0178 .n = sizeof(struct user_fp) / sizeof(u32),
0179 .size = sizeof(u32),
0180 .align = sizeof(u32),
0181 .regset_get = fpr_get,
0182 .set = fpr_set,
0183 },
0184 };
0185
0186 static const struct user_regset_view user_csky_view = {
0187 .name = "csky",
0188 .e_machine = ELF_ARCH,
0189 .regsets = csky_regsets,
0190 .n = ARRAY_SIZE(csky_regsets),
0191 };
0192
0193 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
0194 {
0195 return &user_csky_view;
0196 }
0197
0198 struct pt_regs_offset {
0199 const char *name;
0200 int offset;
0201 };
0202
0203 #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
0204 #define REG_OFFSET_END {.name = NULL, .offset = 0}
0205
0206 static const struct pt_regs_offset regoffset_table[] = {
0207 REG_OFFSET_NAME(tls),
0208 REG_OFFSET_NAME(lr),
0209 REG_OFFSET_NAME(pc),
0210 REG_OFFSET_NAME(sr),
0211 REG_OFFSET_NAME(usp),
0212 REG_OFFSET_NAME(orig_a0),
0213 REG_OFFSET_NAME(a0),
0214 REG_OFFSET_NAME(a1),
0215 REG_OFFSET_NAME(a2),
0216 REG_OFFSET_NAME(a3),
0217 REG_OFFSET_NAME(regs[0]),
0218 REG_OFFSET_NAME(regs[1]),
0219 REG_OFFSET_NAME(regs[2]),
0220 REG_OFFSET_NAME(regs[3]),
0221 REG_OFFSET_NAME(regs[4]),
0222 REG_OFFSET_NAME(regs[5]),
0223 REG_OFFSET_NAME(regs[6]),
0224 REG_OFFSET_NAME(regs[7]),
0225 REG_OFFSET_NAME(regs[8]),
0226 REG_OFFSET_NAME(regs[9]),
0227 #if defined(__CSKYABIV2__)
0228 REG_OFFSET_NAME(exregs[0]),
0229 REG_OFFSET_NAME(exregs[1]),
0230 REG_OFFSET_NAME(exregs[2]),
0231 REG_OFFSET_NAME(exregs[3]),
0232 REG_OFFSET_NAME(exregs[4]),
0233 REG_OFFSET_NAME(exregs[5]),
0234 REG_OFFSET_NAME(exregs[6]),
0235 REG_OFFSET_NAME(exregs[7]),
0236 REG_OFFSET_NAME(exregs[8]),
0237 REG_OFFSET_NAME(exregs[9]),
0238 REG_OFFSET_NAME(exregs[10]),
0239 REG_OFFSET_NAME(exregs[11]),
0240 REG_OFFSET_NAME(exregs[12]),
0241 REG_OFFSET_NAME(exregs[13]),
0242 REG_OFFSET_NAME(exregs[14]),
0243 REG_OFFSET_NAME(rhi),
0244 REG_OFFSET_NAME(rlo),
0245 REG_OFFSET_NAME(dcsr),
0246 #endif
0247 REG_OFFSET_END,
0248 };
0249
0250
0251
0252
0253
0254
0255
0256
0257 int regs_query_register_offset(const char *name)
0258 {
0259 const struct pt_regs_offset *roff;
0260
0261 for (roff = regoffset_table; roff->name != NULL; roff++)
0262 if (!strcmp(roff->name, name))
0263 return roff->offset;
0264 return -EINVAL;
0265 }
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275 static bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
0276 {
0277 return (addr & ~(THREAD_SIZE - 1)) ==
0278 (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1));
0279 }
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290 unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
0291 {
0292 unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
0293
0294 addr += n;
0295 if (regs_within_kernel_stack(regs, (unsigned long)addr))
0296 return *addr;
0297 else
0298 return 0;
0299 }
0300
0301 void ptrace_disable(struct task_struct *child)
0302 {
0303 singlestep_disable(child);
0304 }
0305
0306 long arch_ptrace(struct task_struct *child, long request,
0307 unsigned long addr, unsigned long data)
0308 {
0309 long ret = -EIO;
0310
0311 switch (request) {
0312 default:
0313 ret = ptrace_request(child, request, addr, data);
0314 break;
0315 }
0316
0317 return ret;
0318 }
0319
0320 asmlinkage int syscall_trace_enter(struct pt_regs *regs)
0321 {
0322 if (test_thread_flag(TIF_SYSCALL_TRACE))
0323 if (ptrace_report_syscall_entry(regs))
0324 return -1;
0325
0326 if (secure_computing() == -1)
0327 return -1;
0328
0329 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
0330 trace_sys_enter(regs, syscall_get_nr(current, regs));
0331
0332 audit_syscall_entry(regs_syscallid(regs), regs->a0, regs->a1, regs->a2, regs->a3);
0333 return 0;
0334 }
0335
0336 asmlinkage void syscall_trace_exit(struct pt_regs *regs)
0337 {
0338 audit_syscall_exit(regs);
0339
0340 if (test_thread_flag(TIF_SYSCALL_TRACE))
0341 ptrace_report_syscall_exit(regs, 0);
0342
0343 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
0344 trace_sys_exit(regs, syscall_get_return_value(current, regs));
0345 }
0346
0347 #ifdef CONFIG_CPU_CK860
0348 static void show_iutlb(void)
0349 {
0350 int entry, i;
0351 unsigned long flags;
0352 unsigned long oldpid;
0353 unsigned long entryhi[16], entrylo0[16], entrylo1[16];
0354
0355 oldpid = read_mmu_entryhi();
0356
0357 entry = 0x8000;
0358
0359 local_irq_save(flags);
0360
0361 for (i = 0; i < 16; i++) {
0362 write_mmu_index(entry);
0363 tlb_read();
0364 entryhi[i] = read_mmu_entryhi();
0365 entrylo0[i] = read_mmu_entrylo0();
0366 entrylo1[i] = read_mmu_entrylo1();
0367
0368 entry++;
0369 }
0370
0371 local_irq_restore(flags);
0372
0373 write_mmu_entryhi(oldpid);
0374
0375 printk("\n\n\n");
0376 for (i = 0; i < 16; i++)
0377 printk("iutlb[%d]: entryhi - 0x%lx; entrylo0 - 0x%lx;"
0378 " entrylo1 - 0x%lx\n",
0379 i, entryhi[i], entrylo0[i], entrylo1[i]);
0380 printk("\n\n\n");
0381 }
0382
0383 static void show_dutlb(void)
0384 {
0385 int entry, i;
0386 unsigned long flags;
0387 unsigned long oldpid;
0388 unsigned long entryhi[16], entrylo0[16], entrylo1[16];
0389
0390 oldpid = read_mmu_entryhi();
0391
0392 entry = 0x4000;
0393
0394 local_irq_save(flags);
0395
0396 for (i = 0; i < 16; i++) {
0397 write_mmu_index(entry);
0398 tlb_read();
0399 entryhi[i] = read_mmu_entryhi();
0400 entrylo0[i] = read_mmu_entrylo0();
0401 entrylo1[i] = read_mmu_entrylo1();
0402
0403 entry++;
0404 }
0405
0406 local_irq_restore(flags);
0407
0408 write_mmu_entryhi(oldpid);
0409
0410 printk("\n\n\n");
0411 for (i = 0; i < 16; i++)
0412 printk("dutlb[%d]: entryhi - 0x%lx; entrylo0 - 0x%lx;"
0413 " entrylo1 - 0x%lx\n",
0414 i, entryhi[i], entrylo0[i], entrylo1[i]);
0415 printk("\n\n\n");
0416 }
0417
0418 static unsigned long entryhi[1024], entrylo0[1024], entrylo1[1024];
0419 static void show_jtlb(void)
0420 {
0421 int entry;
0422 unsigned long flags;
0423 unsigned long oldpid;
0424
0425 oldpid = read_mmu_entryhi();
0426
0427 entry = 0;
0428
0429 local_irq_save(flags);
0430 while (entry < 1024) {
0431 write_mmu_index(entry);
0432 tlb_read();
0433 entryhi[entry] = read_mmu_entryhi();
0434 entrylo0[entry] = read_mmu_entrylo0();
0435 entrylo1[entry] = read_mmu_entrylo1();
0436
0437 entry++;
0438 }
0439 local_irq_restore(flags);
0440
0441 write_mmu_entryhi(oldpid);
0442
0443 printk("\n\n\n");
0444
0445 for (entry = 0; entry < 1024; entry++)
0446 printk("jtlb[%x]: entryhi - 0x%lx; entrylo0 - 0x%lx;"
0447 " entrylo1 - 0x%lx\n",
0448 entry, entryhi[entry], entrylo0[entry], entrylo1[entry]);
0449 printk("\n\n\n");
0450 }
0451
0452 static void show_tlb(void)
0453 {
0454 show_iutlb();
0455 show_dutlb();
0456 show_jtlb();
0457 }
0458 #else
0459 static void show_tlb(void)
0460 {
0461 return;
0462 }
0463 #endif
0464
0465 void show_regs(struct pt_regs *fp)
0466 {
0467 pr_info("\nCURRENT PROCESS:\n\n");
0468 pr_info("COMM=%s PID=%d\n", current->comm, current->pid);
0469
0470 if (current->mm) {
0471 pr_info("TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n",
0472 (int) current->mm->start_code,
0473 (int) current->mm->end_code,
0474 (int) current->mm->start_data,
0475 (int) current->mm->end_data,
0476 (int) current->mm->end_data,
0477 (int) current->mm->brk);
0478 pr_info("USER-STACK=%08x KERNEL-STACK=%08x\n\n",
0479 (int) current->mm->start_stack,
0480 (int) (((unsigned long) current) + 2 * PAGE_SIZE));
0481 }
0482
0483 pr_info("PC: 0x%08lx (%pS)\n", (long)fp->pc, (void *)fp->pc);
0484 pr_info("LR: 0x%08lx (%pS)\n", (long)fp->lr, (void *)fp->lr);
0485 pr_info("SP: 0x%08lx\n", (long)fp->usp);
0486 pr_info("PSR: 0x%08lx\n", (long)fp->sr);
0487 pr_info("orig_a0: 0x%08lx\n", fp->orig_a0);
0488 pr_info("PT_REGS: 0x%08lx\n", (long)fp);
0489
0490 pr_info(" a0: 0x%08lx a1: 0x%08lx a2: 0x%08lx a3: 0x%08lx\n",
0491 fp->a0, fp->a1, fp->a2, fp->a3);
0492 #if defined(__CSKYABIV2__)
0493 pr_info(" r4: 0x%08lx r5: 0x%08lx r6: 0x%08lx r7: 0x%08lx\n",
0494 fp->regs[0], fp->regs[1], fp->regs[2], fp->regs[3]);
0495 pr_info(" r8: 0x%08lx r9: 0x%08lx r10: 0x%08lx r11: 0x%08lx\n",
0496 fp->regs[4], fp->regs[5], fp->regs[6], fp->regs[7]);
0497 pr_info("r12: 0x%08lx r13: 0x%08lx r15: 0x%08lx\n",
0498 fp->regs[8], fp->regs[9], fp->lr);
0499 pr_info("r16: 0x%08lx r17: 0x%08lx r18: 0x%08lx r19: 0x%08lx\n",
0500 fp->exregs[0], fp->exregs[1], fp->exregs[2], fp->exregs[3]);
0501 pr_info("r20: 0x%08lx r21: 0x%08lx r22: 0x%08lx r23: 0x%08lx\n",
0502 fp->exregs[4], fp->exregs[5], fp->exregs[6], fp->exregs[7]);
0503 pr_info("r24: 0x%08lx r25: 0x%08lx r26: 0x%08lx r27: 0x%08lx\n",
0504 fp->exregs[8], fp->exregs[9], fp->exregs[10], fp->exregs[11]);
0505 pr_info("r28: 0x%08lx r29: 0x%08lx r30: 0x%08lx tls: 0x%08lx\n",
0506 fp->exregs[12], fp->exregs[13], fp->exregs[14], fp->tls);
0507 pr_info(" hi: 0x%08lx lo: 0x%08lx\n",
0508 fp->rhi, fp->rlo);
0509 #else
0510 pr_info(" r6: 0x%08lx r7: 0x%08lx r8: 0x%08lx r9: 0x%08lx\n",
0511 fp->regs[0], fp->regs[1], fp->regs[2], fp->regs[3]);
0512 pr_info("r10: 0x%08lx r11: 0x%08lx r12: 0x%08lx r13: 0x%08lx\n",
0513 fp->regs[4], fp->regs[5], fp->regs[6], fp->regs[7]);
0514 pr_info("r14: 0x%08lx r1: 0x%08lx\n",
0515 fp->regs[8], fp->regs[9]);
0516 #endif
0517
0518 show_tlb();
0519
0520 return;
0521 }