diff options
Diffstat (limited to 'arch/x86/kernel/process_64.c')
-rw-r--r-- | arch/x86/kernel/process_64.c | 26 |
1 files changed, 1 insertions, 25 deletions
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 72edac026a78..5bafdec34441 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -53,7 +53,6 @@ | |||
53 | #include <asm/syscalls.h> | 53 | #include <asm/syscalls.h> |
54 | #include <asm/ds.h> | 54 | #include <asm/ds.h> |
55 | #include <asm/debugreg.h> | 55 | #include <asm/debugreg.h> |
56 | #include <asm/hw_breakpoint.h> | ||
57 | 56 | ||
58 | asmlinkage extern void ret_from_fork(void); | 57 | asmlinkage extern void ret_from_fork(void); |
59 | 58 | ||
@@ -244,8 +243,6 @@ void release_thread(struct task_struct *dead_task) | |||
244 | BUG(); | 243 | BUG(); |
245 | } | 244 | } |
246 | } | 245 | } |
247 | if (unlikely(dead_task->thread.debugreg7)) | ||
248 | flush_thread_hw_breakpoint(dead_task); | ||
249 | } | 246 | } |
250 | 247 | ||
251 | static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr) | 248 | static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr) |
@@ -309,9 +306,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
309 | savesegment(ds, p->thread.ds); | 306 | savesegment(ds, p->thread.ds); |
310 | 307 | ||
311 | err = -ENOMEM; | 308 | err = -ENOMEM; |
312 | if (unlikely(test_tsk_thread_flag(me, TIF_DEBUG))) | 309 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); |
313 | if (copy_thread_hw_breakpoint(me, p, clone_flags)) | ||
314 | goto out; | ||
315 | 310 | ||
316 | if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) { | 311 | if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) { |
317 | p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); | 312 | p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); |
@@ -351,8 +346,6 @@ out: | |||
351 | kfree(p->thread.io_bitmap_ptr); | 346 | kfree(p->thread.io_bitmap_ptr); |
352 | p->thread.io_bitmap_max = 0; | 347 | p->thread.io_bitmap_max = 0; |
353 | } | 348 | } |
354 | if (err) | ||
355 | flush_thread_hw_breakpoint(p); | ||
356 | 349 | ||
357 | return err; | 350 | return err; |
358 | } | 351 | } |
@@ -508,23 +501,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
508 | */ | 501 | */ |
509 | if (preload_fpu) | 502 | if (preload_fpu) |
510 | __math_state_restore(); | 503 | __math_state_restore(); |
511 | /* | ||
512 | * There's a problem with moving the arch_install_thread_hw_breakpoint() | ||
513 | * call before current is updated. Suppose a kernel breakpoint is | ||
514 | * triggered in between the two, the hw-breakpoint handler will see that | ||
515 | * the 'current' task does not have TIF_DEBUG flag set and will think it | ||
516 | * is leftover from an old task (lazy switching) and will erase it. Then | ||
517 | * until the next context switch, no user-breakpoints will be installed. | ||
518 | * | ||
519 | * The real problem is that it's impossible to update both current and | ||
520 | * physical debug registers at the same instant, so there will always be | ||
521 | * a window in which they disagree and a breakpoint might get triggered. | ||
522 | * Since we use lazy switching, we are forced to assume that a | ||
523 | * disagreement means that current is correct and the exception is due | ||
524 | * to lazy debug register switching. | ||
525 | */ | ||
526 | if (unlikely(test_tsk_thread_flag(next_p, TIF_DEBUG))) | ||
527 | arch_install_thread_hw_breakpoint(next_p); | ||
528 | 504 | ||
529 | return prev_p; | 505 | return prev_p; |
530 | } | 506 | } |