Merge master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog
[pandora-kernel.git] / arch / um / sys-x86_64 / ptrace.c
index 74eee5c..55b66e0 100644 (file)
@@ -8,6 +8,7 @@
 #include <asm/ptrace.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
+#include <linux/mm.h>
 #include <asm/uaccess.h>
 #include <asm/elf.h>
 
@@ -70,8 +71,6 @@ int poke_user(struct task_struct *child, long addr, long data)
 
         if (addr < MAX_REG_OFFSET)
                 return putreg(child, addr, data);
-
-#if 0 /* Need x86_64 debugregs handling */
         else if((addr >= offsetof(struct user, u_debugreg[0])) &&
                 (addr <= offsetof(struct user, u_debugreg[7]))){
                 addr -= offsetof(struct user, u_debugreg[0]);
@@ -80,7 +79,6 @@ int poke_user(struct task_struct *child, long addr, long data)
                 child->thread.arch.debugregs[addr] = data;
                 return 0;
         }
-#endif
         return -EIO;
 }
 
@@ -118,14 +116,12 @@ int peek_user(struct task_struct *child, long addr, long data)
         if(addr < MAX_REG_OFFSET){
                 tmp = getreg(child, addr);
         }
-#if 0 /* Need x86_64 debugregs handling */
         else if((addr >= offsetof(struct user, u_debugreg[0])) &&
                 (addr <= offsetof(struct user, u_debugreg[7]))){
                 addr -= offsetof(struct user, u_debugreg[0]);
                 addr = addr >> 2;
                 tmp = child->thread.arch.debugregs[addr];
         }
-#endif
         return put_user(tmp, (unsigned long *) data);
 }
 
@@ -136,9 +132,28 @@ void arch_switch(void)
 */
 }
 
+/* XXX Mostly copied from sys-i386 */
 int is_syscall(unsigned long addr)
 {
-       panic("is_syscall");
+       unsigned short instr;
+       int n;
+
+       n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
+       if(n){
+               /* access_process_vm() grants access to vsyscall and stub,
+                * while copy_from_user doesn't. Maybe access_process_vm is
+                * slow, but that doesn't matter, since it will be called only
+                * in case of singlestepping, if copy_from_user failed.
+                */
+               n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
+               if(n != sizeof(instr)) {
+                       printk("is_syscall : failed to read instruction from "
+                              "0x%lx\n", addr);
+                       return(1);
+               }
+       }
+       /* sysenter */
+       return(instr == 0x050f);
 }
 
 int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu )