1*5c48b108SAl Viro /* 2*5c48b108SAl Viro * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 3*5c48b108SAl Viro * Licensed under the GPL 4*5c48b108SAl Viro */ 5*5c48b108SAl Viro 6*5c48b108SAl Viro #include "linux/mm.h" 7*5c48b108SAl Viro #include "linux/sched.h" 8*5c48b108SAl Viro #include "asm/uaccess.h" 9*5c48b108SAl Viro #include "skas.h" 10*5c48b108SAl Viro 11*5c48b108SAl Viro extern int arch_switch_tls(struct task_struct *to); 12*5c48b108SAl Viro 13*5c48b108SAl Viro void arch_switch_to(struct task_struct *to) 14*5c48b108SAl Viro { 15*5c48b108SAl Viro int err = arch_switch_tls(to); 16*5c48b108SAl Viro if (!err) 17*5c48b108SAl Viro return; 18*5c48b108SAl Viro 19*5c48b108SAl Viro if (err != -EINVAL) 20*5c48b108SAl Viro printk(KERN_WARNING "arch_switch_tls failed, errno %d, " 21*5c48b108SAl Viro "not EINVAL\n", -err); 22*5c48b108SAl Viro else 23*5c48b108SAl Viro printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n"); 24*5c48b108SAl Viro } 25*5c48b108SAl Viro 26*5c48b108SAl Viro int is_syscall(unsigned long addr) 27*5c48b108SAl Viro { 28*5c48b108SAl Viro unsigned short instr; 29*5c48b108SAl Viro int n; 30*5c48b108SAl Viro 31*5c48b108SAl Viro n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); 32*5c48b108SAl Viro if (n) { 33*5c48b108SAl Viro /* access_process_vm() grants access to vsyscall and stub, 34*5c48b108SAl Viro * while copy_from_user doesn't. Maybe access_process_vm is 35*5c48b108SAl Viro * slow, but that doesn't matter, since it will be called only 36*5c48b108SAl Viro * in case of singlestepping, if copy_from_user failed. 37*5c48b108SAl Viro */ 38*5c48b108SAl Viro n = access_process_vm(current, addr, &instr, sizeof(instr), 0); 39*5c48b108SAl Viro if (n != sizeof(instr)) { 40*5c48b108SAl Viro printk(KERN_ERR "is_syscall : failed to read " 41*5c48b108SAl Viro "instruction from 0x%lx\n", addr); 42*5c48b108SAl Viro return 1; 43*5c48b108SAl Viro } 44*5c48b108SAl Viro } 45*5c48b108SAl Viro /* int 0x80 or sysenter */ 46*5c48b108SAl Viro return (instr == 0x80cd) || (instr == 0x340f); 47*5c48b108SAl Viro } 48*5c48b108SAl Viro 49*5c48b108SAl Viro /* determines which flags the user has access to. */ 50*5c48b108SAl Viro /* 1 = access 0 = no access */ 51*5c48b108SAl Viro #define FLAG_MASK 0x00044dd5 52*5c48b108SAl Viro 53*5c48b108SAl Viro static const int reg_offsets[] = { 54*5c48b108SAl Viro [EBX] = HOST_EBX, 55*5c48b108SAl Viro [ECX] = HOST_ECX, 56*5c48b108SAl Viro [EDX] = HOST_EDX, 57*5c48b108SAl Viro [ESI] = HOST_ESI, 58*5c48b108SAl Viro [EDI] = HOST_EDI, 59*5c48b108SAl Viro [EBP] = HOST_EBP, 60*5c48b108SAl Viro [EAX] = HOST_EAX, 61*5c48b108SAl Viro [DS] = HOST_DS, 62*5c48b108SAl Viro [ES] = HOST_ES, 63*5c48b108SAl Viro [FS] = HOST_FS, 64*5c48b108SAl Viro [GS] = HOST_GS, 65*5c48b108SAl Viro [EIP] = HOST_IP, 66*5c48b108SAl Viro [CS] = HOST_CS, 67*5c48b108SAl Viro [EFL] = HOST_EFLAGS, 68*5c48b108SAl Viro [UESP] = HOST_SP, 69*5c48b108SAl Viro [SS] = HOST_SS, 70*5c48b108SAl Viro }; 71*5c48b108SAl Viro 72*5c48b108SAl Viro int putreg(struct task_struct *child, int regno, unsigned long value) 73*5c48b108SAl Viro { 74*5c48b108SAl Viro regno >>= 2; 75*5c48b108SAl Viro switch (regno) { 76*5c48b108SAl Viro case EBX: 77*5c48b108SAl Viro case ECX: 78*5c48b108SAl Viro case EDX: 79*5c48b108SAl Viro case ESI: 80*5c48b108SAl Viro case EDI: 81*5c48b108SAl Viro case EBP: 82*5c48b108SAl Viro case EAX: 83*5c48b108SAl Viro case EIP: 84*5c48b108SAl Viro case UESP: 85*5c48b108SAl Viro break; 86*5c48b108SAl Viro case FS: 87*5c48b108SAl Viro if (value && (value & 3) != 3) 88*5c48b108SAl Viro return -EIO; 89*5c48b108SAl Viro break; 90*5c48b108SAl Viro case GS: 91*5c48b108SAl Viro if (value && (value & 3) != 3) 92*5c48b108SAl Viro return -EIO; 93*5c48b108SAl Viro break; 94*5c48b108SAl Viro case DS: 95*5c48b108SAl Viro case ES: 96*5c48b108SAl Viro if (value && (value & 3) != 3) 97*5c48b108SAl Viro return -EIO; 98*5c48b108SAl Viro value &= 0xffff; 99*5c48b108SAl Viro break; 100*5c48b108SAl Viro case SS: 101*5c48b108SAl Viro case CS: 102*5c48b108SAl Viro if ((value & 3) != 3) 103*5c48b108SAl Viro return -EIO; 104*5c48b108SAl Viro value &= 0xffff; 105*5c48b108SAl Viro break; 106*5c48b108SAl Viro case EFL: 107*5c48b108SAl Viro value &= FLAG_MASK; 108*5c48b108SAl Viro child->thread.regs.regs.gp[HOST_EFLAGS] |= value; 109*5c48b108SAl Viro return 0; 110*5c48b108SAl Viro case ORIG_EAX: 111*5c48b108SAl Viro child->thread.regs.regs.syscall = value; 112*5c48b108SAl Viro return 0; 113*5c48b108SAl Viro default : 114*5c48b108SAl Viro panic("Bad register in putreg() : %d\n", regno); 115*5c48b108SAl Viro } 116*5c48b108SAl Viro child->thread.regs.regs.gp[reg_offsets[regno]] = value; 117*5c48b108SAl Viro return 0; 118*5c48b108SAl Viro } 119*5c48b108SAl Viro 120*5c48b108SAl Viro int poke_user(struct task_struct *child, long addr, long data) 121*5c48b108SAl Viro { 122*5c48b108SAl Viro if ((addr & 3) || addr < 0) 123*5c48b108SAl Viro return -EIO; 124*5c48b108SAl Viro 125*5c48b108SAl Viro if (addr < MAX_REG_OFFSET) 126*5c48b108SAl Viro return putreg(child, addr, data); 127*5c48b108SAl Viro else if ((addr >= offsetof(struct user, u_debugreg[0])) && 128*5c48b108SAl Viro (addr <= offsetof(struct user, u_debugreg[7]))) { 129*5c48b108SAl Viro addr -= offsetof(struct user, u_debugreg[0]); 130*5c48b108SAl Viro addr = addr >> 2; 131*5c48b108SAl Viro if ((addr == 4) || (addr == 5)) 132*5c48b108SAl Viro return -EIO; 133*5c48b108SAl Viro child->thread.arch.debugregs[addr] = data; 134*5c48b108SAl Viro return 0; 135*5c48b108SAl Viro } 136*5c48b108SAl Viro return -EIO; 137*5c48b108SAl Viro } 138*5c48b108SAl Viro 139*5c48b108SAl Viro unsigned long getreg(struct task_struct *child, int regno) 140*5c48b108SAl Viro { 141*5c48b108SAl Viro unsigned long mask = ~0UL; 142*5c48b108SAl Viro 143*5c48b108SAl Viro regno >>= 2; 144*5c48b108SAl Viro switch (regno) { 145*5c48b108SAl Viro case ORIG_EAX: 146*5c48b108SAl Viro return child->thread.regs.regs.syscall; 147*5c48b108SAl Viro case FS: 148*5c48b108SAl Viro case GS: 149*5c48b108SAl Viro case DS: 150*5c48b108SAl Viro case ES: 151*5c48b108SAl Viro case SS: 152*5c48b108SAl Viro case CS: 153*5c48b108SAl Viro mask = 0xffff; 154*5c48b108SAl Viro break; 155*5c48b108SAl Viro case EIP: 156*5c48b108SAl Viro case UESP: 157*5c48b108SAl Viro case EAX: 158*5c48b108SAl Viro case EBX: 159*5c48b108SAl Viro case ECX: 160*5c48b108SAl Viro case EDX: 161*5c48b108SAl Viro case ESI: 162*5c48b108SAl Viro case EDI: 163*5c48b108SAl Viro case EBP: 164*5c48b108SAl Viro case EFL: 165*5c48b108SAl Viro break; 166*5c48b108SAl Viro default: 167*5c48b108SAl Viro panic("Bad register in getreg() : %d\n", regno); 168*5c48b108SAl Viro } 169*5c48b108SAl Viro return mask & child->thread.regs.regs.gp[reg_offsets[regno]]; 170*5c48b108SAl Viro } 171*5c48b108SAl Viro 172*5c48b108SAl Viro /* read the word at location addr in the USER area. */ 173*5c48b108SAl Viro int peek_user(struct task_struct *child, long addr, long data) 174*5c48b108SAl Viro { 175*5c48b108SAl Viro unsigned long tmp; 176*5c48b108SAl Viro 177*5c48b108SAl Viro if ((addr & 3) || addr < 0) 178*5c48b108SAl Viro return -EIO; 179*5c48b108SAl Viro 180*5c48b108SAl Viro tmp = 0; /* Default return condition */ 181*5c48b108SAl Viro if (addr < MAX_REG_OFFSET) { 182*5c48b108SAl Viro tmp = getreg(child, addr); 183*5c48b108SAl Viro } 184*5c48b108SAl Viro else if ((addr >= offsetof(struct user, u_debugreg[0])) && 185*5c48b108SAl Viro (addr <= offsetof(struct user, u_debugreg[7]))) { 186*5c48b108SAl Viro addr -= offsetof(struct user, u_debugreg[0]); 187*5c48b108SAl Viro addr = addr >> 2; 188*5c48b108SAl Viro tmp = child->thread.arch.debugregs[addr]; 189*5c48b108SAl Viro } 190*5c48b108SAl Viro return put_user(tmp, (unsigned long __user *) data); 191*5c48b108SAl Viro } 192*5c48b108SAl Viro 193*5c48b108SAl Viro static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) 194*5c48b108SAl Viro { 195*5c48b108SAl Viro int err, n, cpu = ((struct thread_info *) child->stack)->cpu; 196*5c48b108SAl Viro struct user_i387_struct fpregs; 197*5c48b108SAl Viro 198*5c48b108SAl Viro err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs); 199*5c48b108SAl Viro if (err) 200*5c48b108SAl Viro return err; 201*5c48b108SAl Viro 202*5c48b108SAl Viro n = copy_to_user(buf, &fpregs, sizeof(fpregs)); 203*5c48b108SAl Viro if(n > 0) 204*5c48b108SAl Viro return -EFAULT; 205*5c48b108SAl Viro 206*5c48b108SAl Viro return n; 207*5c48b108SAl Viro } 208*5c48b108SAl Viro 209*5c48b108SAl Viro static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) 210*5c48b108SAl Viro { 211*5c48b108SAl Viro int n, cpu = ((struct thread_info *) child->stack)->cpu; 212*5c48b108SAl Viro struct user_i387_struct fpregs; 213*5c48b108SAl Viro 214*5c48b108SAl Viro n = copy_from_user(&fpregs, buf, sizeof(fpregs)); 215*5c48b108SAl Viro if (n > 0) 216*5c48b108SAl Viro return -EFAULT; 217*5c48b108SAl Viro 218*5c48b108SAl Viro return restore_fp_registers(userspace_pid[cpu], 219*5c48b108SAl Viro (unsigned long *) &fpregs); 220*5c48b108SAl Viro } 221*5c48b108SAl Viro 222*5c48b108SAl Viro static int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) 223*5c48b108SAl Viro { 224*5c48b108SAl Viro int err, n, cpu = ((struct thread_info *) child->stack)->cpu; 225*5c48b108SAl Viro struct user_fxsr_struct fpregs; 226*5c48b108SAl Viro 227*5c48b108SAl Viro err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs); 228*5c48b108SAl Viro if (err) 229*5c48b108SAl Viro return err; 230*5c48b108SAl Viro 231*5c48b108SAl Viro n = copy_to_user(buf, &fpregs, sizeof(fpregs)); 232*5c48b108SAl Viro if(n > 0) 233*5c48b108SAl Viro return -EFAULT; 234*5c48b108SAl Viro 235*5c48b108SAl Viro return n; 236*5c48b108SAl Viro } 237*5c48b108SAl Viro 238*5c48b108SAl Viro static int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) 239*5c48b108SAl Viro { 240*5c48b108SAl Viro int n, cpu = ((struct thread_info *) child->stack)->cpu; 241*5c48b108SAl Viro struct user_fxsr_struct fpregs; 242*5c48b108SAl Viro 243*5c48b108SAl Viro n = copy_from_user(&fpregs, buf, sizeof(fpregs)); 244*5c48b108SAl Viro if (n > 0) 245*5c48b108SAl Viro return -EFAULT; 246*5c48b108SAl Viro 247*5c48b108SAl Viro return restore_fpx_registers(userspace_pid[cpu], 248*5c48b108SAl Viro (unsigned long *) &fpregs); 249*5c48b108SAl Viro } 250*5c48b108SAl Viro 251*5c48b108SAl Viro long subarch_ptrace(struct task_struct *child, long request, 252*5c48b108SAl Viro unsigned long addr, unsigned long data) 253*5c48b108SAl Viro { 254*5c48b108SAl Viro int ret = -EIO; 255*5c48b108SAl Viro void __user *datap = (void __user *) data; 256*5c48b108SAl Viro switch (request) { 257*5c48b108SAl Viro case PTRACE_GETFPREGS: /* Get the child FPU state. */ 258*5c48b108SAl Viro ret = get_fpregs(datap, child); 259*5c48b108SAl Viro break; 260*5c48b108SAl Viro case PTRACE_SETFPREGS: /* Set the child FPU state. */ 261*5c48b108SAl Viro ret = set_fpregs(datap, child); 262*5c48b108SAl Viro break; 263*5c48b108SAl Viro case PTRACE_GETFPXREGS: /* Get the child FPU state. */ 264*5c48b108SAl Viro ret = get_fpxregs(datap, child); 265*5c48b108SAl Viro break; 266*5c48b108SAl Viro case PTRACE_SETFPXREGS: /* Set the child FPU state. */ 267*5c48b108SAl Viro ret = set_fpxregs(datap, child); 268*5c48b108SAl Viro break; 269*5c48b108SAl Viro default: 270*5c48b108SAl Viro ret = -EIO; 271*5c48b108SAl Viro } 272*5c48b108SAl Viro return ret; 273*5c48b108SAl Viro } 274