s390/diag: add tracepoint for diagnose calls
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 21 Aug 2015 14:05:32 +0000 (16:05 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 14 Oct 2015 12:32:06 +0000 (14:32 +0200)
To be able to analyse problems in regard to hypervisor overhead
add a tracepoing for diagnose calls. It reports the number of
the diagnose issued, e.g.

            sshd-1385  [002] ....    42.701431: diagnose: nr=0x9c
          <idle>-0     [001] ..s.    43.587528: diagnose: nr=0x9c

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/diag.h
arch/s390/include/asm/trace/diag.h [new file with mode: 0644]
arch/s390/kernel/Makefile
arch/s390/kernel/diag.c
arch/s390/kernel/smp.c
arch/s390/kernel/trace.c [new file with mode: 0644]

index e423cfcaf77d694333d286feda0cdaaba09d2430..5fac921c1c4210c66b8cb3f3a6b4ca4f4bf71ed9 100644 (file)
@@ -33,16 +33,8 @@ enum diag_stat_enum {
        NR_DIAG_STAT
 };
 
-struct diag_stat {
-       unsigned int counter[NR_DIAG_STAT];
-};
-
-DECLARE_PER_CPU(struct diag_stat, diag_stat);
-
-static inline void diag_stat_inc(enum diag_stat_enum nr)
-{
-       this_cpu_inc(diag_stat.counter[nr]);
-}
+void diag_stat_inc(enum diag_stat_enum nr);
+void diag_stat_inc_norecursion(enum diag_stat_enum nr);
 
 /*
  * Diagnose 10: Release page range
diff --git a/arch/s390/include/asm/trace/diag.h b/arch/s390/include/asm/trace/diag.h
new file mode 100644 (file)
index 0000000..776f307
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Tracepoint header for s390 diagnose calls
+ *
+ * Copyright IBM Corp. 2015
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM s390
+
+#if !defined(_TRACE_S390_DIAG_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_S390_DIAG_H
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+
+#define TRACE_INCLUDE_PATH asm/trace
+#define TRACE_INCLUDE_FILE diag
+
+TRACE_EVENT(diagnose,
+       TP_PROTO(unsigned short nr),
+       TP_ARGS(nr),
+       TP_STRUCT__entry(
+               __field(unsigned short, nr)
+       ),
+       TP_fast_assign(
+               __entry->nr = nr;
+       ),
+       TP_printk("nr=0x%x", __entry->nr)
+);
+
+#ifdef CONFIG_TRACEPOINTS
+void trace_diagnose_norecursion(int diag_nr);
+#else
+static inline void trace_diagnose_norecursion(int diag_nr) { }
+#endif
+
+#endif /* _TRACE_S390_DIAG_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index b756c6348ac68ec20d9b67269823ab50db61f837..dc167a23b92055b63ecf20f9e9146f672b98ac0e 100644 (file)
@@ -66,6 +66,8 @@ obj-$(CONFIG_UPROBES)         += uprobes.o
 obj-$(CONFIG_PERF_EVENTS)      += perf_event.o perf_cpum_cf.o perf_cpum_sf.o
 obj-$(CONFIG_PERF_EVENTS)      += perf_cpum_cf_events.o
 
+obj-$(CONFIG_TRACEPOINTS)      += trace.o
+
 # vdso
 obj-y                          += vdso64/
 obj-$(CONFIG_COMPAT)           += vdso32/
index 4ddb5200ddf0a0f457cde957f49b791715e91ed6..f98766ede4e156e83dc222194ed677150b891c64 100644 (file)
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
 #include <asm/diag.h>
+#include <asm/trace/diag.h>
 
-DEFINE_PER_CPU(struct diag_stat, diag_stat);
-EXPORT_PER_CPU_SYMBOL(diag_stat);
+struct diag_stat {
+       unsigned int counter[NR_DIAG_STAT];
+};
+
+static DEFINE_PER_CPU(struct diag_stat, diag_stat);
 
 struct diag_desc {
        int code;
@@ -114,6 +118,20 @@ static int __init show_diag_stat_init(void)
 
 device_initcall(show_diag_stat_init);
 
+void diag_stat_inc(enum diag_stat_enum nr)
+{
+       this_cpu_inc(diag_stat.counter[nr]);
+       trace_diagnose(diag_map[nr].code);
+}
+EXPORT_SYMBOL(diag_stat_inc);
+
+void diag_stat_inc_norecursion(enum diag_stat_enum nr)
+{
+       this_cpu_inc(diag_stat.counter[nr]);
+       trace_diagnose_norecursion(diag_map[nr].code);
+}
+EXPORT_SYMBOL(diag_stat_inc_norecursion);
+
 /*
  * Diagnose 14: Input spool file manipulation
  */
index f7db48b61dcfe11d786f2b518d193b9aa4d3ac45..dbd40d448294dde8e2149b09d6931efb704fd65e 100644 (file)
@@ -377,11 +377,11 @@ int smp_vcpu_scheduled(int cpu)
 void smp_yield_cpu(int cpu)
 {
        if (MACHINE_HAS_DIAG9C) {
-               diag_stat_inc(DIAG_STAT_X09C);
+               diag_stat_inc_norecursion(DIAG_STAT_X09C);
                asm volatile("diag %0,0,0x9c"
                             : : "d" (pcpu_devices[cpu].address));
        } else if (MACHINE_HAS_DIAG44) {
-               diag_stat_inc(DIAG_STAT_X044);
+               diag_stat_inc_norecursion(DIAG_STAT_X044);
                asm volatile("diag 0,0,0x44");
        }
 }
diff --git a/arch/s390/kernel/trace.c b/arch/s390/kernel/trace.c
new file mode 100644 (file)
index 0000000..73239bb
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Tracepoint definitions for s390
+ *
+ * Copyright IBM Corp. 2015
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#include <linux/percpu.h>
+#define CREATE_TRACE_POINTS
+#include <asm/trace/diag.h>
+
+EXPORT_TRACEPOINT_SYMBOL(diagnose);
+
+static DEFINE_PER_CPU(unsigned int, diagnose_trace_depth);
+
+void trace_diagnose_norecursion(int diag_nr)
+{
+       unsigned long flags;
+       unsigned int *depth;
+
+       local_irq_save(flags);
+       depth = this_cpu_ptr(&diagnose_trace_depth);
+       if (*depth == 0) {
+               (*depth)++;
+               trace_diagnose(diag_nr);
+               (*depth)--;
+       }
+       local_irq_restore(flags);
+}