diff options
-rw-r--r-- | arch/s390/include/asm/setup.h | 2 | ||||
-rw-r--r-- | arch/s390/kernel/perf_cpum_sf.c | 76 | ||||
-rw-r--r-- | arch/s390/mm/fault.c | 2 |
3 files changed, 78 insertions, 2 deletions
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index 8bc87dcb10eb..2eb0c8a7b664 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h | |||
@@ -36,7 +36,7 @@ | |||
36 | #define MACHINE_FLAG_SCC _BITUL(17) | 36 | #define MACHINE_FLAG_SCC _BITUL(17) |
37 | 37 | ||
38 | #define LPP_MAGIC _BITUL(31) | 38 | #define LPP_MAGIC _BITUL(31) |
39 | #define LPP_PFAULT_PID_MASK _AC(0xffffffff, UL) | 39 | #define LPP_PID_MASK _AC(0xffffffff, UL) |
40 | 40 | ||
41 | #ifndef __ASSEMBLY__ | 41 | #ifndef __ASSEMBLY__ |
42 | 42 | ||
diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c index dbb62c05805d..227b38bd82c9 100644 --- a/arch/s390/kernel/perf_cpum_sf.c +++ b/arch/s390/kernel/perf_cpum_sf.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/kernel_stat.h> | 15 | #include <linux/kernel_stat.h> |
16 | #include <linux/perf_event.h> | 16 | #include <linux/perf_event.h> |
17 | #include <linux/percpu.h> | 17 | #include <linux/percpu.h> |
18 | #include <linux/pid.h> | ||
18 | #include <linux/notifier.h> | 19 | #include <linux/notifier.h> |
19 | #include <linux/export.h> | 20 | #include <linux/export.h> |
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
@@ -615,6 +616,67 @@ static unsigned long hw_limit_rate(const struct hws_qsi_info_block *si, | |||
615 | si->min_sampl_rate, si->max_sampl_rate); | 616 | si->min_sampl_rate, si->max_sampl_rate); |
616 | } | 617 | } |
617 | 618 | ||
619 | static u32 cpumsf_pid_type(struct perf_event *event, | ||
620 | u32 pid, enum pid_type type) | ||
621 | { | ||
622 | struct task_struct *tsk; | ||
623 | |||
624 | /* Idle process */ | ||
625 | if (!pid) | ||
626 | goto out; | ||
627 | |||
628 | tsk = find_task_by_pid_ns(pid, &init_pid_ns); | ||
629 | pid = -1; | ||
630 | if (tsk) { | ||
631 | /* | ||
632 | * Only top level events contain the pid namespace in which | ||
633 | * they are created. | ||
634 | */ | ||
635 | if (event->parent) | ||
636 | event = event->parent; | ||
637 | pid = __task_pid_nr_ns(tsk, type, event->ns); | ||
638 | /* | ||
639 | * See also 1d953111b648 | ||
640 | * "perf/core: Don't report zero PIDs for exiting tasks". | ||
641 | */ | ||
642 | if (!pid && !pid_alive(tsk)) | ||
643 | pid = -1; | ||
644 | } | ||
645 | out: | ||
646 | return pid; | ||
647 | } | ||
648 | |||
649 | static void cpumsf_output_event_pid(struct perf_event *event, | ||
650 | struct perf_sample_data *data, | ||
651 | struct pt_regs *regs) | ||
652 | { | ||
653 | u32 pid; | ||
654 | struct perf_event_header header; | ||
655 | struct perf_output_handle handle; | ||
656 | |||
657 | /* | ||
658 | * Obtain the PID from the basic-sampling data entry and | ||
659 | * correct the data->tid_entry.pid value. | ||
660 | */ | ||
661 | pid = data->tid_entry.pid; | ||
662 | |||
663 | /* Protect callchain buffers, tasks */ | ||
664 | rcu_read_lock(); | ||
665 | |||
666 | perf_prepare_sample(&header, data, event, regs); | ||
667 | if (perf_output_begin(&handle, event, header.size)) | ||
668 | goto out; | ||
669 | |||
670 | /* Update the process ID (see also kernel/events/core.c) */ | ||
671 | data->tid_entry.pid = cpumsf_pid_type(event, pid, __PIDTYPE_TGID); | ||
672 | data->tid_entry.tid = cpumsf_pid_type(event, pid, PIDTYPE_PID); | ||
673 | |||
674 | perf_output_sample(&handle, &header, data, event); | ||
675 | perf_output_end(&handle); | ||
676 | out: | ||
677 | rcu_read_unlock(); | ||
678 | } | ||
679 | |||
618 | static int __hw_perf_event_init(struct perf_event *event) | 680 | static int __hw_perf_event_init(struct perf_event *event) |
619 | { | 681 | { |
620 | struct cpu_hw_sf *cpuhw; | 682 | struct cpu_hw_sf *cpuhw; |
@@ -748,6 +810,14 @@ static int __hw_perf_event_init(struct perf_event *event) | |||
748 | break; | 810 | break; |
749 | } | 811 | } |
750 | } | 812 | } |
813 | |||
814 | /* If PID/TID sampling is active, replace the default overflow | ||
815 | * handler to extract and resolve the PIDs from the basic-sampling | ||
816 | * data entries. | ||
817 | */ | ||
818 | if (event->attr.sample_type & PERF_SAMPLE_TID) | ||
819 | if (is_default_overflow_handler(event)) | ||
820 | event->overflow_handler = cpumsf_output_event_pid; | ||
751 | out: | 821 | out: |
752 | return err; | 822 | return err; |
753 | } | 823 | } |
@@ -985,6 +1055,12 @@ static int perf_push_sample(struct perf_event *event, | |||
985 | break; | 1055 | break; |
986 | } | 1056 | } |
987 | 1057 | ||
1058 | /* | ||
1059 | * Store the PID value from the sample-data-entry to be | ||
1060 | * processed and resolved by cpumsf_output_event_pid(). | ||
1061 | */ | ||
1062 | data.tid_entry.pid = basic->hpp & LPP_PID_MASK; | ||
1063 | |||
988 | overflow = 0; | 1064 | overflow = 0; |
989 | if (perf_exclude_event(event, ®s, sde_regs)) | 1065 | if (perf_exclude_event(event, ®s, sde_regs)) |
990 | goto out; | 1066 | goto out; |
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 14654007dce4..93faeca52284 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -728,7 +728,7 @@ static void pfault_interrupt(struct ext_code ext_code, | |||
728 | return; | 728 | return; |
729 | inc_irq_stat(IRQEXT_PFL); | 729 | inc_irq_stat(IRQEXT_PFL); |
730 | /* Get the token (= pid of the affected task). */ | 730 | /* Get the token (= pid of the affected task). */ |
731 | pid = param64 & LPP_PFAULT_PID_MASK; | 731 | pid = param64 & LPP_PID_MASK; |
732 | rcu_read_lock(); | 732 | rcu_read_lock(); |
733 | tsk = find_task_by_pid_ns(pid, &init_pid_ns); | 733 | tsk = find_task_by_pid_ns(pid, &init_pid_ns); |
734 | if (tsk) | 734 | if (tsk) |