summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2007-02-10 01:44:30 -0800
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-11 10:51:24 -0800
commit6e6d74cfac782a3a4cb5111bd9c25cd95d6b7c6c (patch)
treef63c0433740168f56916ece27793e9b69a40e072
parentf355559cf78455ed6be103b020e4b800230c64eb (diff)
[PATCH] uml: x86_64 ptrace fixes
This patch fixes some missing ptrace bits on x86_64. PTRACE_ARCH_PRCTL is hooked up and implemented. This required generalizing arch_prctl_skas slightly to take a task_struct to modify. Previously, it always operated on current. Reading and writing the debug registers is also enabled by un-ifdefing the code that implements that. It turns out that x86_64 is identical to i386, so the same code can be used. Signed-off-by: Jeff Dike <jdike@addtoit.com> Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/um/kernel/ptrace.c7
-rw-r--r--arch/um/sys-x86_64/ptrace.c5
-rw-r--r--arch/um/sys-x86_64/syscalls.c14
-rw-r--r--include/asm-um/ptrace-x86_64.h3
4 files changed, 18 insertions, 11 deletions
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 9a77fb3c269..627742d8943 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -18,6 +18,7 @@
#include "kern_util.h"
#include "skas_ptrace.h"
#include "sysdep/ptrace.h"
+#include "os.h"
static inline void set_singlestepping(struct task_struct *child, int on)
{
@@ -241,6 +242,12 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
}
#endif
+#ifdef PTRACE_ARCH_PRCTL
+ case PTRACE_ARCH_PRCTL:
+ /* XXX Calls ptrace on the host - needs some SMP thinking */
+ ret = arch_prctl_skas(child, data, (void *) addr);
+ break;
+#endif
default:
ret = ptrace_request(child, request, addr, data);
break;
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index 147bbf05cbc..55b66e09a98 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -71,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]);
@@ -81,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;
}
@@ -119,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);
}
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index f309fa9bc23..01b91f9fa78 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -59,18 +59,20 @@ static long arch_prctl_tt(int code, unsigned long addr)
#ifdef CONFIG_MODE_SKAS
-static long arch_prctl_skas(int code, unsigned long __user *addr)
+long arch_prctl_skas(struct task_struct *task, int code,
+ unsigned long __user *addr)
{
unsigned long *ptr = addr, tmp;
long ret;
- int pid = current->mm->context.skas.id.u.pid;
+ int pid = task->mm->context.skas.id.u.pid;
/*
* With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to
* be safe), we need to call arch_prctl on the host because
* setting %fs may result in something else happening (like a
- * GDT being set instead). So, we let the host fiddle the
- * registers and restore them afterwards.
+ * GDT or thread.fs being set instead). So, we let the host
+ * fiddle the registers and thread struct and restore the
+ * registers afterwards.
*
* So, the saved registers are stored to the process (this
* needed because a stub may have been the last thing to run),
@@ -118,7 +120,7 @@ static long arch_prctl_skas(int code, unsigned long __user *addr)
long sys_arch_prctl(int code, unsigned long addr)
{
- return CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, code,
+ return CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, current, code,
(unsigned long __user *) addr);
}
@@ -141,6 +143,6 @@ void arch_switch_to_skas(struct task_struct *from, struct task_struct *to)
if(to->thread.arch.fs == 0)
return;
- arch_prctl_skas(ARCH_SET_FS, (void __user *) to->thread.arch.fs);
+ arch_prctl_skas(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs);
}
diff --git a/include/asm-um/ptrace-x86_64.h b/include/asm-um/ptrace-x86_64.h
index a927450ce40..bf61d17de3f 100644
--- a/include/asm-um/ptrace-x86_64.h
+++ b/include/asm-um/ptrace-x86_64.h
@@ -84,4 +84,7 @@ static inline void arch_switch_to_tt(struct task_struct *from,
extern void arch_switch_to_skas(struct task_struct *from,
struct task_struct *to);
+extern long arch_prctl_skas(struct task_struct *task, int code,
+ unsigned long __user *addr);
+
#endif