diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2010-03-25 09:51:51 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-03-26 06:33:57 -0400 |
commit | ea8e61b7bbc4a2faef77db34eb2db2a2c2372ff6 (patch) | |
tree | df2998225dc10245ce3d392576a724ab788e456c /arch/x86/kernel/step.c | |
parent | faa4602e47690fb11221e00f9b9697c8dc0d4b19 (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.c | 24 |
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 | ||
177 | void user_enable_single_step(struct task_struct *child) | 187 | void 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); |