15c48b108SAl Viro /* 25c48b108SAl Viro * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 35c48b108SAl Viro * Licensed under the GPL 45c48b108SAl Viro */ 55c48b108SAl Viro 65c48b108SAl Viro #include "linux/mm.h" 75c48b108SAl Viro #include "linux/sched.h" 85c48b108SAl Viro #include "asm/uaccess.h" 95c48b108SAl Viro #include "skas.h" 105c48b108SAl Viro 115c48b108SAl Viro extern int arch_switch_tls(struct task_struct *to); 125c48b108SAl Viro 135c48b108SAl Viro void arch_switch_to(struct task_struct *to) 145c48b108SAl Viro { 155c48b108SAl Viro int err = arch_switch_tls(to); 165c48b108SAl Viro if (!err) 175c48b108SAl Viro return; 185c48b108SAl Viro 195c48b108SAl Viro if (err != -EINVAL) 205c48b108SAl Viro printk(KERN_WARNING "arch_switch_tls failed, errno %d, " 215c48b108SAl Viro "not EINVAL\n", -err); 225c48b108SAl Viro else 235c48b108SAl Viro printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n"); 245c48b108SAl Viro } 255c48b108SAl Viro 265c48b108SAl Viro int is_syscall(unsigned long addr) 275c48b108SAl Viro { 285c48b108SAl Viro unsigned short instr; 295c48b108SAl Viro int n; 305c48b108SAl Viro 315c48b108SAl Viro n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); 325c48b108SAl Viro if (n) { 335c48b108SAl Viro /* access_process_vm() grants access to vsyscall and stub, 345c48b108SAl Viro * while copy_from_user doesn't. Maybe access_process_vm is 355c48b108SAl Viro * slow, but that doesn't matter, since it will be called only 365c48b108SAl Viro * in case of singlestepping, if copy_from_user failed. 375c48b108SAl Viro */ 385c48b108SAl Viro n = access_process_vm(current, addr, &instr, sizeof(instr), 0); 395c48b108SAl Viro if (n != sizeof(instr)) { 405c48b108SAl Viro printk(KERN_ERR "is_syscall : failed to read " 415c48b108SAl Viro "instruction from 0x%lx\n", addr); 425c48b108SAl Viro return 1; 435c48b108SAl Viro } 445c48b108SAl Viro } 455c48b108SAl Viro /* int 0x80 or sysenter */ 465c48b108SAl Viro return (instr == 0x80cd) || (instr == 0x340f); 475c48b108SAl Viro } 485c48b108SAl Viro 495c48b108SAl Viro /* determines which flags the user has access to. */ 505c48b108SAl Viro /* 1 = access 0 = no access */ 515c48b108SAl Viro #define FLAG_MASK 0x00044dd5 525c48b108SAl Viro 535c48b108SAl Viro static const int reg_offsets[] = { 54*3579a389SAl Viro [EBX] = HOST_BX, 55*3579a389SAl Viro [ECX] = HOST_CX, 56*3579a389SAl Viro [EDX] = HOST_DX, 57*3579a389SAl Viro [ESI] = HOST_SI, 58*3579a389SAl Viro [EDI] = HOST_DI, 59*3579a389SAl Viro [EBP] = HOST_BP, 60*3579a389SAl Viro [EAX] = HOST_AX, 615c48b108SAl Viro [DS] = HOST_DS, 625c48b108SAl Viro [ES] = HOST_ES, 635c48b108SAl Viro [FS] = HOST_FS, 645c48b108SAl Viro [GS] = HOST_GS, 655c48b108SAl Viro [EIP] = HOST_IP, 665c48b108SAl Viro [CS] = HOST_CS, 675c48b108SAl Viro [EFL] = HOST_EFLAGS, 685c48b108SAl Viro [UESP] = HOST_SP, 695c48b108SAl Viro [SS] = HOST_SS, 705c48b108SAl Viro }; 715c48b108SAl Viro 725c48b108SAl Viro int putreg(struct task_struct *child, int regno, unsigned long value) 735c48b108SAl Viro { 745c48b108SAl Viro regno >>= 2; 755c48b108SAl Viro switch (regno) { 765c48b108SAl Viro case EBX: 775c48b108SAl Viro case ECX: 785c48b108SAl Viro case EDX: 795c48b108SAl Viro case ESI: 805c48b108SAl Viro case EDI: 815c48b108SAl Viro case EBP: 825c48b108SAl Viro case EAX: 835c48b108SAl Viro case EIP: 845c48b108SAl Viro case UESP: 855c48b108SAl Viro break; 865c48b108SAl Viro case FS: 875c48b108SAl Viro if (value && (value & 3) != 3) 885c48b108SAl Viro return -EIO; 895c48b108SAl Viro break; 905c48b108SAl Viro case GS: 915c48b108SAl Viro if (value && (value & 3) != 3) 925c48b108SAl Viro return -EIO; 935c48b108SAl Viro break; 945c48b108SAl Viro case DS: 955c48b108SAl Viro case ES: 965c48b108SAl Viro if (value && (value & 3) != 3) 975c48b108SAl Viro return -EIO; 985c48b108SAl Viro value &= 0xffff; 995c48b108SAl Viro break; 1005c48b108SAl Viro case SS: 1015c48b108SAl Viro case CS: 1025c48b108SAl Viro if ((value & 3) != 3) 1035c48b108SAl Viro return -EIO; 1045c48b108SAl Viro value &= 0xffff; 1055c48b108SAl Viro break; 1065c48b108SAl Viro case EFL: 1075c48b108SAl Viro value &= FLAG_MASK; 1085c48b108SAl Viro child->thread.regs.regs.gp[HOST_EFLAGS] |= value; 1095c48b108SAl Viro return 0; 1105c48b108SAl Viro case ORIG_EAX: 1115c48b108SAl Viro child->thread.regs.regs.syscall = value; 1125c48b108SAl Viro return 0; 1135c48b108SAl Viro default : 1145c48b108SAl Viro panic("Bad register in putreg() : %d\n", regno); 1155c48b108SAl Viro } 1165c48b108SAl Viro child->thread.regs.regs.gp[reg_offsets[regno]] = value; 1175c48b108SAl Viro return 0; 1185c48b108SAl Viro } 1195c48b108SAl Viro 1205c48b108SAl Viro int poke_user(struct task_struct *child, long addr, long data) 1215c48b108SAl Viro { 1225c48b108SAl Viro if ((addr & 3) || addr < 0) 1235c48b108SAl Viro return -EIO; 1245c48b108SAl Viro 1255c48b108SAl Viro if (addr < MAX_REG_OFFSET) 1265c48b108SAl Viro return putreg(child, addr, data); 1275c48b108SAl Viro else if ((addr >= offsetof(struct user, u_debugreg[0])) && 1285c48b108SAl Viro (addr <= offsetof(struct user, u_debugreg[7]))) { 1295c48b108SAl Viro addr -= offsetof(struct user, u_debugreg[0]); 1305c48b108SAl Viro addr = addr >> 2; 1315c48b108SAl Viro if ((addr == 4) || (addr == 5)) 1325c48b108SAl Viro return -EIO; 1335c48b108SAl Viro child->thread.arch.debugregs[addr] = data; 1345c48b108SAl Viro return 0; 1355c48b108SAl Viro } 1365c48b108SAl Viro return -EIO; 1375c48b108SAl Viro } 1385c48b108SAl Viro 1395c48b108SAl Viro unsigned long getreg(struct task_struct *child, int regno) 1405c48b108SAl Viro { 1415c48b108SAl Viro unsigned long mask = ~0UL; 1425c48b108SAl Viro 1435c48b108SAl Viro regno >>= 2; 1445c48b108SAl Viro switch (regno) { 1455c48b108SAl Viro case ORIG_EAX: 1465c48b108SAl Viro return child->thread.regs.regs.syscall; 1475c48b108SAl Viro case FS: 1485c48b108SAl Viro case GS: 1495c48b108SAl Viro case DS: 1505c48b108SAl Viro case ES: 1515c48b108SAl Viro case SS: 1525c48b108SAl Viro case CS: 1535c48b108SAl Viro mask = 0xffff; 1545c48b108SAl Viro break; 1555c48b108SAl Viro case EIP: 1565c48b108SAl Viro case UESP: 1575c48b108SAl Viro case EAX: 1585c48b108SAl Viro case EBX: 1595c48b108SAl Viro case ECX: 1605c48b108SAl Viro case EDX: 1615c48b108SAl Viro case ESI: 1625c48b108SAl Viro case EDI: 1635c48b108SAl Viro case EBP: 1645c48b108SAl Viro case EFL: 1655c48b108SAl Viro break; 1665c48b108SAl Viro default: 1675c48b108SAl Viro panic("Bad register in getreg() : %d\n", regno); 1685c48b108SAl Viro } 1695c48b108SAl Viro return mask & child->thread.regs.regs.gp[reg_offsets[regno]]; 1705c48b108SAl Viro } 1715c48b108SAl Viro 1725c48b108SAl Viro /* read the word at location addr in the USER area. */ 1735c48b108SAl Viro int peek_user(struct task_struct *child, long addr, long data) 1745c48b108SAl Viro { 1755c48b108SAl Viro unsigned long tmp; 1765c48b108SAl Viro 1775c48b108SAl Viro if ((addr & 3) || addr < 0) 1785c48b108SAl Viro return -EIO; 1795c48b108SAl Viro 1805c48b108SAl Viro tmp = 0; /* Default return condition */ 1815c48b108SAl Viro if (addr < MAX_REG_OFFSET) { 1825c48b108SAl Viro tmp = getreg(child, addr); 1835c48b108SAl Viro } 1845c48b108SAl Viro else if ((addr >= offsetof(struct user, u_debugreg[0])) && 1855c48b108SAl Viro (addr <= offsetof(struct user, u_debugreg[7]))) { 1865c48b108SAl Viro addr -= offsetof(struct user, u_debugreg[0]); 1875c48b108SAl Viro addr = addr >> 2; 1885c48b108SAl Viro tmp = child->thread.arch.debugregs[addr]; 1895c48b108SAl Viro } 1905c48b108SAl Viro return put_user(tmp, (unsigned long __user *) data); 1915c48b108SAl Viro } 1925c48b108SAl Viro 1935c48b108SAl Viro static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) 1945c48b108SAl Viro { 1955c48b108SAl Viro int err, n, cpu = ((struct thread_info *) child->stack)->cpu; 1965c48b108SAl Viro struct user_i387_struct fpregs; 1975c48b108SAl Viro 1985c48b108SAl Viro err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs); 1995c48b108SAl Viro if (err) 2005c48b108SAl Viro return err; 2015c48b108SAl Viro 2025c48b108SAl Viro n = copy_to_user(buf, &fpregs, sizeof(fpregs)); 2035c48b108SAl Viro if(n > 0) 2045c48b108SAl Viro return -EFAULT; 2055c48b108SAl Viro 2065c48b108SAl Viro return n; 2075c48b108SAl Viro } 2085c48b108SAl Viro 2095c48b108SAl Viro static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) 2105c48b108SAl Viro { 2115c48b108SAl Viro int n, cpu = ((struct thread_info *) child->stack)->cpu; 2125c48b108SAl Viro struct user_i387_struct fpregs; 2135c48b108SAl Viro 2145c48b108SAl Viro n = copy_from_user(&fpregs, buf, sizeof(fpregs)); 2155c48b108SAl Viro if (n > 0) 2165c48b108SAl Viro return -EFAULT; 2175c48b108SAl Viro 2185c48b108SAl Viro return restore_fp_registers(userspace_pid[cpu], 2195c48b108SAl Viro (unsigned long *) &fpregs); 2205c48b108SAl Viro } 2215c48b108SAl Viro 2225c48b108SAl Viro static int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) 2235c48b108SAl Viro { 2245c48b108SAl Viro int err, n, cpu = ((struct thread_info *) child->stack)->cpu; 2255c48b108SAl Viro struct user_fxsr_struct fpregs; 2265c48b108SAl Viro 2275c48b108SAl Viro err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs); 2285c48b108SAl Viro if (err) 2295c48b108SAl Viro return err; 2305c48b108SAl Viro 2315c48b108SAl Viro n = copy_to_user(buf, &fpregs, sizeof(fpregs)); 2325c48b108SAl Viro if(n > 0) 2335c48b108SAl Viro return -EFAULT; 2345c48b108SAl Viro 2355c48b108SAl Viro return n; 2365c48b108SAl Viro } 2375c48b108SAl Viro 2385c48b108SAl Viro static int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) 2395c48b108SAl Viro { 2405c48b108SAl Viro int n, cpu = ((struct thread_info *) child->stack)->cpu; 2415c48b108SAl Viro struct user_fxsr_struct fpregs; 2425c48b108SAl Viro 2435c48b108SAl Viro n = copy_from_user(&fpregs, buf, sizeof(fpregs)); 2445c48b108SAl Viro if (n > 0) 2455c48b108SAl Viro return -EFAULT; 2465c48b108SAl Viro 2475c48b108SAl Viro return restore_fpx_registers(userspace_pid[cpu], 2485c48b108SAl Viro (unsigned long *) &fpregs); 2495c48b108SAl Viro } 2505c48b108SAl Viro 2515c48b108SAl Viro long subarch_ptrace(struct task_struct *child, long request, 2525c48b108SAl Viro unsigned long addr, unsigned long data) 2535c48b108SAl Viro { 2545c48b108SAl Viro int ret = -EIO; 2555c48b108SAl Viro void __user *datap = (void __user *) data; 2565c48b108SAl Viro switch (request) { 2575c48b108SAl Viro case PTRACE_GETFPREGS: /* Get the child FPU state. */ 2585c48b108SAl Viro ret = get_fpregs(datap, child); 2595c48b108SAl Viro break; 2605c48b108SAl Viro case PTRACE_SETFPREGS: /* Set the child FPU state. */ 2615c48b108SAl Viro ret = set_fpregs(datap, child); 2625c48b108SAl Viro break; 2635c48b108SAl Viro case PTRACE_GETFPXREGS: /* Get the child FPU state. */ 2645c48b108SAl Viro ret = get_fpxregs(datap, child); 2655c48b108SAl Viro break; 2665c48b108SAl Viro case PTRACE_SETFPXREGS: /* Set the child FPU state. */ 2675c48b108SAl Viro ret = set_fpxregs(datap, child); 2685c48b108SAl Viro break; 2695c48b108SAl Viro default: 2705c48b108SAl Viro ret = -EIO; 2715c48b108SAl Viro } 2725c48b108SAl Viro return ret; 2735c48b108SAl Viro } 274