diff options
author | Markus Metzger <markus.t.metzger@intel.com> | 2008-12-19 09:10:24 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-12-20 03:15:46 -0500 |
commit | bf53de907dfdaac178c92d774aae7370d7b97d20 (patch) | |
tree | 738a07a8b4b22f7bb8ec2029c9ea9c635db6c62a /arch/x86/kernel | |
parent | 30cd324e9787ccc9a5ede59742d5409857550692 (diff) |
x86, bts: add fork and exit handling
Impact: introduce new ptrace facility
Add arch_ptrace_untrace() function that is called when the tracer
detaches (either voluntarily or when the tracing task dies);
ptrace_disable() is only called on a voluntary detach.
Add ptrace_fork() and arch_ptrace_fork(). They are called when a
traced task is forked.
Clear DS and BTS related fields on fork.
Release DS resources and reclaim memory in ptrace_untrace(). This
releases resources already when the tracing task dies. We used to do
that when the traced task dies.
Signed-off-by: Markus Metzger <markus.t.metzger@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/ds.c | 11 | ||||
-rw-r--r-- | arch/x86/kernel/process_32.c | 20 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 20 | ||||
-rw-r--r-- | arch/x86/kernel/ptrace.c | 50 |
4 files changed, 69 insertions, 32 deletions
diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c index 98d271e60e08..da91701a2348 100644 --- a/arch/x86/kernel/ds.c +++ b/arch/x86/kernel/ds.c | |||
@@ -1017,3 +1017,14 @@ void ds_switch_to(struct task_struct *prev, struct task_struct *next) | |||
1017 | 1017 | ||
1018 | update_debugctlmsr(next->thread.debugctlmsr); | 1018 | update_debugctlmsr(next->thread.debugctlmsr); |
1019 | } | 1019 | } |
1020 | |||
1021 | void ds_copy_thread(struct task_struct *tsk, struct task_struct *father) | ||
1022 | { | ||
1023 | clear_tsk_thread_flag(tsk, TIF_DS_AREA_MSR); | ||
1024 | tsk->thread.ds_ctx = NULL; | ||
1025 | } | ||
1026 | |||
1027 | void ds_exit_thread(struct task_struct *tsk) | ||
1028 | { | ||
1029 | WARN_ON(tsk->thread.ds_ctx); | ||
1030 | } | ||
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 605eff9a8ac0..3ba155d24884 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -60,6 +60,7 @@ | |||
60 | #include <asm/idle.h> | 60 | #include <asm/idle.h> |
61 | #include <asm/syscalls.h> | 61 | #include <asm/syscalls.h> |
62 | #include <asm/smp.h> | 62 | #include <asm/smp.h> |
63 | #include <asm/ds.h> | ||
63 | 64 | ||
64 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); | 65 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); |
65 | 66 | ||
@@ -251,17 +252,8 @@ void exit_thread(void) | |||
251 | tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET; | 252 | tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET; |
252 | put_cpu(); | 253 | put_cpu(); |
253 | } | 254 | } |
254 | #ifdef CONFIG_X86_DS | 255 | |
255 | /* Free any BTS tracers that have not been properly released. */ | 256 | ds_exit_thread(current); |
256 | if (unlikely(current->bts)) { | ||
257 | ds_release_bts(current->bts); | ||
258 | current->bts = NULL; | ||
259 | |||
260 | kfree(current->bts_buffer); | ||
261 | current->bts_buffer = NULL; | ||
262 | current->bts_size = 0; | ||
263 | } | ||
264 | #endif /* CONFIG_X86_DS */ | ||
265 | } | 257 | } |
266 | 258 | ||
267 | void flush_thread(void) | 259 | void flush_thread(void) |
@@ -343,6 +335,12 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, | |||
343 | kfree(p->thread.io_bitmap_ptr); | 335 | kfree(p->thread.io_bitmap_ptr); |
344 | p->thread.io_bitmap_max = 0; | 336 | p->thread.io_bitmap_max = 0; |
345 | } | 337 | } |
338 | |||
339 | ds_copy_thread(p, current); | ||
340 | |||
341 | clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR); | ||
342 | p->thread.debugctlmsr = 0; | ||
343 | |||
346 | return err; | 344 | return err; |
347 | } | 345 | } |
348 | 346 | ||
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 1cfd2a4bf853..416fb9282f4f 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <asm/ia32.h> | 53 | #include <asm/ia32.h> |
54 | #include <asm/idle.h> | 54 | #include <asm/idle.h> |
55 | #include <asm/syscalls.h> | 55 | #include <asm/syscalls.h> |
56 | #include <asm/ds.h> | ||
56 | 57 | ||
57 | asmlinkage extern void ret_from_fork(void); | 58 | asmlinkage extern void ret_from_fork(void); |
58 | 59 | ||
@@ -236,17 +237,8 @@ void exit_thread(void) | |||
236 | t->io_bitmap_max = 0; | 237 | t->io_bitmap_max = 0; |
237 | put_cpu(); | 238 | put_cpu(); |
238 | } | 239 | } |
239 | #ifdef CONFIG_X86_DS | 240 | |
240 | /* Free any BTS tracers that have not been properly released. */ | 241 | ds_exit_thread(current); |
241 | if (unlikely(current->bts)) { | ||
242 | ds_release_bts(current->bts); | ||
243 | current->bts = NULL; | ||
244 | |||
245 | kfree(current->bts_buffer); | ||
246 | current->bts_buffer = NULL; | ||
247 | current->bts_size = 0; | ||
248 | } | ||
249 | #endif /* CONFIG_X86_DS */ | ||
250 | } | 242 | } |
251 | 243 | ||
252 | void flush_thread(void) | 244 | void flush_thread(void) |
@@ -376,6 +368,12 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, | |||
376 | if (err) | 368 | if (err) |
377 | goto out; | 369 | goto out; |
378 | } | 370 | } |
371 | |||
372 | ds_copy_thread(p, me); | ||
373 | |||
374 | clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR); | ||
375 | p->thread.debugctlmsr = 0; | ||
376 | |||
379 | err = 0; | 377 | err = 0; |
380 | out: | 378 | out: |
381 | if (err && p->thread.io_bitmap_ptr) { | 379 | if (err && p->thread.io_bitmap_ptr) { |
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 45e9855da2d2..6ad2bb607650 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
@@ -769,8 +769,47 @@ static int ptrace_bts_size(struct task_struct *child) | |||
769 | 769 | ||
770 | return (trace->ds.top - trace->ds.begin) / trace->ds.size; | 770 | return (trace->ds.top - trace->ds.begin) / trace->ds.size; |
771 | } | 771 | } |
772 | |||
773 | static void ptrace_bts_fork(struct task_struct *tsk) | ||
774 | { | ||
775 | tsk->bts = NULL; | ||
776 | tsk->bts_buffer = NULL; | ||
777 | tsk->bts_size = 0; | ||
778 | tsk->thread.bts_ovfl_signal = 0; | ||
779 | } | ||
780 | |||
781 | static void ptrace_bts_untrace(struct task_struct *child) | ||
782 | { | ||
783 | if (unlikely(child->bts)) { | ||
784 | ds_release_bts(child->bts); | ||
785 | child->bts = NULL; | ||
786 | |||
787 | kfree(child->bts_buffer); | ||
788 | child->bts_buffer = NULL; | ||
789 | child->bts_size = 0; | ||
790 | } | ||
791 | } | ||
792 | |||
793 | static void ptrace_bts_detach(struct task_struct *child) | ||
794 | { | ||
795 | ptrace_bts_untrace(child); | ||
796 | } | ||
797 | #else | ||
798 | static inline void ptrace_bts_fork(struct task_struct *tsk) {} | ||
799 | static inline void ptrace_bts_detach(struct task_struct *child) {} | ||
800 | static inline void ptrace_bts_untrace(struct task_struct *child) {} | ||
772 | #endif /* CONFIG_X86_PTRACE_BTS */ | 801 | #endif /* CONFIG_X86_PTRACE_BTS */ |
773 | 802 | ||
803 | void x86_ptrace_fork(struct task_struct *child, unsigned long clone_flags) | ||
804 | { | ||
805 | ptrace_bts_fork(child); | ||
806 | } | ||
807 | |||
808 | void x86_ptrace_untrace(struct task_struct *child) | ||
809 | { | ||
810 | ptrace_bts_untrace(child); | ||
811 | } | ||
812 | |||
774 | /* | 813 | /* |
775 | * Called by kernel/ptrace.c when detaching.. | 814 | * Called by kernel/ptrace.c when detaching.. |
776 | * | 815 | * |
@@ -782,16 +821,7 @@ void ptrace_disable(struct task_struct *child) | |||
782 | #ifdef TIF_SYSCALL_EMU | 821 | #ifdef TIF_SYSCALL_EMU |
783 | clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); | 822 | clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); |
784 | #endif | 823 | #endif |
785 | #ifdef CONFIG_X86_PTRACE_BTS | 824 | ptrace_bts_detach(child); |
786 | if (child->bts) { | ||
787 | ds_release_bts(child->bts); | ||
788 | child->bts = NULL; | ||
789 | |||
790 | kfree(child->bts_buffer); | ||
791 | child->bts_buffer = NULL; | ||
792 | child->bts_size = 0; | ||
793 | } | ||
794 | #endif /* CONFIG_X86_PTRACE_BTS */ | ||
795 | } | 825 | } |
796 | 826 | ||
797 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION | 827 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION |