···289289 ret = ptrace_detach(child, data);290290 break;291291292292+ case PTRACE_GET_THREAD_AREA:293293+ ret = put_user(child->thread_info->tp_value,294294+ (unsigned long __user *) data);295295+ break;296296+292297 default:293298 ret = ptrace_request(child, request, addr, data);294299 break;
+5
arch/mips/kernel/ptrace32.c
···268268 wake_up_process(child);269269 break;270270271271+ case PTRACE_GET_THREAD_AREA:272272+ ret = put_user(child->thread_info->tp_value,273273+ (unsigned int __user *) (unsigned long) data);274274+ break;275275+271276 case PTRACE_DETACH: /* detach a process that was attached. */272277 ret = ptrace_detach(child, data);273278 break;
···77 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.88 * Copyright (C) 2001 MIPS Technologies, Inc.99 */1010+#include <linux/config.h>1011#include <linux/a.out.h>1112#include <linux/errno.h>1213#include <linux/linkage.h>···177176{178177 unsigned long clone_flags;179178 unsigned long newsp;180180- int *parent_tidptr, *child_tidptr;179179+ int __user *parent_tidptr, *child_tidptr;181180182181 clone_flags = regs.regs[4];183182 newsp = regs.regs[5];184183 if (!newsp)185184 newsp = regs.regs[29];186186- parent_tidptr = (int *) regs.regs[6];187187- child_tidptr = (int *) regs.regs[7];185185+ parent_tidptr = (int __user *) regs.regs[6];186186+#ifdef CONFIG_32BIT187187+ /* We need to fetch the fifth argument off the stack. */188188+ child_tidptr = NULL;189189+ if (clone_flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) {190190+ int __user *__user *usp = (int __user *__user *) regs.regs[29];191191+ if (regs.regs[2] == __NR_syscall) {192192+ if (get_user (child_tidptr, &usp[5]))193193+ return -EFAULT;194194+ }195195+ else if (get_user (child_tidptr, &usp[4]))196196+ return -EFAULT;197197+ }198198+#else199199+ child_tidptr = (int __user *) regs.regs[8];200200+#endif188201 return do_fork(clone_flags, newsp, ®s, 0,189202 parent_tidptr, child_tidptr);190203}···258243 error = error ? -EFAULT : 0;259244260245 return error;246246+}247247+248248+void sys_set_thread_area(unsigned long addr)249249+{250250+ struct thread_info *ti = current->thread_info;251251+252252+ ti->tp_value = addr;253253+254254+ /* If some future MIPS implementation has this register in hardware,255255+ * we will need to update it here (and in context switches). */261256}262257263258asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
+43-3
arch/mips/kernel/traps.c
···360360#define OFFSET 0x0000ffff361361#define LL 0xc0000000362362#define SC 0xe0000000363363+#define SPEC3 0x7c000000364364+#define RD 0x0000f800365365+#define FUNC 0x0000003f366366+#define RDHWR 0x0000003b363367364368/*365369 * The ll_bit is cleared by r*_switch.S···497493 }498494499495 return -EFAULT; /* Strange things going on ... */496496+}497497+498498+/*499499+ * Simulate trapping 'rdhwr' instructions to provide user accessible500500+ * registers not implemented in hardware. The only current use of this501501+ * is the thread area pointer.502502+ */503503+static inline int simulate_rdhwr(struct pt_regs *regs)504504+{505505+ struct thread_info *ti = current->thread_info;506506+ unsigned int opcode;507507+508508+ if (unlikely(get_insn_opcode(regs, &opcode)))509509+ return -EFAULT;510510+511511+ if (unlikely(compute_return_epc(regs)))512512+ return -EFAULT;513513+514514+ if ((opcode & OPCODE) == SPEC3 && (opcode & FUNC) == RDHWR) {515515+ int rd = (opcode & RD) >> 11;516516+ int rt = (opcode & RT) >> 16;517517+ switch (rd) {518518+ case 29:519519+ regs->regs[rt] = ti->tp_value;520520+ break;521521+ default:522522+ return -EFAULT;523523+ }524524+ }525525+526526+ return 0;500527}501528502529asmlinkage void do_ov(struct pt_regs *regs)···676641 if (!simulate_llsc(regs))677642 return;678643644644+ if (!simulate_rdhwr(regs))645645+ return;646646+679647 force_sig(SIGILL, current);680648}681649···692654693655 switch (cpid) {694656 case 0:695695- if (cpu_has_llsc)696696- break;657657+ if (!cpu_has_llsc)658658+ if (!simulate_llsc(regs))659659+ return;697660698698- if (!simulate_llsc(regs))661661+ if (!simulate_rdhwr(regs))699662 return;663663+700664 break;701665702666 case 1: