X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fmips%2Fkernel%2Fptrace.c;h=6ca8e9e2a0ca66e1bcb28bcb12960b1aac6df067;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=0d533ef07ef2ea411a699bdd85e1ee949ee189c7;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 0d533ef07..6ca8e9e2a 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -14,7 +14,6 @@ * At this time Linux/MIPS64 only supports syscall tracing, even for 32-bit * binaries. */ -#include #include #include #include @@ -27,6 +26,7 @@ #include #include #include +#include #include #include @@ -107,6 +107,7 @@ int ptrace_setregs (struct task_struct *child, __s64 __user *data) int ptrace_getfpregs (struct task_struct *child, __u32 __user *data) { int i; + unsigned int tmp; if (!access_ok(VERIFY_WRITE, data, 33 * 8)) return -EIO; @@ -120,12 +121,12 @@ int ptrace_getfpregs (struct task_struct *child, __u32 __user *data) __put_user ((__u64) -1, i + (__u64 __user *) data); } - if (cpu_has_fpu) { - unsigned int flags, tmp; + __put_user (child->thread.fpu.fcr31, data + 64); - __put_user (child->thread.fpu.hard.fcr31, data + 64); + preempt_disable(); + if (cpu_has_fpu) { + unsigned int flags; - preempt_disable(); if (cpu_has_mipsmt) { unsigned int vpflags = dvpe(); flags = read_c0_status(); @@ -139,12 +140,11 @@ int ptrace_getfpregs (struct task_struct *child, __u32 __user *data) __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); - __put_user ((__u32) 0, data + 65); + tmp = 0; } + preempt_enable(); + __put_user (tmp, data + 65); return 0; } @@ -162,10 +162,7 @@ int ptrace_setfpregs (struct task_struct *child, __u32 __user *data) 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); + __get_user (child->thread.fpu.fcr31, data + 64); /* FIR may not be written. */ @@ -176,6 +173,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) { int ret; + if (!vx_check(vx_task_xid(child), VS_WATCH_P|VS_IDENT)) + goto out; + switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -241,18 +241,26 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) tmp = regs->lo; break; case FPC_CSR: - if (cpu_has_fpu) - tmp = child->thread.fpu.hard.fcr31; - else - tmp = child->thread.fpu.soft.fcr31; + tmp = child->thread.fpu.fcr31; break; case FPC_EIR: { /* implementation / version register */ unsigned int flags; +#ifdef CONFIG_MIPS_MT_SMTC + unsigned int irqflags; + unsigned int mtflags; +#endif /* CONFIG_MIPS_MT_SMTC */ - if (!cpu_has_fpu) + preempt_disable(); + if (!cpu_has_fpu) { + preempt_enable(); break; + } - preempt_disable(); +#ifdef CONFIG_MIPS_MT_SMTC + /* Read-modify-write of Status must be atomic */ + local_irq_save(irqflags); + mtflags = dmt(); +#endif /* CONFIG_MIPS_MT_SMTC */ if (cpu_has_mipsmt) { unsigned int vpflags = dvpe(); flags = read_c0_status(); @@ -266,6 +274,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); write_c0_status(flags); } +#ifdef CONFIG_MIPS_MT_SMTC + emt(mtflags); + local_irq_restore(irqflags); +#endif /* CONFIG_MIPS_MT_SMTC */ preempt_enable(); break; } @@ -322,9 +334,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) if (!tsk_used_math(child)) { /* FP not yet used */ - memset(&child->thread.fpu.hard, ~0, - sizeof(child->thread.fpu.hard)); - child->thread.fpu.hard.fcr31 = 0; + memset(&child->thread.fpu, ~0, + sizeof(child->thread.fpu)); + child->thread.fpu.fcr31 = 0; } #ifdef CONFIG_32BIT /* @@ -355,10 +367,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) regs->lo = data; break; case FPC_CSR: - if (cpu_has_fpu) - child->thread.fpu.hard.fcr31 = data; - else - child->thread.fpu.soft.fcr31 = data; + child->thread.fpu.fcr31 = data; break; case DSP_BASE ... DSP_BASE + 5: { dspreg_t *dregs; @@ -469,33 +478,14 @@ 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]), + audit_syscall_exit(AUDITSC_RESULT(regs->regs[2]), regs->regs[2]); - if (!(current->ptrace & PT_PTRACED)) - goto out; - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - goto out; - if (!vx_check(vx_task_xid(child), VX_WATCH|VX_IDENT)) - goto out_tsk; + if (test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall(regs, entryexit); - /* The 0x80 provides a way for the tracing parent to distinguish - between a syscall stop and SIGTRAP delivery */ - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? - 0x80 : 0)); - - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } - out: if (unlikely(current->audit_context) && !entryexit) - audit_syscall_entry(current, audit_arch(), regs->regs[2], + audit_syscall_entry(audit_arch(), regs->regs[2], regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); }