1/* 2 * Copyright 2003 PathScale, Inc. 3 * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 4 * 5 * Licensed under the GPL 6 */ 7 8#include <linux/mm.h> 9#include <linux/sched.h> 10#include <linux/errno.h> 11#define __FRAME_OFFSETS 12#include <asm/ptrace.h> 13#include <asm/uaccess.h> 14 15/* 16 * determines which flags the user has access to. 17 * 1 = access 0 = no access 18 */ 19#define FLAG_MASK 0x44dd5UL 20 21static const int reg_offsets[] = 22{ 23 [R8 >> 3] = HOST_R8, 24 [R9 >> 3] = HOST_R9, 25 [R10 >> 3] = HOST_R10, 26 [R11 >> 3] = HOST_R11, 27 [R12 >> 3] = HOST_R12, 28 [R13 >> 3] = HOST_R13, 29 [R14 >> 3] = HOST_R14, 30 [R15 >> 3] = HOST_R15, 31 [RIP >> 3] = HOST_IP, 32 [RSP >> 3] = HOST_SP, 33 [RAX >> 3] = HOST_AX, 34 [RBX >> 3] = HOST_BX, 35 [RCX >> 3] = HOST_CX, 36 [RDX >> 3] = HOST_DX, 37 [RSI >> 3] = HOST_SI, 38 [RDI >> 3] = HOST_DI, 39 [RBP >> 3] = HOST_BP, 40 [CS >> 3] = HOST_CS, 41 [SS >> 3] = HOST_SS, 42 [FS_BASE >> 3] = HOST_FS_BASE, 43 [GS_BASE >> 3] = HOST_GS_BASE, 44 [DS >> 3] = HOST_DS, 45 [ES >> 3] = HOST_ES, 46 [FS >> 3] = HOST_FS, 47 [GS >> 3] = HOST_GS, 48 [EFLAGS >> 3] = HOST_EFLAGS, 49 [ORIG_RAX >> 3] = HOST_ORIG_AX, 50}; 51 52int putreg(struct task_struct *child, int regno, unsigned long value) 53{ 54#ifdef TIF_IA32 55 /* 56 * Some code in the 64bit emulation may not be 64bit clean. 57 * Don't take any chances. 58 */ 59 if (test_tsk_thread_flag(child, TIF_IA32)) 60 value &= 0xffffffff; 61#endif 62 switch (regno) { 63 case R8: 64 case R9: 65 case R10: 66 case R11: 67 case R12: 68 case R13: 69 case R14: 70 case R15: 71 case RIP: 72 case RSP: 73 case RAX: 74 case RBX: 75 case RCX: 76 case RDX: 77 case RSI: 78 case RDI: 79 case RBP: 80 case ORIG_RAX: 81 break; 82 83 case FS: 84 case GS: 85 case DS: 86 case ES: 87 case SS: 88 case CS: 89 if (value && (value & 3) != 3) 90 return -EIO; 91 value &= 0xffff; 92 break; 93 94 case FS_BASE: 95 case GS_BASE: 96 if (!((value >> 48) == 0 || (value >> 48) == 0xffff)) 97 return -EIO; 98 break; 99 100 case EFLAGS: 101 value &= FLAG_MASK; 102 child->thread.regs.regs.gp[HOST_EFLAGS] |= value; 103 return 0; 104 105 default: 106 panic("Bad register in putreg(): %d\n", regno); 107 } 108 109 child->thread.regs.regs.gp[reg_offsets[regno >> 3]] = value; 110 return 0; 111} 112 113int poke_user(struct task_struct *child, long addr, long data) 114{ 115 if ((addr & 3) || addr < 0) 116 return -EIO; 117 118 if (addr < MAX_REG_OFFSET) 119 return putreg(child, addr, data); 120 else if ((addr >= offsetof(struct user, u_debugreg[0])) && 121 (addr <= offsetof(struct user, u_debugreg[7]))) { 122 addr -= offsetof(struct user, u_debugreg[0]); 123 addr = addr >> 2; 124 if ((addr == 4) || (addr == 5)) 125 return -EIO; 126 child->thread.arch.debugregs[addr] = data; 127 return 0; 128 } 129 return -EIO; 130} 131 132unsigned long getreg(struct task_struct *child, int regno) 133{ 134 unsigned long mask = ~0UL; 135#ifdef TIF_IA32 136 if (test_tsk_thread_flag(child, TIF_IA32)) 137 mask = 0xffffffff; 138#endif 139 switch (regno) { 140 case R8: 141 case R9: 142 case R10: 143 case R11: 144 case R12: 145 case R13: 146 case R14: 147 case R15: 148 case RIP: 149 case RSP: 150 case RAX: 151 case RBX: 152 case RCX: 153 case RDX: 154 case RSI: 155 case RDI: 156 case RBP: 157 case ORIG_RAX: 158 case EFLAGS: 159 case FS_BASE: 160 case GS_BASE: 161 break; 162 case FS: 163 case GS: 164 case DS: 165 case ES: 166 case SS: 167 case CS: 168 mask = 0xffff; 169 break; 170 default: 171 panic("Bad register in getreg: %d\n", regno); 172 } 173 return mask & child->thread.regs.regs.gp[reg_offsets[regno >> 3]]; 174} 175 176int peek_user(struct task_struct *child, long addr, long data) 177{ 178 /* read the word at location addr in the USER area. */ 179 unsigned long tmp; 180 181 if ((addr & 3) || addr < 0) 182 return -EIO; 183 184 tmp = 0; /* Default return condition */ 185 if (addr < MAX_REG_OFFSET) 186 tmp = getreg(child, addr); 187 else if ((addr >= offsetof(struct user, u_debugreg[0])) && 188 (addr <= offsetof(struct user, u_debugreg[7]))) { 189 addr -= offsetof(struct user, u_debugreg[0]); 190 addr = addr >> 2; 191 tmp = child->thread.arch.debugregs[addr]; 192 } 193 return put_user(tmp, (unsigned long *) data); 194} 195 196/* XXX Mostly copied from sys-i386 */ 197int is_syscall(unsigned long addr) 198{ 199 unsigned short instr; 200 int n; 201 202 n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); 203 if (n) { 204 /* 205 * access_process_vm() grants access to vsyscall and stub, 206 * while copy_from_user doesn't. Maybe access_process_vm is 207 * slow, but that doesn't matter, since it will be called only 208 * in case of singlestepping, if copy_from_user failed. 209 */ 210 n = access_process_vm(current, addr, &instr, sizeof(instr), 0); 211 if (n != sizeof(instr)) { 212 printk("is_syscall : failed to read instruction from " 213 "0x%lx\n", addr); 214 return 1; 215 } 216 } 217 /* sysenter */ 218 return instr == 0x050f; 219} 220 221static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) 222{ 223 int err, n, cpu = ((struct thread_info *) child->stack)->cpu; 224 long fpregs[HOST_FP_SIZE]; 225 226 BUG_ON(sizeof(*buf) != sizeof(fpregs)); 227 err = save_fp_registers(userspace_pid[cpu], fpregs); 228 if (err) 229 return err; 230 231 n = copy_to_user(buf, fpregs, sizeof(fpregs)); 232 if (n > 0) 233 return -EFAULT; 234 235 return n; 236} 237 238static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) 239{ 240 int n, cpu = ((struct thread_info *) child->stack)->cpu; 241 long fpregs[HOST_FP_SIZE]; 242 243 BUG_ON(sizeof(*buf) != sizeof(fpregs)); 244 n = copy_from_user(fpregs, buf, sizeof(fpregs)); 245 if (n > 0) 246 return -EFAULT; 247 248 return restore_fp_registers(userspace_pid[cpu], fpregs); 249} 250 251long subarch_ptrace(struct task_struct *child, long request, 252 unsigned long addr, unsigned long data) 253{ 254 int ret = -EIO; 255 void __user *datap = (void __user *) data; 256 257 switch (request) { 258 case PTRACE_GETFPREGS: /* Get the child FPU state. */ 259 ret = get_fpregs(datap, child); 260 break; 261 case PTRACE_SETFPREGS: /* Set the child FPU state. */ 262 ret = set_fpregs(datap, child); 263 break; 264 case PTRACE_ARCH_PRCTL: 265 /* XXX Calls ptrace on the host - needs some SMP thinking */ 266 ret = arch_prctl(child, data, (void __user *) addr); 267 break; 268 } 269 270 return ret; 271} 272