0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/compiler.h>
0018 #include <linux/compat.h>
0019 #include <linux/kernel.h>
0020 #include <linux/sched.h>
0021 #include <linux/sched/task_stack.h>
0022 #include <linux/mm.h>
0023 #include <linux/errno.h>
0024 #include <linux/ptrace.h>
0025 #include <linux/smp.h>
0026 #include <linux/security.h>
0027
0028 #include <asm/cpu.h>
0029 #include <asm/dsp.h>
0030 #include <asm/fpu.h>
0031 #include <asm/mipsregs.h>
0032 #include <asm/mipsmtregs.h>
0033 #include <asm/page.h>
0034 #include <asm/reg.h>
0035 #include <asm/syscall.h>
0036 #include <linux/uaccess.h>
0037 #include <asm/bootinfo.h>
0038
0039
0040
0041
0042
0043 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
0044 compat_ulong_t caddr, compat_ulong_t cdata)
0045 {
0046 int addr = caddr;
0047 int data = cdata;
0048 int ret;
0049
0050 switch (request) {
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 case PTRACE_PEEKTEXT_3264:
0062 case PTRACE_PEEKDATA_3264: {
0063 u32 tmp;
0064 int copied;
0065 u32 __user * addrOthers;
0066
0067 ret = -EIO;
0068
0069
0070 if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
0071 break;
0072
0073 copied = ptrace_access_vm(child, (u64)addrOthers, &tmp,
0074 sizeof(tmp), FOLL_FORCE);
0075 if (copied != sizeof(tmp))
0076 break;
0077 ret = put_user(tmp, (u32 __user *) (unsigned long) data);
0078 break;
0079 }
0080
0081
0082 case PTRACE_PEEKUSR: {
0083 struct pt_regs *regs;
0084 unsigned int tmp;
0085
0086 regs = task_pt_regs(child);
0087 ret = 0;
0088
0089 switch (addr) {
0090 case 0 ... 31:
0091 tmp = regs->regs[addr];
0092 break;
0093 #ifdef CONFIG_MIPS_FP_SUPPORT
0094 case FPR_BASE ... FPR_BASE + 31: {
0095 union fpureg *fregs;
0096
0097 if (!tsk_used_math(child)) {
0098
0099 tmp = -1;
0100 break;
0101 }
0102 fregs = get_fpu_regs(child);
0103 if (test_tsk_thread_flag(child, TIF_32BIT_FPREGS)) {
0104
0105
0106
0107
0108
0109 tmp = get_fpr32(&fregs[(addr & ~1) - FPR_BASE],
0110 addr & 1);
0111 break;
0112 }
0113 tmp = get_fpr64(&fregs[addr - FPR_BASE], 0);
0114 break;
0115 }
0116 case FPC_CSR:
0117 tmp = child->thread.fpu.fcr31;
0118 break;
0119 case FPC_EIR:
0120
0121 tmp = boot_cpu_data.fpu_id;
0122 break;
0123 #endif
0124 case PC:
0125 tmp = regs->cp0_epc;
0126 break;
0127 case CAUSE:
0128 tmp = regs->cp0_cause;
0129 break;
0130 case BADVADDR:
0131 tmp = regs->cp0_badvaddr;
0132 break;
0133 case MMHI:
0134 tmp = regs->hi;
0135 break;
0136 case MMLO:
0137 tmp = regs->lo;
0138 break;
0139 case DSP_BASE ... DSP_BASE + 5: {
0140 dspreg_t *dregs;
0141
0142 if (!cpu_has_dsp) {
0143 tmp = 0;
0144 ret = -EIO;
0145 goto out;
0146 }
0147 dregs = __get_dsp_regs(child);
0148 tmp = dregs[addr - DSP_BASE];
0149 break;
0150 }
0151 case DSP_CONTROL:
0152 if (!cpu_has_dsp) {
0153 tmp = 0;
0154 ret = -EIO;
0155 goto out;
0156 }
0157 tmp = child->thread.dsp.dspcontrol;
0158 break;
0159 default:
0160 tmp = 0;
0161 ret = -EIO;
0162 goto out;
0163 }
0164 ret = put_user(tmp, (unsigned __user *) (unsigned long) data);
0165 break;
0166 }
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177 case PTRACE_POKETEXT_3264:
0178 case PTRACE_POKEDATA_3264: {
0179 u32 __user * addrOthers;
0180
0181
0182 ret = -EIO;
0183 if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
0184 break;
0185 ret = 0;
0186 if (ptrace_access_vm(child, (u64)addrOthers, &data,
0187 sizeof(data),
0188 FOLL_FORCE | FOLL_WRITE) == sizeof(data))
0189 break;
0190 ret = -EIO;
0191 break;
0192 }
0193
0194 case PTRACE_POKEUSR: {
0195 struct pt_regs *regs;
0196 ret = 0;
0197 regs = task_pt_regs(child);
0198
0199 switch (addr) {
0200 case 0 ... 31:
0201 regs->regs[addr] = data;
0202
0203 if (addr == 2)
0204 mips_syscall_update_nr(child, regs);
0205 else if (addr == 4 &&
0206 mips_syscall_is_indirect(child, regs))
0207 mips_syscall_update_nr(child, regs);
0208 break;
0209 #ifdef CONFIG_MIPS_FP_SUPPORT
0210 case FPR_BASE ... FPR_BASE + 31: {
0211 union fpureg *fregs = get_fpu_regs(child);
0212
0213 if (!tsk_used_math(child)) {
0214
0215 memset(&child->thread.fpu, ~0,
0216 sizeof(child->thread.fpu));
0217 child->thread.fpu.fcr31 = 0;
0218 }
0219 if (test_tsk_thread_flag(child, TIF_32BIT_FPREGS)) {
0220
0221
0222
0223
0224
0225 set_fpr32(&fregs[(addr & ~1) - FPR_BASE],
0226 addr & 1, data);
0227 break;
0228 }
0229 set_fpr64(&fregs[addr - FPR_BASE], 0, data);
0230 break;
0231 }
0232 case FPC_CSR:
0233 child->thread.fpu.fcr31 = data;
0234 break;
0235 #endif
0236 case PC:
0237 regs->cp0_epc = data;
0238 break;
0239 case MMHI:
0240 regs->hi = data;
0241 break;
0242 case MMLO:
0243 regs->lo = data;
0244 break;
0245 case DSP_BASE ... DSP_BASE + 5: {
0246 dspreg_t *dregs;
0247
0248 if (!cpu_has_dsp) {
0249 ret = -EIO;
0250 break;
0251 }
0252
0253 dregs = __get_dsp_regs(child);
0254 dregs[addr - DSP_BASE] = data;
0255 break;
0256 }
0257 case DSP_CONTROL:
0258 if (!cpu_has_dsp) {
0259 ret = -EIO;
0260 break;
0261 }
0262 child->thread.dsp.dspcontrol = data;
0263 break;
0264 default:
0265
0266 ret = -EIO;
0267 break;
0268 }
0269 break;
0270 }
0271
0272 case PTRACE_GETREGS:
0273 ret = ptrace_getregs(child,
0274 (struct user_pt_regs __user *) (__u64) data);
0275 break;
0276
0277 case PTRACE_SETREGS:
0278 ret = ptrace_setregs(child,
0279 (struct user_pt_regs __user *) (__u64) data);
0280 break;
0281
0282 #ifdef CONFIG_MIPS_FP_SUPPORT
0283 case PTRACE_GETFPREGS:
0284 ret = ptrace_getfpregs(child, (__u32 __user *) (__u64) data);
0285 break;
0286
0287 case PTRACE_SETFPREGS:
0288 ret = ptrace_setfpregs(child, (__u32 __user *) (__u64) data);
0289 break;
0290 #endif
0291 case PTRACE_GET_THREAD_AREA:
0292 ret = put_user(task_thread_info(child)->tp_value,
0293 (unsigned int __user *) (unsigned long) data);
0294 break;
0295
0296 case PTRACE_GET_THREAD_AREA_3264:
0297 ret = put_user(task_thread_info(child)->tp_value,
0298 (unsigned long __user *) (unsigned long) data);
0299 break;
0300
0301 case PTRACE_GET_WATCH_REGS:
0302 ret = ptrace_get_watch_regs(child,
0303 (struct pt_watch_regs __user *) (unsigned long) addr);
0304 break;
0305
0306 case PTRACE_SET_WATCH_REGS:
0307 ret = ptrace_set_watch_regs(child,
0308 (struct pt_watch_regs __user *) (unsigned long) addr);
0309 break;
0310
0311 default:
0312 ret = compat_ptrace_request(child, request, addr, data);
0313 break;
0314 }
0315 out:
0316 return ret;
0317 }