linux/arch/mips/kernel/ptrace32.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 1992 Ross Biro
   7 * Copyright (C) Linus Torvalds
   8 * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
   9 * Copyright (C) 1996 David S. Miller
  10 * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
  11 * Copyright (C) 1999 MIPS Technologies, Inc.
  12 * Copyright (C) 2000 Ulf Carlsson
  13 *
  14 * At this time Linux/MIPS64 only supports syscall tracing, even for 32-bit
  15 * binaries.
  16 */
  17#include <linux/compiler.h>
  18#include <linux/compat.h>
  19#include <linux/kernel.h>
  20#include <linux/sched.h>
  21#include <linux/mm.h>
  22#include <linux/errno.h>
  23#include <linux/ptrace.h>
  24#include <linux/smp.h>
  25#include <linux/smp_lock.h>
  26#include <linux/user.h>
  27#include <linux/security.h>
  28
  29#include <asm/cpu.h>
  30#include <asm/dsp.h>
  31#include <asm/fpu.h>
  32#include <asm/mipsregs.h>
  33#include <asm/mipsmtregs.h>
  34#include <asm/pgtable.h>
  35#include <asm/page.h>
  36#include <asm/system.h>
  37#include <asm/uaccess.h>
  38#include <asm/bootinfo.h>
  39
  40/*
  41 * Tracing a 32-bit process with a 64-bit strace and vice versa will not
  42 * work.  I don't know how to fix this.
  43 */
  44long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
  45                        compat_ulong_t caddr, compat_ulong_t cdata)
  46{
  47        int addr = caddr;
  48        int data = cdata;
  49        int ret;
  50
  51        switch (request) {
  52
  53        /*
  54         * Read 4 bytes of the other process' storage
  55         *  data is a pointer specifying where the user wants the
  56         *      4 bytes copied into
  57         *  addr is a pointer in the user's storage that contains an 8 byte
  58         *      address in the other process of the 4 bytes that is to be read
  59         * (this is run in a 32-bit process looking at a 64-bit process)
  60         * when I and D space are separate, these will need to be fixed.
  61         */
  62        case PTRACE_PEEKTEXT_3264:
  63        case PTRACE_PEEKDATA_3264: {
  64                u32 tmp;
  65                int copied;
  66                u32 __user * addrOthers;
  67
  68                ret = -EIO;
  69
  70                /* Get the addr in the other process that we want to read */
  71                if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
  72                        break;
  73
  74                copied = access_process_vm(child, (u64)addrOthers, &tmp,
  75                                sizeof(tmp), 0);
  76                if (copied != sizeof(tmp))
  77                        break;
  78                ret = put_user(tmp, (u32 __user *) (unsigned long) data);
  79                break;
  80        }
  81
  82        /* Read the word at location addr in the USER area. */
  83        case PTRACE_PEEKUSR: {
  84                struct pt_regs *regs;
  85                unsigned int tmp;
  86
  87                regs = task_pt_regs(child);
  88                ret = 0;  /* Default return value. */
  89
  90                switch (addr) {
  91                case 0 ... 31:
  92                        tmp = regs->regs[addr];
  93                        break;
  94                case FPR_BASE ... FPR_BASE + 31:
  95                        if (tsk_used_math(child)) {
  96                                fpureg_t *fregs = get_fpu_regs(child);
  97
  98                                /*
  99                                 * The odd registers are actually the high
 100                                 * order bits of the values stored in the even
 101                                 * registers - unless we're using r2k_switch.S.
 102                                 */
 103                                if (addr & 1)
 104                                        tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32);
 105                                else
 106                                        tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff);
 107                        } else {
 108                                tmp = -1;       /* FP not yet used  */
 109                        }
 110                        break;
 111                case PC:
 112                        tmp = regs->cp0_epc;
 113                        break;
 114                case CAUSE:
 115                        tmp = regs->cp0_cause;
 116                        break;
 117                case BADVADDR:
 118                        tmp = regs->cp0_badvaddr;
 119                        break;
 120                case MMHI:
 121                        tmp = regs->hi;
 122                        break;
 123                case MMLO:
 124                        tmp = regs->lo;
 125                        break;
 126                case FPC_CSR:
 127                        tmp = child->thread.fpu.fcr31;
 128                        break;
 129                case FPC_EIR: { /* implementation / version register */
 130                        unsigned int flags;
 131#ifdef CONFIG_MIPS_MT_SMTC
 132                        unsigned int irqflags;
 133                        unsigned int mtflags;
 134#endif /* CONFIG_MIPS_MT_SMTC */
 135
 136                        preempt_disable();
 137                        if (!cpu_has_fpu) {
 138                                preempt_enable();
 139                                tmp = 0;
 140                                break;
 141                        }
 142
 143#ifdef CONFIG_MIPS_MT_SMTC
 144                        /* Read-modify-write of Status must be atomic */
 145                        local_irq_save(irqflags);
 146                        mtflags = dmt();
 147#endif /* CONFIG_MIPS_MT_SMTC */
 148
 149                        if (cpu_has_mipsmt) {
 150                                unsigned int vpflags = dvpe();
 151                                flags = read_c0_status();
 152                                __enable_fpu();
 153                                __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
 154                                write_c0_status(flags);
 155                                evpe(vpflags);
 156                        } else {
 157                                flags = read_c0_status();
 158                                __enable_fpu();
 159                                __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
 160                                write_c0_status(flags);
 161                        }
 162#ifdef CONFIG_MIPS_MT_SMTC
 163                        emt(mtflags);
 164                        local_irq_restore(irqflags);
 165#endif /* CONFIG_MIPS_MT_SMTC */
 166                        preempt_enable();
 167                        break;
 168                }
 169                case DSP_BASE ... DSP_BASE + 5: {
 170                        dspreg_t *dregs;
 171
 172                        if (!cpu_has_dsp) {
 173                                tmp = 0;
 174                                ret = -EIO;
 175                                goto out;
 176                        }
 177                        dregs = __get_dsp_regs(child);
 178                        tmp = (unsigned long) (dregs[addr - DSP_BASE]);
 179                        break;
 180                }
 181                case DSP_CONTROL:
 182                        if (!cpu_has_dsp) {
 183                                tmp = 0;
 184                                ret = -EIO;
 185                                goto out;
 186                        }
 187                        tmp = child->thread.dsp.dspcontrol;
 188                        break;
 189                default:
 190                        tmp = 0;
 191                        ret = -EIO;
 192                        goto out;
 193                }
 194                ret = put_user(tmp, (unsigned __user *) (unsigned long) data);
 195                break;
 196        }
 197
 198        /*
 199         * Write 4 bytes into the other process' storage
 200         *  data is the 4 bytes that the user wants written
 201         *  addr is a pointer in the user's storage that contains an
 202         *      8 byte address in the other process where the 4 bytes
 203         *      that is to be written
 204         * (this is run in a 32-bit process looking at a 64-bit process)
 205         * when I and D space are separate, these will need to be fixed.
 206         */
 207        case PTRACE_POKETEXT_3264:
 208        case PTRACE_POKEDATA_3264: {
 209                u32 __user * addrOthers;
 210
 211                /* Get the addr in the other process that we want to write into */
 212                ret = -EIO;
 213                if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
 214                        break;
 215                ret = 0;
 216                if (access_process_vm(child, (u64)addrOthers, &data,
 217                                        sizeof(data), 1) == sizeof(data))
 218                        break;
 219                ret = -EIO;
 220                break;
 221        }
 222
 223        case PTRACE_POKEUSR: {
 224                struct pt_regs *regs;
 225                ret = 0;
 226                regs = task_pt_regs(child);
 227
 228                switch (addr) {
 229                case 0 ... 31:
 230                        regs->regs[addr] = data;
 231                        break;
 232                case FPR_BASE ... FPR_BASE + 31: {
 233                        fpureg_t *fregs = get_fpu_regs(child);
 234
 235                        if (!tsk_used_math(child)) {
 236                                /* FP not yet used  */
 237                                memset(&child->thread.fpu, ~0,
 238                                       sizeof(child->thread.fpu));
 239                                child->thread.fpu.fcr31 = 0;
 240                        }
 241                        /*
 242                         * The odd registers are actually the high order bits
 243                         * of the values stored in the even registers - unless
 244                         * we're using r2k_switch.S.
 245                         */
 246                        if (addr & 1) {
 247                                fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff;
 248                                fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long long) data) << 32;
 249                        } else {
 250                                fregs[addr - FPR_BASE] &= ~0xffffffffLL;
 251                                /* Must cast, lest sign extension fill upper
 252                                   bits!  */
 253                                fregs[addr - FPR_BASE] |= (unsigned int)data;
 254                        }
 255                        break;
 256                }
 257                case PC:
 258                        regs->cp0_epc = data;
 259                        break;
 260                case MMHI:
 261                        regs->hi = data;
 262                        break;
 263                case MMLO:
 264                        regs->lo = data;
 265                        break;
 266                case FPC_CSR:
 267                        child->thread.fpu.fcr31 = data;
 268                        break;
 269                case DSP_BASE ... DSP_BASE + 5: {
 270                        dspreg_t *dregs;
 271
 272                        if (!cpu_has_dsp) {
 273                                ret = -EIO;
 274                                break;
 275                        }
 276
 277                        dregs = __get_dsp_regs(child);
 278                        dregs[addr - DSP_BASE] = data;
 279                        break;
 280                }
 281                case DSP_CONTROL:
 282                        if (!cpu_has_dsp) {
 283                                ret = -EIO;
 284                                break;
 285                        }
 286                        child->thread.dsp.dspcontrol = data;
 287                        break;
 288                default:
 289                        /* The rest are not allowed. */
 290                        ret = -EIO;
 291                        break;
 292                }
 293                break;
 294                }
 295
 296        case PTRACE_GETREGS:
 297                ret = ptrace_getregs(child, (__s64 __user *) (__u64) data);
 298                break;
 299
 300        case PTRACE_SETREGS:
 301                ret = ptrace_setregs(child, (__s64 __user *) (__u64) data);
 302                break;
 303
 304        case PTRACE_GETFPREGS:
 305                ret = ptrace_getfpregs(child, (__u32 __user *) (__u64) data);
 306                break;
 307
 308        case PTRACE_SETFPREGS:
 309                ret = ptrace_setfpregs(child, (__u32 __user *) (__u64) data);
 310                break;
 311
 312        case PTRACE_GET_THREAD_AREA:
 313                ret = put_user(task_thread_info(child)->tp_value,
 314                                (unsigned int __user *) (unsigned long) data);
 315                break;
 316
 317        case PTRACE_GET_THREAD_AREA_3264:
 318                ret = put_user(task_thread_info(child)->tp_value,
 319                                (unsigned long __user *) (unsigned long) data);
 320                break;
 321
 322        case PTRACE_GET_WATCH_REGS:
 323                ret = ptrace_get_watch_regs(child,
 324                        (struct pt_watch_regs __user *) (unsigned long) addr);
 325                break;
 326
 327        case PTRACE_SET_WATCH_REGS:
 328                ret = ptrace_set_watch_regs(child,
 329                        (struct pt_watch_regs __user *) (unsigned long) addr);
 330                break;
 331
 332        default:
 333                ret = compat_ptrace_request(child, request, addr, data);
 334                break;
 335        }
 336out:
 337        return ret;
 338}
 339