aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2007-02-10 04:44:30 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-11 13:51:24 -0500
commit6e6d74cfac782a3a4cb5111bd9c25cd95d6b7c6c (patch)
treef63c0433740168f56916ece27793e9b69a40e072 /arch
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>
Diffstat (limited to 'arch')
-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
3 files changed, 15 insertions, 11 deletions
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 9a77fb3c269d..627742d89434 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -18,6 +18,7 @@
18#include "kern_util.h" 18#include "kern_util.h"
19#include "skas_ptrace.h" 19#include "skas_ptrace.h"
20#include "sysdep/ptrace.h" 20#include "sysdep/ptrace.h"
21#include "os.h"
21 22
22static inline void set_singlestepping(struct task_struct *child, int on) 23static inline void set_singlestepping(struct task_struct *child, int on)
23{ 24{
@@ -241,6 +242,12 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
241 break; 242 break;
242 } 243 }
243#endif 244#endif
245#ifdef PTRACE_ARCH_PRCTL
246 case PTRACE_ARCH_PRCTL:
247 /* XXX Calls ptrace on the host - needs some SMP thinking */
248 ret = arch_prctl_skas(child, data, (void *) addr);
249 break;
250#endif
244 default: 251 default:
245 ret = ptrace_request(child, request, addr, data); 252 ret = ptrace_request(child, request, addr, data);
246 break; 253 break;
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index 147bbf05cbc2..55b66e09a98c 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)
71 71
72 if (addr < MAX_REG_OFFSET) 72 if (addr < MAX_REG_OFFSET)
73 return putreg(child, addr, data); 73 return putreg(child, addr, data);
74
75#if 0 /* Need x86_64 debugregs handling */
76 else if((addr >= offsetof(struct user, u_debugreg[0])) && 74 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
77 (addr <= offsetof(struct user, u_debugreg[7]))){ 75 (addr <= offsetof(struct user, u_debugreg[7]))){
78 addr -= offsetof(struct user, u_debugreg[0]); 76 addr -= offsetof(struct user, u_debugreg[0]);
@@ -81,7 +79,6 @@ int poke_user(struct task_struct *child, long addr, long data)
81 child->thread.arch.debugregs[addr] = data; 79 child->thread.arch.debugregs[addr] = data;
82 return 0; 80 return 0;
83 } 81 }
84#endif
85 return -EIO; 82 return -EIO;
86} 83}
87 84
@@ -119,14 +116,12 @@ int peek_user(struct task_struct *child, long addr, long data)
119 if(addr < MAX_REG_OFFSET){ 116 if(addr < MAX_REG_OFFSET){
120 tmp = getreg(child, addr); 117 tmp = getreg(child, addr);
121 } 118 }
122#if 0 /* Need x86_64 debugregs handling */
123 else if((addr >= offsetof(struct user, u_debugreg[0])) && 119 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
124 (addr <= offsetof(struct user, u_debugreg[7]))){ 120 (addr <= offsetof(struct user, u_debugreg[7]))){
125 addr -= offsetof(struct user, u_debugreg[0]); 121 addr -= offsetof(struct user, u_debugreg[0]);
126 addr = addr >> 2; 122 addr = addr >> 2;
127 tmp = child->thread.arch.debugregs[addr]; 123 tmp = child->thread.arch.debugregs[addr];
128 } 124 }
129#endif
130 return put_user(tmp, (unsigned long *) data); 125 return put_user(tmp, (unsigned long *) data);
131} 126}
132 127
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index f309fa9bc232..01b91f9fa789 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)
59 59
60#ifdef CONFIG_MODE_SKAS 60#ifdef CONFIG_MODE_SKAS
61 61
62static long arch_prctl_skas(int code, unsigned long __user *addr) 62long arch_prctl_skas(struct task_struct *task, int code,
63 unsigned long __user *addr)
63{ 64{
64 unsigned long *ptr = addr, tmp; 65 unsigned long *ptr = addr, tmp;
65 long ret; 66 long ret;
66 int pid = current->mm->context.skas.id.u.pid; 67 int pid = task->mm->context.skas.id.u.pid;
67 68
68 /* 69 /*
69 * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to 70 * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to
70 * be safe), we need to call arch_prctl on the host because 71 * be safe), we need to call arch_prctl on the host because
71 * setting %fs may result in something else happening (like a 72 * setting %fs may result in something else happening (like a
72 * GDT being set instead). So, we let the host fiddle the 73 * GDT or thread.fs being set instead). So, we let the host
73 * registers and restore them afterwards. 74 * fiddle the registers and thread struct and restore the
75 * registers afterwards.
74 * 76 *
75 * So, the saved registers are stored to the process (this 77 * So, the saved registers are stored to the process (this
76 * needed because a stub may have been the last thing to run), 78 * 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)
118 120
119long sys_arch_prctl(int code, unsigned long addr) 121long sys_arch_prctl(int code, unsigned long addr)
120{ 122{
121 return CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, code, 123 return CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, current, code,
122 (unsigned long __user *) addr); 124 (unsigned long __user *) addr);
123} 125}
124 126
@@ -141,6 +143,6 @@ void arch_switch_to_skas(struct task_struct *from, struct task_struct *to)
141 if(to->thread.arch.fs == 0) 143 if(to->thread.arch.fs == 0)
142 return; 144 return;
143 145
144 arch_prctl_skas(ARCH_SET_FS, (void __user *) to->thread.arch.fs); 146 arch_prctl_skas(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs);
145} 147}
146 148