aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/step.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c
index 7a514986ca09..f89cdc6ccd5b 100644
--- a/arch/x86/kernel/step.c
+++ b/arch/x86/kernel/step.c
@@ -161,6 +161,16 @@ static void set_task_blockstep(struct task_struct *task, bool on)
161{ 161{
162 unsigned long debugctl; 162 unsigned long debugctl;
163 163
164 /*
165 * Ensure irq/preemption can't change debugctl in between.
166 * Note also that both TIF_BLOCKSTEP and debugctl should
167 * be changed atomically wrt preemption.
168 * FIXME: this means that set/clear TIF_BLOCKSTEP is simply
169 * wrong if task != current, SIGKILL can wakeup the stopped
170 * tracee and set/clear can play with the running task, this
171 * can confuse the next __switch_to_xtra().
172 */
173 local_irq_disable();
164 debugctl = get_debugctlmsr(); 174 debugctl = get_debugctlmsr();
165 if (on) { 175 if (on) {
166 debugctl |= DEBUGCTLMSR_BTF; 176 debugctl |= DEBUGCTLMSR_BTF;
@@ -169,7 +179,9 @@ static void set_task_blockstep(struct task_struct *task, bool on)
169 debugctl &= ~DEBUGCTLMSR_BTF; 179 debugctl &= ~DEBUGCTLMSR_BTF;
170 clear_tsk_thread_flag(task, TIF_BLOCKSTEP); 180 clear_tsk_thread_flag(task, TIF_BLOCKSTEP);
171 } 181 }
172 update_debugctlmsr(debugctl); 182 if (task == current)
183 update_debugctlmsr(debugctl);
184 local_irq_enable();
173} 185}
174 186
175/* 187/*