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 72edac026a7..5bafdec3444 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 | } |
