aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/ptrace.c')
-rw-r--r--arch/x86/kernel/ptrace.c212
1 files changed, 212 insertions, 0 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 3399c1be79b8..8d0dd8b5effe 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -2,6 +2,9 @@
2/* 2/*
3 * Pentium III FXSR, SSE support 3 * Pentium III FXSR, SSE support
4 * Gareth Hughes <gareth@valinux.com>, May 2000 4 * Gareth Hughes <gareth@valinux.com>, May 2000
5 *
6 * BTS tracing
7 * Markus Metzger <markus.t.metzger@intel.com>, Dec 2007
5 */ 8 */
6 9
7#include <linux/kernel.h> 10#include <linux/kernel.h>
@@ -26,6 +29,14 @@
26#include <asm/desc.h> 29#include <asm/desc.h>
27#include <asm/prctl.h> 30#include <asm/prctl.h>
28#include <asm/proto.h> 31#include <asm/proto.h>
32#include <asm/ds.h>
33
34
35/*
36 * The maximal size of a BTS buffer per traced task in number of BTS
37 * records.
38 */
39#define PTRACE_BTS_BUFFER_MAX 4000
29 40
30/* 41/*
31 * does not yet catch signals sent when the child dies. 42 * does not yet catch signals sent when the child dies.
@@ -455,6 +466,165 @@ static int ptrace_set_debugreg(struct task_struct *child,
455 return 0; 466 return 0;
456} 467}
457 468
469static int ptrace_bts_max_buffer_size(void)
470{
471 return PTRACE_BTS_BUFFER_MAX;
472}
473
474static int ptrace_bts_get_buffer_size(struct task_struct *child)
475{
476 if (!child->thread.ds_area_msr)
477 return -ENXIO;
478
479 return ds_get_bts_size((void *)child->thread.ds_area_msr);
480}
481
482static int ptrace_bts_get_index(struct task_struct *child)
483{
484 if (!child->thread.ds_area_msr)
485 return -ENXIO;
486
487 return ds_get_bts_index((void *)child->thread.ds_area_msr);
488}
489
490static int ptrace_bts_read_record(struct task_struct *child,
491 long index,
492 struct bts_struct __user *out)
493{
494 struct bts_struct ret;
495 int retval;
496
497 if (!child->thread.ds_area_msr)
498 return -ENXIO;
499
500 retval = ds_read_bts((void *)child->thread.ds_area_msr,
501 index, &ret);
502 if (retval)
503 return retval;
504
505 if (copy_to_user(out, &ret, sizeof(ret)))
506 return -EFAULT;
507
508 return sizeof(ret);
509}
510
511static int ptrace_bts_write_record(struct task_struct *child,
512 const struct bts_struct *in)
513{
514 int retval;
515
516 if (!child->thread.ds_area_msr)
517 return -ENXIO;
518
519 retval = ds_write_bts((void *)child->thread.ds_area_msr, in);
520 if (retval)
521 return retval;
522
523 return sizeof(*in);
524}
525
526static int ptrace_bts_config(struct task_struct *child,
527 unsigned long options)
528{
529 unsigned long debugctl_mask = ds_debugctl_mask();
530 int retval;
531
532 retval = ptrace_bts_get_buffer_size(child);
533 if (retval < 0)
534 return retval;
535 if (retval == 0)
536 return -ENXIO;
537
538 if (options & PTRACE_BTS_O_TRACE_TASK) {
539 child->thread.debugctlmsr |= debugctl_mask;
540 set_tsk_thread_flag(child, TIF_DEBUGCTLMSR);
541 } else {
542 /* there is no way for us to check whether we 'own'
543 * the respective bits in the DEBUGCTL MSR, we're
544 * about to clear */
545 child->thread.debugctlmsr &= ~debugctl_mask;
546
547 if (!child->thread.debugctlmsr)
548 clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR);
549 }
550
551 if (options & PTRACE_BTS_O_TIMESTAMPS)
552 set_tsk_thread_flag(child, TIF_BTS_TRACE_TS);
553 else
554 clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS);
555
556 return 0;
557}
558
559static int ptrace_bts_status(struct task_struct *child)
560{
561 unsigned long debugctl_mask = ds_debugctl_mask();
562 int retval, status = 0;
563
564 retval = ptrace_bts_get_buffer_size(child);
565 if (retval < 0)
566 return retval;
567 if (retval == 0)
568 return -ENXIO;
569
570 if (ptrace_bts_get_buffer_size(child) <= 0)
571 return -ENXIO;
572
573 if (test_tsk_thread_flag(child, TIF_DEBUGCTLMSR) &&
574 child->thread.debugctlmsr & debugctl_mask)
575 status |= PTRACE_BTS_O_TRACE_TASK;
576 if (test_tsk_thread_flag(child, TIF_BTS_TRACE_TS))
577 status |= PTRACE_BTS_O_TIMESTAMPS;
578
579 return status;
580}
581
582static int ptrace_bts_allocate_bts(struct task_struct *child,
583 int size_in_records)
584{
585 int retval = 0;
586 void *ds;
587
588 if (size_in_records < 0)
589 return -EINVAL;
590
591 if (size_in_records > ptrace_bts_max_buffer_size())
592 return -EINVAL;
593
594 if (size_in_records == 0) {
595 ptrace_bts_config(child, /* options = */ 0);
596 } else {
597 retval = ds_allocate(&ds, size_in_records);
598 if (retval)
599 return retval;
600 }
601
602 if (child->thread.ds_area_msr)
603 ds_free((void **)&child->thread.ds_area_msr);
604
605 child->thread.ds_area_msr = (unsigned long)ds;
606 if (child->thread.ds_area_msr)
607 set_tsk_thread_flag(child, TIF_DS_AREA_MSR);
608 else
609 clear_tsk_thread_flag(child, TIF_DS_AREA_MSR);
610
611 return retval;
612}
613
614void ptrace_bts_take_timestamp(struct task_struct *tsk,
615 enum bts_qualifier qualifier)
616{
617 struct bts_struct rec = {
618 .qualifier = qualifier,
619 .variant.timestamp = sched_clock()
620 };
621
622 if (ptrace_bts_get_buffer_size(tsk) <= 0)
623 return;
624
625 ptrace_bts_write_record(tsk, &rec);
626}
627
458/* 628/*
459 * Called by kernel/ptrace.c when detaching.. 629 * Called by kernel/ptrace.c when detaching..
460 * 630 *
@@ -466,6 +636,11 @@ void ptrace_disable(struct task_struct *child)
466#ifdef TIF_SYSCALL_EMU 636#ifdef TIF_SYSCALL_EMU
467 clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); 637 clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
468#endif 638#endif
639 ptrace_bts_config(child, /* options = */ 0);
640 if (child->thread.ds_area_msr) {
641 ds_free((void **)&child->thread.ds_area_msr);
642 clear_tsk_thread_flag(child, TIF_DS_AREA_MSR);
643 }
469} 644}
470 645
471long arch_ptrace(struct task_struct *child, long request, long addr, long data) 646long arch_ptrace(struct task_struct *child, long request, long addr, long data)
@@ -626,6 +801,36 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
626 break; 801 break;
627#endif 802#endif
628 803
804 case PTRACE_BTS_MAX_BUFFER_SIZE:
805 ret = ptrace_bts_max_buffer_size();
806 break;
807
808 case PTRACE_BTS_ALLOCATE_BUFFER:
809 ret = ptrace_bts_allocate_bts(child, data);
810 break;
811
812 case PTRACE_BTS_GET_BUFFER_SIZE:
813 ret = ptrace_bts_get_buffer_size(child);
814 break;
815
816 case PTRACE_BTS_GET_INDEX:
817 ret = ptrace_bts_get_index(child);
818 break;
819
820 case PTRACE_BTS_READ_RECORD:
821 ret = ptrace_bts_read_record
822 (child, data,
823 (struct bts_struct __user *) addr);
824 break;
825
826 case PTRACE_BTS_CONFIG:
827 ret = ptrace_bts_config(child, data);
828 break;
829
830 case PTRACE_BTS_STATUS:
831 ret = ptrace_bts_status(child);
832 break;
833
629 default: 834 default:
630 ret = ptrace_request(child, request, addr, data); 835 ret = ptrace_request(child, request, addr, data);
631 break; 836 break;
@@ -809,6 +1014,13 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
809 case PTRACE_SETOPTIONS: 1014 case PTRACE_SETOPTIONS:
810 case PTRACE_SET_THREAD_AREA: 1015 case PTRACE_SET_THREAD_AREA:
811 case PTRACE_GET_THREAD_AREA: 1016 case PTRACE_GET_THREAD_AREA:
1017 case PTRACE_BTS_MAX_BUFFER_SIZE:
1018 case PTRACE_BTS_ALLOCATE_BUFFER:
1019 case PTRACE_BTS_GET_BUFFER_SIZE:
1020 case PTRACE_BTS_GET_INDEX:
1021 case PTRACE_BTS_READ_RECORD:
1022 case PTRACE_BTS_CONFIG:
1023 case PTRACE_BTS_STATUS:
812 return sys_ptrace(request, pid, addr, data); 1024 return sys_ptrace(request, pid, addr, data);
813 1025
814 default: 1026 default: