From fe00f943e0ef98b4057abcc2940d631a975b43cd Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 1 Mar 2005 19:22:29 +0000 Subject: Sparseify MIPS. Signed-off-by: Ralf Baechle --- arch/mips/kernel/ptrace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/mips/kernel/ptrace.c') diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 0b571a5b4b83..2c7fc7472fb2 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -103,7 +103,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; if (copied != sizeof(tmp)) break; - ret = put_user(tmp,(unsigned long *) data); + ret = put_user(tmp,(unsigned long __user *) data); break; } @@ -180,7 +180,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; goto out_tsk; } - ret = put_user(tmp, (unsigned long *) data); + ret = put_user(tmp, (unsigned long __user *) data); break; } -- cgit v1.2.2 From 3c37026d43c47bec4710cbda286f4a17f416f5e6 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 13 Apr 2005 17:43:59 +0000 Subject: NPTL, round one. Signed-off-by: Ralf Baechle --- arch/mips/kernel/ptrace.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/mips/kernel/ptrace.c') diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 2c7fc7472fb2..649c90dee38e 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -289,6 +289,11 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_detach(child, data); break; + case PTRACE_GET_THREAD_AREA: + ret = put_user(child->thread_info->tp_value, + (unsigned long __user *) data); + break; + default: ret = ptrace_request(child, request, addr, data); break; -- cgit v1.2.2 From f8280c8d3d51667015c2363eeaa76b4e28e002a5 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 19 May 2005 12:08:04 +0000 Subject: Fix tasteless #ifdef mess in audit_arch(), minor cleanups. Signed-off-by: Ralf Baechle --- arch/mips/kernel/ptrace.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'arch/mips/kernel/ptrace.c') diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 649c90dee38e..49821ee18984 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -308,21 +309,14 @@ out: static inline int audit_arch(void) { -#ifdef CONFIG_CPU_LITTLE_ENDIAN + int arch = EM_MIPS; #ifdef CONFIG_64BIT - if (!(current->thread.mflags & MF_32BIT_REGS)) - return AUDIT_ARCH_MIPSEL64; -#endif /* MIPS64 */ - return AUDIT_ARCH_MIPSEL; - -#else /* big endian... */ -#ifdef CONFIG_64BIT - if (!(current->thread.mflags & MF_32BIT_REGS)) - return AUDIT_ARCH_MIPS64; -#endif /* MIPS64 */ - return AUDIT_ARCH_MIPS; - -#endif /* endian */ + arch |= __AUDIT_ARCH_64BIT; +#endif +#if defined(__LITTLE_ENDIAN) + arch |= __AUDIT_ARCH_LE; +#endif + return arch; } /* @@ -332,12 +326,13 @@ static inline int audit_arch(void) asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit) { if (unlikely(current->audit_context) && entryexit) - audit_syscall_exit(current, AUDITSC_RESULT(regs->regs[2]), regs->regs[2]); + audit_syscall_exit(current, AUDITSC_RESULT(regs->regs[2]), + regs->regs[2]); - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - goto out; if (!(current->ptrace & PT_PTRACED)) goto out; + if (!test_thread_flag(TIF_SYSCALL_TRACE)) + goto out; /* The 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ -- cgit v1.2.2 From e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2f Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 31 May 2005 11:49:19 +0000 Subject: Support the MIPS32 / MIPS64 DSP ASE. Signed-off-by: Ralf Baechle --- arch/mips/kernel/ptrace.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'arch/mips/kernel/ptrace.c') diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 49821ee18984..2441e32ce820 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -176,6 +177,27 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) write_c0_status(flags); break; } + case DSP_BASE ... DSP_BASE + 5: + if (!cpu_has_dsp) { + tmp = 0; + ret = -EIO; + goto out_tsk; + } + if (child->thread.dsp.used_dsp) { + dspreg_t *dregs = __get_dsp_regs(child); + tmp = (unsigned long) (dregs[addr - DSP_BASE]); + } else { + tmp = -1; /* DSP registers yet used */ + } + break; + case DSP_CONTROL: + if (!cpu_has_dsp) { + tmp = 0; + ret = -EIO; + goto out_tsk; + } + tmp = child->thread.dsp.dspcontrol; + break; default: tmp = 0; ret = -EIO; @@ -248,6 +270,22 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) else child->thread.fpu.soft.fcr31 = data; break; + case DSP_BASE ... DSP_BASE + 5: + if (!cpu_has_dsp) { + ret = -EIO; + break; + } + + dspreg_t *dregs = __get_dsp_regs(child); + dregs[addr - DSP_BASE] = data; + break; + case DSP_CONTROL: + if (!cpu_has_dsp) { + ret = -EIO; + break; + } + child->thread.dsp.dspcontrol = data; + break; default: /* The rest are not allowed. */ ret = -EIO; -- cgit v1.2.2 From c134a5ecdb8f4aee09feca0d4d395915e752fcb8 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 30 Jun 2005 09:42:00 +0000 Subject: Avoid defining variables in the middle of a block which breaks older compilers. Signed-off-by: Ralf Baechle --- arch/mips/kernel/ptrace.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'arch/mips/kernel/ptrace.c') diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 2441e32ce820..74283369a1e3 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -177,19 +177,22 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) write_c0_status(flags); break; } - case DSP_BASE ... DSP_BASE + 5: + case DSP_BASE ... DSP_BASE + 5: { + dspreg_t *dregs; + if (!cpu_has_dsp) { tmp = 0; ret = -EIO; goto out_tsk; } if (child->thread.dsp.used_dsp) { - dspreg_t *dregs = __get_dsp_regs(child); + dregs = __get_dsp_regs(child); tmp = (unsigned long) (dregs[addr - DSP_BASE]); } else { tmp = -1; /* DSP registers yet used */ } break; + } case DSP_CONTROL: if (!cpu_has_dsp) { tmp = 0; @@ -270,15 +273,18 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) else child->thread.fpu.soft.fcr31 = data; break; - case DSP_BASE ... DSP_BASE + 5: + case DSP_BASE ... DSP_BASE + 5: { + dspreg_t *dregs; + if (!cpu_has_dsp) { ret = -EIO; break; } - dspreg_t *dregs = __get_dsp_regs(child); + dregs = __get_dsp_regs(child); dregs[addr - DSP_BASE] = data; break; + } case DSP_CONTROL: if (!cpu_has_dsp) { ret = -EIO; -- cgit v1.2.2 From ea3d710fe572f0af4d242701973f7363b2146429 Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Wed, 28 Sep 2005 18:11:15 -0400 Subject: Revise MIPS 64-bit ptrace interface Change the N32 debugging ABI to something more sane, and add support for o32 and n32 debuggers to trace n64 programs. Signed-off-by: Daniel Jacobowitz Signed-off-by: Ralf Baechle --- arch/mips/kernel/ptrace.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) (limited to 'arch/mips/kernel/ptrace.c') diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 74283369a1e3..122433f835e3 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -38,6 +38,7 @@ #include #include #include +#include /* * Called by kernel/ptrace.c when detaching.. @@ -49,6 +50,118 @@ void ptrace_disable(struct task_struct *child) /* Nothing to do.. */ } +/* + * Read a general register set. We always use the 64-bit format, even + * for 32-bit kernels and for 32-bit processes on a 64-bit kernel. + * Registers are sign extended to fill the available space. + */ +int ptrace_getregs (struct task_struct *child, __s64 __user *data) +{ + struct pt_regs *regs; + int i; + + if (!access_ok(VERIFY_WRITE, data, 38 * 8)) + return -EIO; + + regs = (struct pt_regs *) ((unsigned long) child->thread_info + + THREAD_SIZE - 32 - sizeof(struct pt_regs)); + + for (i = 0; i < 32; i++) + __put_user (regs->regs[i], data + i); + __put_user (regs->lo, data + EF_LO - EF_R0); + __put_user (regs->hi, data + EF_HI - EF_R0); + __put_user (regs->cp0_epc, data + EF_CP0_EPC - EF_R0); + __put_user (regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0); + __put_user (regs->cp0_status, data + EF_CP0_STATUS - EF_R0); + __put_user (regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0); + + return 0; +} + +/* + * Write a general register set. As for PTRACE_GETREGS, we always use + * the 64-bit format. On a 32-bit kernel only the lower order half + * (according to endianness) will be used. + */ +int ptrace_setregs (struct task_struct *child, __s64 __user *data) +{ + struct pt_regs *regs; + int i; + + if (!access_ok(VERIFY_READ, data, 38 * 8)) + return -EIO; + + regs = (struct pt_regs *) ((unsigned long) child->thread_info + + THREAD_SIZE - 32 - sizeof(struct pt_regs)); + + for (i = 0; i < 32; i++) + __get_user (regs->regs[i], data + i); + __get_user (regs->lo, data + EF_LO - EF_R0); + __get_user (regs->hi, data + EF_HI - EF_R0); + __get_user (regs->cp0_epc, data + EF_CP0_EPC - EF_R0); + + /* badvaddr, status, and cause may not be written. */ + + return 0; +} + +int ptrace_getfpregs (struct task_struct *child, __u32 __user *data) +{ + int i; + + if (!access_ok(VERIFY_WRITE, data, 33 * 8)) + return -EIO; + + if (tsk_used_math(child)) { + fpureg_t *fregs = get_fpu_regs(child); + for (i = 0; i < 32; i++) + __put_user (fregs[i], i + (__u64 __user *) data); + } else { + for (i = 0; i < 32; i++) + __put_user ((__u64) -1, i + (__u64 __user *) data); + } + + if (cpu_has_fpu) { + unsigned int flags, tmp; + + __put_user (child->thread.fpu.hard.fcr31, data + 64); + + flags = read_c0_status(); + __enable_fpu(); + __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp)); + write_c0_status(flags); + __put_user (tmp, data + 65); + } else { + __put_user (child->thread.fpu.soft.fcr31, data + 64); + __put_user ((__u32) 0, data + 65); + } + + return 0; +} + +int ptrace_setfpregs (struct task_struct *child, __u32 __user *data) +{ + fpureg_t *fregs; + int i; + + if (!access_ok(VERIFY_READ, data, 33 * 8)) + return -EIO; + + fregs = get_fpu_regs(child); + + for (i = 0; i < 32; i++) + __get_user (fregs[i], i + (__u64 __user *) data); + + if (cpu_has_fpu) + __get_user (child->thread.fpu.hard.fcr31, data + 64); + else + __get_user (child->thread.fpu.soft.fcr31, data + 64); + + /* FIR may not be written. */ + + return 0; +} + asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; @@ -300,6 +413,22 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) break; } + case PTRACE_GETREGS: + ret = ptrace_getregs (child, (__u64 __user *) data); + break; + + case PTRACE_SETREGS: + ret = ptrace_setregs (child, (__u64 __user *) data); + break; + + case PTRACE_GETFPREGS: + ret = ptrace_getfpregs (child, (__u32 __user *) data); + break; + + case PTRACE_SETFPREGS: + ret = ptrace_setfpregs (child, (__u32 __user *) data); + break; + case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ ret = -EIO; -- cgit v1.2.2 From 101b3531a693ad890f33f2f04323592cd376616a Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 6 Oct 2005 17:39:32 +0100 Subject: Protect manipulation of c0_status against preemption and multithreading. Signed-off-by: Ralf Baechle --- arch/mips/kernel/ptrace.c | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) (limited to 'arch/mips/kernel/ptrace.c') diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 122433f835e3..fcceab8f2e00 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -126,10 +127,21 @@ int ptrace_getfpregs (struct task_struct *child, __u32 __user *data) __put_user (child->thread.fpu.hard.fcr31, data + 64); - flags = read_c0_status(); - __enable_fpu(); - __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp)); - write_c0_status(flags); + preempt_disable(); + if (cpu_has_mipsmt) { + unsigned int vpflags = dvpe(); + flags = read_c0_status(); + __enable_fpu(); + __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp)); + write_c0_status(flags); + evpe(vpflags); + } else { + flags = read_c0_status(); + __enable_fpu(); + __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp)); + write_c0_status(flags); + } + preempt_enable(); __put_user (tmp, data + 65); } else { __put_user (child->thread.fpu.soft.fcr31, data + 64); @@ -284,10 +296,21 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) if (!cpu_has_fpu) break; - flags = read_c0_status(); - __enable_fpu(); - __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); - write_c0_status(flags); + preempt_disable(); + if (cpu_has_mipsmt) { + unsigned int vpflags = dvpe(); + flags = read_c0_status(); + __enable_fpu(); + __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); + write_c0_status(flags); + evpe(vpflags); + } else { + flags = read_c0_status(); + __enable_fpu(); + __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); + write_c0_status(flags); + } + preempt_enable(); break; } case DSP_BASE ... DSP_BASE + 5: { -- cgit v1.2.2