aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2008-01-30 07:30:58 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:30:58 -0500
commitce90f340855d7a9b3bec24f0fe49a76904242387 (patch)
treedeba4e16ad9f65e7cc80e84f3c2fc0694a4c9f73 /arch
parent9e714bed644cb463489b9250774a4b0fb352cabc (diff)
x86: x86-64 ptrace get/putreg current task
This generalizes the getreg and putreg functions so they can be used on the current task, as well as on a task stopped in TASK_TRACED and switched off. This lays the groundwork to share this code for all kinds of user-mode machine state access, not just ptrace. Signed-off-by: Roland McGrath <roland@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/ptrace_64.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/arch/x86/kernel/ptrace_64.c b/arch/x86/kernel/ptrace_64.c
index 2427548f2a01..5979dbe8e0a2 100644
--- a/arch/x86/kernel/ptrace_64.c
+++ b/arch/x86/kernel/ptrace_64.c
@@ -67,21 +67,29 @@ static int putreg(struct task_struct *child,
67 if (value && (value & 3) != 3) 67 if (value && (value & 3) != 3)
68 return -EIO; 68 return -EIO;
69 child->thread.fsindex = value & 0xffff; 69 child->thread.fsindex = value & 0xffff;
70 if (child == current)
71 loadsegment(fs, child->thread.fsindex);
70 return 0; 72 return 0;
71 case offsetof(struct user_regs_struct,gs): 73 case offsetof(struct user_regs_struct,gs):
72 if (value && (value & 3) != 3) 74 if (value && (value & 3) != 3)
73 return -EIO; 75 return -EIO;
74 child->thread.gsindex = value & 0xffff; 76 child->thread.gsindex = value & 0xffff;
77 if (child == current)
78 load_gs_index(child->thread.gsindex);
75 return 0; 79 return 0;
76 case offsetof(struct user_regs_struct,ds): 80 case offsetof(struct user_regs_struct,ds):
77 if (value && (value & 3) != 3) 81 if (value && (value & 3) != 3)
78 return -EIO; 82 return -EIO;
79 child->thread.ds = value & 0xffff; 83 child->thread.ds = value & 0xffff;
84 if (child == current)
85 loadsegment(ds, child->thread.ds);
80 return 0; 86 return 0;
81 case offsetof(struct user_regs_struct,es): 87 case offsetof(struct user_regs_struct,es):
82 if (value && (value & 3) != 3) 88 if (value && (value & 3) != 3)
83 return -EIO; 89 return -EIO;
84 child->thread.es = value & 0xffff; 90 child->thread.es = value & 0xffff;
91 if (child == current)
92 loadsegment(es, child->thread.es);
85 return 0; 93 return 0;
86 case offsetof(struct user_regs_struct,ss): 94 case offsetof(struct user_regs_struct,ss):
87 if ((value & 3) != 3) 95 if ((value & 3) != 3)
@@ -135,14 +143,32 @@ static unsigned long getreg(struct task_struct *child, unsigned long regno)
135{ 143{
136 struct pt_regs *regs = task_pt_regs(child); 144 struct pt_regs *regs = task_pt_regs(child);
137 unsigned long val; 145 unsigned long val;
146 unsigned int seg;
138 switch (regno) { 147 switch (regno) {
139 case offsetof(struct user_regs_struct, fs): 148 case offsetof(struct user_regs_struct, fs):
149 if (child == current) {
150 /* Older gas can't assemble movq %?s,%r?? */
151 asm("movl %%fs,%0" : "=r" (seg));
152 return seg;
153 }
140 return child->thread.fsindex; 154 return child->thread.fsindex;
141 case offsetof(struct user_regs_struct, gs): 155 case offsetof(struct user_regs_struct, gs):
156 if (child == current) {
157 asm("movl %%gs,%0" : "=r" (seg));
158 return seg;
159 }
142 return child->thread.gsindex; 160 return child->thread.gsindex;
143 case offsetof(struct user_regs_struct, ds): 161 case offsetof(struct user_regs_struct, ds):
162 if (child == current) {
163 asm("movl %%ds,%0" : "=r" (seg));
164 return seg;
165 }
144 return child->thread.ds; 166 return child->thread.ds;
145 case offsetof(struct user_regs_struct, es): 167 case offsetof(struct user_regs_struct, es):
168 if (child == current) {
169 asm("movl %%es,%0" : "=r" (seg));
170 return seg;
171 }
146 return child->thread.es; 172 return child->thread.es;
147 case offsetof(struct user_regs_struct, fs_base): 173 case offsetof(struct user_regs_struct, fs_base):
148 /* 174 /*
@@ -152,7 +178,10 @@ static unsigned long getreg(struct task_struct *child, unsigned long regno)
152 */ 178 */
153 if (child->thread.fs != 0) 179 if (child->thread.fs != 0)
154 return child->thread.fs; 180 return child->thread.fs;
155 if (child->thread.fsindex != FS_TLS_SEL) 181 seg = child->thread.fsindex;
182 if (child == current)
183 asm("movl %%fs,%0" : "=r" (seg));
184 if (seg != FS_TLS_SEL)
156 return 0; 185 return 0;
157 return get_desc_base(&child->thread.tls_array[FS_TLS]); 186 return get_desc_base(&child->thread.tls_array[FS_TLS]);
158 case offsetof(struct user_regs_struct, gs_base): 187 case offsetof(struct user_regs_struct, gs_base):
@@ -161,7 +190,10 @@ static unsigned long getreg(struct task_struct *child, unsigned long regno)
161 */ 190 */
162 if (child->thread.gs != 0) 191 if (child->thread.gs != 0)
163 return child->thread.gs; 192 return child->thread.gs;
164 if (child->thread.gsindex != GS_TLS_SEL) 193 seg = child->thread.gsindex;
194 if (child == current)
195 asm("movl %%gs,%0" : "=r" (seg));
196 if (seg != GS_TLS_SEL)
165 return 0; 197 return 0;
166 return get_desc_base(&child->thread.tls_array[GS_TLS]); 198 return get_desc_base(&child->thread.tls_array[GS_TLS]);
167 case offsetof(struct user_regs_struct, flags): 199 case offsetof(struct user_regs_struct, flags):