aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)