aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/step.c
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2010-03-25 09:51:51 -0400
committerIngo Molnar <mingo@elte.hu>2010-03-26 06:33:57 -0400
commitea8e61b7bbc4a2faef77db34eb2db2a2c2372ff6 (patch)
treedf2998225dc10245ce3d392576a724ab788e456c /arch/x86/kernel/step.c
parentfaa4602e47690fb11221e00f9b9697c8dc0d4b19 (diff)
x86, ptrace: Fix block-step
Implement ptrace-block-step using TIF_BLOCKSTEP which will set DEBUGCTLMSR_BTF when set for a task while preserving any other DEBUGCTLMSR bits. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <20100325135414.017536066@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/step.c')
-rw-r--r--arch/x86/kernel/step.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c
index 7beba0769a8c..58de45ee08b6 100644
--- a/arch/x86/kernel/step.c
+++ b/arch/x86/kernel/step.c
@@ -169,9 +169,19 @@ static void enable_step(struct task_struct *child, bool block)
169 * So noone should try to use debugger block stepping in a program 169 * So noone should try to use debugger block stepping in a program
170 * that uses user-mode single stepping itself. 170 * that uses user-mode single stepping itself.
171 */ 171 */
172 if (!enable_single_step(child)) 172 if (enable_single_step(child) && block) {
173 return; 173 unsigned long debugctl = get_debugctlmsr();
174 /* XXX */ 174
175 debugctl |= DEBUGCTLMSR_BTF;
176 update_debugctlmsr(debugctl);
177 set_tsk_thread_flag(child, TIF_BLOCKSTEP);
178 } else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) {
179 unsigned long debugctl = get_debugctlmsr();
180
181 debugctl &= ~DEBUGCTLMSR_BTF;
182 update_debugctlmsr(debugctl);
183 clear_tsk_thread_flag(child, TIF_BLOCKSTEP);
184 }
175} 185}
176 186
177void user_enable_single_step(struct task_struct *child) 187void user_enable_single_step(struct task_struct *child)
@@ -189,7 +199,13 @@ void user_disable_single_step(struct task_struct *child)
189 /* 199 /*
190 * Make sure block stepping (BTF) is disabled. 200 * Make sure block stepping (BTF) is disabled.
191 */ 201 */
192 /* XXX */ 202 if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) {
203 unsigned long debugctl = get_debugctlmsr();
204
205 debugctl &= ~DEBUGCTLMSR_BTF;
206 update_debugctlmsr(debugctl);
207 clear_tsk_thread_flag(child, TIF_BLOCKSTEP);
208 }
193 209
194 /* Always clear TIF_SINGLESTEP... */ 210 /* Always clear TIF_SINGLESTEP... */
195 clear_tsk_thread_flag(child, TIF_SINGLESTEP); 211 clear_tsk_thread_flag(child, TIF_SINGLESTEP);