aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHendrik Brueckner <brueckner@linux.vnet.ibm.com>2016-03-08 08:00:23 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2017-11-16 09:06:17 -0500
commit544e8dd7a8e49d22b4315fc232479bc02b417b46 (patch)
tree1896b1f409ea5c14ea733d514b3fc0547d55cec2
parentd4c7e649d7bf17792629dbeaf25945e26a32894f (diff)
s390/cpum_sf: correctly set the PID and TID in perf samples
The hardware sampler creates samples that are processed at a later point in time. The PID and TID values of the perf samples that are created for hardware samples are initialized with values from the current task. Hence, the PID and TID values are not correct and perf samples are associated with wrong processes. The PID and TID values are obtained from the Host Program Parameter (HPP) field in the basic-sampling data entries. These PIDs are valid in the init PID namespace. Ensure that the PIDs in the perf samples are resolved considering the PID namespace in which the perf event was created. To correct the PID and TID values in the created perf samples, a special overflow handler is installed. It replaces the default overflow handler and does not become effective if any other overflow handler is used. With the special overflow handler most of the perf samples are associated with the right processes. For processes, that are no longer exist, the association might still be wrong. Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/include/asm/setup.h2
-rw-r--r--arch/s390/kernel/perf_cpum_sf.c76
-rw-r--r--arch/s390/mm/fault.c2
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
619static 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 }
645out:
646 return pid;
647}
648
649static 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);
676out:
677 rcu_read_unlock();
678}
679
618static int __hw_perf_event_init(struct perf_event *event) 680static 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;
751out: 821out:
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, &regs, sde_regs)) 1065 if (perf_exclude_event(event, &regs, 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)