aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2015-08-20 11:28:44 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2015-10-14 08:32:06 -0400
commit1ec2772e0c3ca3159035c03165355e355efc326b (patch)
tree469be3ba9032d367e4a796d6a31b25ccaab0d06a
parentacdc9fc9a8121ce2ebcd7533bd72852c20b353f3 (diff)
s390/diag: add a statistic for diagnose calls
Introduce /sys/debug/kernel/diag_stat with a statistic how many diagnose calls have been done by each CPU in the system. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/hypfs/hypfs_diag.c10
-rw-r--r--arch/s390/hypfs/hypfs_diag0c.c2
-rw-r--r--arch/s390/hypfs/hypfs_sprp.c9
-rw-r--r--arch/s390/hypfs/hypfs_vm.c2
-rw-r--r--arch/s390/include/asm/appldata.h2
-rw-r--r--arch/s390/include/asm/diag.h37
-rw-r--r--arch/s390/include/asm/kvm_para.h67
-rw-r--r--arch/s390/kernel/cpcmd.c2
-rw-r--r--arch/s390/kernel/diag.c116
-rw-r--r--arch/s390/kernel/early.c3
-rw-r--r--arch/s390/kernel/ipl.c9
-rw-r--r--arch/s390/kernel/processor.c5
-rw-r--r--arch/s390/kernel/smp.c8
-rw-r--r--arch/s390/mm/extmem.c3
-rw-r--r--arch/s390/mm/fault.c3
-rw-r--r--drivers/s390/block/dasd_diag.c2
-rw-r--r--drivers/s390/char/diag_ftp.c2
-rw-r--r--drivers/s390/virtio/virtio_ccw.c15
-rw-r--r--drivers/watchdog/diag288_wdt.c4
19 files changed, 282 insertions, 19 deletions
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index 5eeffeefae06..045035796ca7 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -15,6 +15,7 @@
15#include <linux/string.h> 15#include <linux/string.h>
16#include <linux/vmalloc.h> 16#include <linux/vmalloc.h>
17#include <linux/mm.h> 17#include <linux/mm.h>
18#include <asm/diag.h>
18#include <asm/ebcdic.h> 19#include <asm/ebcdic.h>
19#include "hypfs.h" 20#include "hypfs.h"
20 21
@@ -336,7 +337,7 @@ static inline __u64 phys_cpu__ctidx(enum diag204_format type, void *hdr)
336 337
337/* Diagnose 204 functions */ 338/* Diagnose 204 functions */
338 339
339static int diag204(unsigned long subcode, unsigned long size, void *addr) 340static inline int __diag204(unsigned long subcode, unsigned long size, void *addr)
340{ 341{
341 register unsigned long _subcode asm("0") = subcode; 342 register unsigned long _subcode asm("0") = subcode;
342 register unsigned long _size asm("1") = size; 343 register unsigned long _size asm("1") = size;
@@ -351,6 +352,12 @@ static int diag204(unsigned long subcode, unsigned long size, void *addr)
351 return _size; 352 return _size;
352} 353}
353 354
355static int diag204(unsigned long subcode, unsigned long size, void *addr)
356{
357 diag_stat_inc(DIAG_STAT_X204);
358 return __diag204(subcode, size, addr);
359}
360
354/* 361/*
355 * For the old diag subcode 4 with simple data format we have to use real 362 * For the old diag subcode 4 with simple data format we have to use real
356 * memory. If we use subcode 6 or 7 with extended data format, we can (and 363 * memory. If we use subcode 6 or 7 with extended data format, we can (and
@@ -505,6 +512,7 @@ static int diag224(void *ptr)
505{ 512{
506 int rc = -EOPNOTSUPP; 513 int rc = -EOPNOTSUPP;
507 514
515 diag_stat_inc(DIAG_STAT_X224);
508 asm volatile( 516 asm volatile(
509 " diag %1,%2,0x224\n" 517 " diag %1,%2,0x224\n"
510 "0: lhi %0,0x0\n" 518 "0: lhi %0,0x0\n"
diff --git a/arch/s390/hypfs/hypfs_diag0c.c b/arch/s390/hypfs/hypfs_diag0c.c
index 24c747a0fcc3..0f1927cbba31 100644
--- a/arch/s390/hypfs/hypfs_diag0c.c
+++ b/arch/s390/hypfs/hypfs_diag0c.c
@@ -8,6 +8,7 @@
8 8
9#include <linux/slab.h> 9#include <linux/slab.h>
10#include <linux/cpu.h> 10#include <linux/cpu.h>
11#include <asm/diag.h>
11#include <asm/hypfs.h> 12#include <asm/hypfs.h>
12#include "hypfs.h" 13#include "hypfs.h"
13 14
@@ -18,6 +19,7 @@
18 */ 19 */
19static void diag0c(struct hypfs_diag0c_entry *entry) 20static void diag0c(struct hypfs_diag0c_entry *entry)
20{ 21{
22 diag_stat_inc(DIAG_STAT_X00C);
21 asm volatile ( 23 asm volatile (
22 " sam31\n" 24 " sam31\n"
23 " diag %0,%0,0x0c\n" 25 " diag %0,%0,0x0c\n"
diff --git a/arch/s390/hypfs/hypfs_sprp.c b/arch/s390/hypfs/hypfs_sprp.c
index dd42a26d049d..c9e5c72f78bd 100644
--- a/arch/s390/hypfs/hypfs_sprp.c
+++ b/arch/s390/hypfs/hypfs_sprp.c
@@ -13,6 +13,7 @@
13#include <linux/types.h> 13#include <linux/types.h>
14#include <linux/uaccess.h> 14#include <linux/uaccess.h>
15#include <asm/compat.h> 15#include <asm/compat.h>
16#include <asm/diag.h>
16#include <asm/sclp.h> 17#include <asm/sclp.h>
17#include "hypfs.h" 18#include "hypfs.h"
18 19
@@ -22,7 +23,7 @@
22 23
23#define DIAG304_CMD_MAX 2 24#define DIAG304_CMD_MAX 2
24 25
25static unsigned long hypfs_sprp_diag304(void *data, unsigned long cmd) 26static inline unsigned long __hypfs_sprp_diag304(void *data, unsigned long cmd)
26{ 27{
27 register unsigned long _data asm("2") = (unsigned long) data; 28 register unsigned long _data asm("2") = (unsigned long) data;
28 register unsigned long _rc asm("3"); 29 register unsigned long _rc asm("3");
@@ -34,6 +35,12 @@ static unsigned long hypfs_sprp_diag304(void *data, unsigned long cmd)
34 return _rc; 35 return _rc;
35} 36}
36 37
38static unsigned long hypfs_sprp_diag304(void *data, unsigned long cmd)
39{
40 diag_stat_inc(DIAG_STAT_X304);
41 return __hypfs_sprp_diag304(data, cmd);
42}
43
37static void hypfs_sprp_free(const void *data) 44static void hypfs_sprp_free(const void *data)
38{ 45{
39 free_page((unsigned long) data); 46 free_page((unsigned long) data);
diff --git a/arch/s390/hypfs/hypfs_vm.c b/arch/s390/hypfs/hypfs_vm.c
index afbe07907c10..44feac38ccfc 100644
--- a/arch/s390/hypfs/hypfs_vm.c
+++ b/arch/s390/hypfs/hypfs_vm.c
@@ -9,6 +9,7 @@
9#include <linux/errno.h> 9#include <linux/errno.h>
10#include <linux/string.h> 10#include <linux/string.h>
11#include <linux/vmalloc.h> 11#include <linux/vmalloc.h>
12#include <asm/diag.h>
12#include <asm/ebcdic.h> 13#include <asm/ebcdic.h>
13#include <asm/timex.h> 14#include <asm/timex.h>
14#include "hypfs.h" 15#include "hypfs.h"
@@ -66,6 +67,7 @@ static int diag2fc(int size, char* query, void *addr)
66 memset(parm_list.aci_grp, 0x40, NAME_LEN); 67 memset(parm_list.aci_grp, 0x40, NAME_LEN);
67 rc = -1; 68 rc = -1;
68 69
70 diag_stat_inc(DIAG_STAT_X2FC);
69 asm volatile( 71 asm volatile(
70 " diag %0,%1,0x2fc\n" 72 " diag %0,%1,0x2fc\n"
71 "0:\n" 73 "0:\n"
diff --git a/arch/s390/include/asm/appldata.h b/arch/s390/include/asm/appldata.h
index 16887c5fd989..a6263d4e8e56 100644
--- a/arch/s390/include/asm/appldata.h
+++ b/arch/s390/include/asm/appldata.h
@@ -7,6 +7,7 @@
7#ifndef _ASM_S390_APPLDATA_H 7#ifndef _ASM_S390_APPLDATA_H
8#define _ASM_S390_APPLDATA_H 8#define _ASM_S390_APPLDATA_H
9 9
10#include <asm/diag.h>
10#include <asm/io.h> 11#include <asm/io.h>
11 12
12#define APPLDATA_START_INTERVAL_REC 0x80 13#define APPLDATA_START_INTERVAL_REC 0x80
@@ -53,6 +54,7 @@ static inline int appldata_asm(struct appldata_product_id *id,
53 parm_list.buffer_length = length; 54 parm_list.buffer_length = length;
54 parm_list.product_id_addr = (unsigned long) id; 55 parm_list.product_id_addr = (unsigned long) id;
55 parm_list.buffer_addr = virt_to_phys(buffer); 56 parm_list.buffer_addr = virt_to_phys(buffer);
57 diag_stat_inc(DIAG_STAT_X0DC);
56 asm volatile( 58 asm volatile(
57 " diag %1,%0,0xdc" 59 " diag %1,%0,0xdc"
58 : "=d" (ry) 60 : "=d" (ry)
diff --git a/arch/s390/include/asm/diag.h b/arch/s390/include/asm/diag.h
index 7e91c58072e2..e423cfcaf77d 100644
--- a/arch/s390/include/asm/diag.h
+++ b/arch/s390/include/asm/diag.h
@@ -8,6 +8,42 @@
8#ifndef _ASM_S390_DIAG_H 8#ifndef _ASM_S390_DIAG_H
9#define _ASM_S390_DIAG_H 9#define _ASM_S390_DIAG_H
10 10
11#include <linux/percpu.h>
12
13enum diag_stat_enum {
14 DIAG_STAT_X008,
15 DIAG_STAT_X00C,
16 DIAG_STAT_X010,
17 DIAG_STAT_X014,
18 DIAG_STAT_X044,
19 DIAG_STAT_X064,
20 DIAG_STAT_X09C,
21 DIAG_STAT_X0DC,
22 DIAG_STAT_X204,
23 DIAG_STAT_X210,
24 DIAG_STAT_X224,
25 DIAG_STAT_X250,
26 DIAG_STAT_X258,
27 DIAG_STAT_X288,
28 DIAG_STAT_X2C4,
29 DIAG_STAT_X2FC,
30 DIAG_STAT_X304,
31 DIAG_STAT_X308,
32 DIAG_STAT_X500,
33 NR_DIAG_STAT
34};
35
36struct diag_stat {
37 unsigned int counter[NR_DIAG_STAT];
38};
39
40DECLARE_PER_CPU(struct diag_stat, diag_stat);
41
42static inline void diag_stat_inc(enum diag_stat_enum nr)
43{
44 this_cpu_inc(diag_stat.counter[nr]);
45}
46
11/* 47/*
12 * Diagnose 10: Release page range 48 * Diagnose 10: Release page range
13 */ 49 */
@@ -18,6 +54,7 @@ static inline void diag10_range(unsigned long start_pfn, unsigned long num_pfn)
18 start_addr = start_pfn << PAGE_SHIFT; 54 start_addr = start_pfn << PAGE_SHIFT;
19 end_addr = (start_pfn + num_pfn - 1) << PAGE_SHIFT; 55 end_addr = (start_pfn + num_pfn - 1) << PAGE_SHIFT;
20 56
57 diag_stat_inc(DIAG_STAT_X010);
21 asm volatile( 58 asm volatile(
22 "0: diag %0,%1,0x10\n" 59 "0: diag %0,%1,0x10\n"
23 "1:\n" 60 "1:\n"
diff --git a/arch/s390/include/asm/kvm_para.h b/arch/s390/include/asm/kvm_para.h
index e0f842308a68..41393052ac57 100644
--- a/arch/s390/include/asm/kvm_para.h
+++ b/arch/s390/include/asm/kvm_para.h
@@ -27,10 +27,9 @@
27#define __S390_KVM_PARA_H 27#define __S390_KVM_PARA_H
28 28
29#include <uapi/asm/kvm_para.h> 29#include <uapi/asm/kvm_para.h>
30#include <asm/diag.h>
30 31
31 32static inline long __kvm_hypercall0(unsigned long nr)
32
33static inline long kvm_hypercall0(unsigned long nr)
34{ 33{
35 register unsigned long __nr asm("1") = nr; 34 register unsigned long __nr asm("1") = nr;
36 register long __rc asm("2"); 35 register long __rc asm("2");
@@ -40,7 +39,13 @@ static inline long kvm_hypercall0(unsigned long nr)
40 return __rc; 39 return __rc;
41} 40}
42 41
43static inline long kvm_hypercall1(unsigned long nr, unsigned long p1) 42static inline long kvm_hypercall0(unsigned long nr)
43{
44 diag_stat_inc(DIAG_STAT_X500);
45 return __kvm_hypercall0(nr);
46}
47
48static inline long __kvm_hypercall1(unsigned long nr, unsigned long p1)
44{ 49{
45 register unsigned long __nr asm("1") = nr; 50 register unsigned long __nr asm("1") = nr;
46 register unsigned long __p1 asm("2") = p1; 51 register unsigned long __p1 asm("2") = p1;
@@ -51,7 +56,13 @@ static inline long kvm_hypercall1(unsigned long nr, unsigned long p1)
51 return __rc; 56 return __rc;
52} 57}
53 58
54static inline long kvm_hypercall2(unsigned long nr, unsigned long p1, 59static inline long kvm_hypercall1(unsigned long nr, unsigned long p1)
60{
61 diag_stat_inc(DIAG_STAT_X500);
62 return __kvm_hypercall1(nr, p1);
63}
64
65static inline long __kvm_hypercall2(unsigned long nr, unsigned long p1,
55 unsigned long p2) 66 unsigned long p2)
56{ 67{
57 register unsigned long __nr asm("1") = nr; 68 register unsigned long __nr asm("1") = nr;
@@ -65,7 +76,14 @@ static inline long kvm_hypercall2(unsigned long nr, unsigned long p1,
65 return __rc; 76 return __rc;
66} 77}
67 78
68static inline long kvm_hypercall3(unsigned long nr, unsigned long p1, 79static inline long kvm_hypercall2(unsigned long nr, unsigned long p1,
80 unsigned long p2)
81{
82 diag_stat_inc(DIAG_STAT_X500);
83 return __kvm_hypercall2(nr, p1, p2);
84}
85
86static inline long __kvm_hypercall3(unsigned long nr, unsigned long p1,
69 unsigned long p2, unsigned long p3) 87 unsigned long p2, unsigned long p3)
70{ 88{
71 register unsigned long __nr asm("1") = nr; 89 register unsigned long __nr asm("1") = nr;
@@ -80,8 +98,14 @@ static inline long kvm_hypercall3(unsigned long nr, unsigned long p1,
80 return __rc; 98 return __rc;
81} 99}
82 100
101static inline long kvm_hypercall3(unsigned long nr, unsigned long p1,
102 unsigned long p2, unsigned long p3)
103{
104 diag_stat_inc(DIAG_STAT_X500);
105 return __kvm_hypercall3(nr, p1, p2, p3);
106}
83 107
84static inline long kvm_hypercall4(unsigned long nr, unsigned long p1, 108static inline long __kvm_hypercall4(unsigned long nr, unsigned long p1,
85 unsigned long p2, unsigned long p3, 109 unsigned long p2, unsigned long p3,
86 unsigned long p4) 110 unsigned long p4)
87{ 111{
@@ -98,7 +122,15 @@ static inline long kvm_hypercall4(unsigned long nr, unsigned long p1,
98 return __rc; 122 return __rc;
99} 123}
100 124
101static inline long kvm_hypercall5(unsigned long nr, unsigned long p1, 125static inline long kvm_hypercall4(unsigned long nr, unsigned long p1,
126 unsigned long p2, unsigned long p3,
127 unsigned long p4)
128{
129 diag_stat_inc(DIAG_STAT_X500);
130 return __kvm_hypercall4(nr, p1, p2, p3, p4);
131}
132
133static inline long __kvm_hypercall5(unsigned long nr, unsigned long p1,
102 unsigned long p2, unsigned long p3, 134 unsigned long p2, unsigned long p3,
103 unsigned long p4, unsigned long p5) 135 unsigned long p4, unsigned long p5)
104{ 136{
@@ -116,7 +148,15 @@ static inline long kvm_hypercall5(unsigned long nr, unsigned long p1,
116 return __rc; 148 return __rc;
117} 149}
118 150
119static inline long kvm_hypercall6(unsigned long nr, unsigned long p1, 151static inline long kvm_hypercall5(unsigned long nr, unsigned long p1,
152 unsigned long p2, unsigned long p3,
153 unsigned long p4, unsigned long p5)
154{
155 diag_stat_inc(DIAG_STAT_X500);
156 return __kvm_hypercall5(nr, p1, p2, p3, p4, p5);
157}
158
159static inline long __kvm_hypercall6(unsigned long nr, unsigned long p1,
120 unsigned long p2, unsigned long p3, 160 unsigned long p2, unsigned long p3,
121 unsigned long p4, unsigned long p5, 161 unsigned long p4, unsigned long p5,
122 unsigned long p6) 162 unsigned long p6)
@@ -137,6 +177,15 @@ static inline long kvm_hypercall6(unsigned long nr, unsigned long p1,
137 return __rc; 177 return __rc;
138} 178}
139 179
180static inline long kvm_hypercall6(unsigned long nr, unsigned long p1,
181 unsigned long p2, unsigned long p3,
182 unsigned long p4, unsigned long p5,
183 unsigned long p6)
184{
185 diag_stat_inc(DIAG_STAT_X500);
186 return __kvm_hypercall6(nr, p1, p2, p3, p4, p5, p6);
187}
188
140/* kvm on s390 is always paravirtualization enabled */ 189/* kvm on s390 is always paravirtualization enabled */
141static inline int kvm_para_available(void) 190static inline int kvm_para_available(void)
142{ 191{
diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c
index 199ec92ef4fe..7f768914fb4f 100644
--- a/arch/s390/kernel/cpcmd.c
+++ b/arch/s390/kernel/cpcmd.c
@@ -14,6 +14,7 @@
14#include <linux/spinlock.h> 14#include <linux/spinlock.h>
15#include <linux/stddef.h> 15#include <linux/stddef.h>
16#include <linux/string.h> 16#include <linux/string.h>
17#include <asm/diag.h>
17#include <asm/ebcdic.h> 18#include <asm/ebcdic.h>
18#include <asm/cpcmd.h> 19#include <asm/cpcmd.h>
19#include <asm/io.h> 20#include <asm/io.h>
@@ -70,6 +71,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
70 memcpy(cpcmd_buf, cmd, cmdlen); 71 memcpy(cpcmd_buf, cmd, cmdlen);
71 ASCEBC(cpcmd_buf, cmdlen); 72 ASCEBC(cpcmd_buf, cmdlen);
72 73
74 diag_stat_inc(DIAG_STAT_X008);
73 if (response) { 75 if (response) {
74 memset(response, 0, rlen); 76 memset(response, 0, rlen);
75 response_len = rlen; 77 response_len = rlen;
diff --git a/arch/s390/kernel/diag.c b/arch/s390/kernel/diag.c
index 2f69243bf700..4ddb5200ddf0 100644
--- a/arch/s390/kernel/diag.c
+++ b/arch/s390/kernel/diag.c
@@ -6,12 +6,119 @@
6 */ 6 */
7 7
8#include <linux/module.h> 8#include <linux/module.h>
9#include <linux/cpu.h>
10#include <linux/seq_file.h>
11#include <linux/debugfs.h>
9#include <asm/diag.h> 12#include <asm/diag.h>
10 13
14DEFINE_PER_CPU(struct diag_stat, diag_stat);
15EXPORT_PER_CPU_SYMBOL(diag_stat);
16
17struct diag_desc {
18 int code;
19 char *name;
20};
21
22static const struct diag_desc diag_map[NR_DIAG_STAT] = {
23 [DIAG_STAT_X008] = { .code = 0x008, .name = "Console Function" },
24 [DIAG_STAT_X00C] = { .code = 0x00c, .name = "Pseudo Timer" },
25 [DIAG_STAT_X010] = { .code = 0x010, .name = "Release Pages" },
26 [DIAG_STAT_X014] = { .code = 0x014, .name = "Spool File Services" },
27 [DIAG_STAT_X044] = { .code = 0x044, .name = "Voluntary Timeslice End" },
28 [DIAG_STAT_X064] = { .code = 0x064, .name = "NSS Manipulation" },
29 [DIAG_STAT_X09C] = { .code = 0x09c, .name = "Relinquish Timeslice" },
30 [DIAG_STAT_X0DC] = { .code = 0x0dc, .name = "Appldata Control" },
31 [DIAG_STAT_X204] = { .code = 0x204, .name = "Logical-CPU Utilization" },
32 [DIAG_STAT_X210] = { .code = 0x210, .name = "Device Information" },
33 [DIAG_STAT_X224] = { .code = 0x224, .name = "EBCDIC-Name Table" },
34 [DIAG_STAT_X250] = { .code = 0x250, .name = "Block I/O" },
35 [DIAG_STAT_X258] = { .code = 0x258, .name = "Page-Reference Services" },
36 [DIAG_STAT_X288] = { .code = 0x288, .name = "Time Bomb" },
37 [DIAG_STAT_X2C4] = { .code = 0x2c4, .name = "FTP Services" },
38 [DIAG_STAT_X2FC] = { .code = 0x2fc, .name = "Guest Performance Data" },
39 [DIAG_STAT_X304] = { .code = 0x304, .name = "Partition-Resource Service" },
40 [DIAG_STAT_X308] = { .code = 0x308, .name = "List-Directed IPL" },
41 [DIAG_STAT_X500] = { .code = 0x500, .name = "Virtio Service" },
42};
43
44static int show_diag_stat(struct seq_file *m, void *v)
45{
46 struct diag_stat *stat;
47 unsigned long n = (unsigned long) v - 1;
48 int cpu, prec, tmp;
49
50 get_online_cpus();
51 if (n == 0) {
52 seq_puts(m, " ");
53
54 for_each_online_cpu(cpu) {
55 prec = 10;
56 for (tmp = 10; cpu >= tmp; tmp *= 10)
57 prec--;
58 seq_printf(m, "%*s%d", prec, "CPU", cpu);
59 }
60 seq_putc(m, '\n');
61 } else if (n <= NR_DIAG_STAT) {
62 seq_printf(m, "diag %03x:", diag_map[n-1].code);
63 for_each_online_cpu(cpu) {
64 stat = &per_cpu(diag_stat, cpu);
65 seq_printf(m, " %10u", stat->counter[n-1]);
66 }
67 seq_printf(m, " %s\n", diag_map[n-1].name);
68 }
69 put_online_cpus();
70 return 0;
71}
72
73static void *show_diag_stat_start(struct seq_file *m, loff_t *pos)
74{
75 return *pos <= nr_cpu_ids ? (void *)((unsigned long) *pos + 1) : NULL;
76}
77
78static void *show_diag_stat_next(struct seq_file *m, void *v, loff_t *pos)
79{
80 ++*pos;
81 return show_diag_stat_start(m, pos);
82}
83
84static void show_diag_stat_stop(struct seq_file *m, void *v)
85{
86}
87
88static const struct seq_operations show_diag_stat_sops = {
89 .start = show_diag_stat_start,
90 .next = show_diag_stat_next,
91 .stop = show_diag_stat_stop,
92 .show = show_diag_stat,
93};
94
95static int show_diag_stat_open(struct inode *inode, struct file *file)
96{
97 return seq_open(file, &show_diag_stat_sops);
98}
99
100static const struct file_operations show_diag_stat_fops = {
101 .open = show_diag_stat_open,
102 .read = seq_read,
103 .llseek = seq_lseek,
104 .release = seq_release,
105};
106
107
108static int __init show_diag_stat_init(void)
109{
110 debugfs_create_file("diag_stat", 0400, NULL, NULL,
111 &show_diag_stat_fops);
112 return 0;
113}
114
115device_initcall(show_diag_stat_init);
116
11/* 117/*
12 * Diagnose 14: Input spool file manipulation 118 * Diagnose 14: Input spool file manipulation
13 */ 119 */
14int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode) 120static inline int __diag14(unsigned long rx, unsigned long ry1,
121 unsigned long subcode)
15{ 122{
16 register unsigned long _ry1 asm("2") = ry1; 123 register unsigned long _ry1 asm("2") = ry1;
17 register unsigned long _ry2 asm("3") = subcode; 124 register unsigned long _ry2 asm("3") = subcode;
@@ -29,6 +136,12 @@ int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode)
29 136
30 return rc; 137 return rc;
31} 138}
139
140int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode)
141{
142 diag_stat_inc(DIAG_STAT_X014);
143 return __diag14(rx, ry1, subcode);
144}
32EXPORT_SYMBOL(diag14); 145EXPORT_SYMBOL(diag14);
33 146
34/* 147/*
@@ -48,6 +161,7 @@ int diag210(struct diag210 *addr)
48 spin_lock_irqsave(&diag210_lock, flags); 161 spin_lock_irqsave(&diag210_lock, flags);
49 diag210_tmp = *addr; 162 diag210_tmp = *addr;
50 163
164 diag_stat_inc(DIAG_STAT_X210);
51 asm volatile( 165 asm volatile(
52 " lhi %0,-1\n" 166 " lhi %0,-1\n"
53 " sam31\n" 167 " sam31\n"
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 549a73a4b543..311a2d6d48e4 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -17,6 +17,7 @@
17#include <linux/pfn.h> 17#include <linux/pfn.h>
18#include <linux/uaccess.h> 18#include <linux/uaccess.h>
19#include <linux/kernel.h> 19#include <linux/kernel.h>
20#include <asm/diag.h>
20#include <asm/ebcdic.h> 21#include <asm/ebcdic.h>
21#include <asm/ipl.h> 22#include <asm/ipl.h>
22#include <asm/lowcore.h> 23#include <asm/lowcore.h>
@@ -286,6 +287,7 @@ static __init void detect_diag9c(void)
286 int rc; 287 int rc;
287 288
288 cpu_address = stap(); 289 cpu_address = stap();
290 diag_stat_inc(DIAG_STAT_X09C);
289 asm volatile( 291 asm volatile(
290 " diag %2,0,0x9c\n" 292 " diag %2,0,0x9c\n"
291 "0: la %0,0\n" 293 "0: la %0,0\n"
@@ -300,6 +302,7 @@ static __init void detect_diag44(void)
300{ 302{
301 int rc; 303 int rc;
302 304
305 diag_stat_inc(DIAG_STAT_X044);
303 asm volatile( 306 asm volatile(
304 " diag 0,0,0x44\n" 307 " diag 0,0,0x44\n"
305 "0: la %0,0\n" 308 "0: la %0,0\n"
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 52fbef91d1d9..f6d8acd7e136 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -17,6 +17,7 @@
17#include <linux/gfp.h> 17#include <linux/gfp.h>
18#include <linux/crash_dump.h> 18#include <linux/crash_dump.h>
19#include <linux/debug_locks.h> 19#include <linux/debug_locks.h>
20#include <asm/diag.h>
20#include <asm/ipl.h> 21#include <asm/ipl.h>
21#include <asm/smp.h> 22#include <asm/smp.h>
22#include <asm/setup.h> 23#include <asm/setup.h>
@@ -165,7 +166,7 @@ static struct ipl_parameter_block *dump_block_ccw;
165 166
166static struct sclp_ipl_info sclp_ipl_info; 167static struct sclp_ipl_info sclp_ipl_info;
167 168
168int diag308(unsigned long subcode, void *addr) 169static inline int __diag308(unsigned long subcode, void *addr)
169{ 170{
170 register unsigned long _addr asm("0") = (unsigned long) addr; 171 register unsigned long _addr asm("0") = (unsigned long) addr;
171 register unsigned long _rc asm("1") = 0; 172 register unsigned long _rc asm("1") = 0;
@@ -178,6 +179,12 @@ int diag308(unsigned long subcode, void *addr)
178 : "d" (subcode) : "cc", "memory"); 179 : "d" (subcode) : "cc", "memory");
179 return _rc; 180 return _rc;
180} 181}
182
183int diag308(unsigned long subcode, void *addr)
184{
185 diag_stat_inc(DIAG_STAT_X308);
186 return __diag308(subcode, addr);
187}
181EXPORT_SYMBOL_GPL(diag308); 188EXPORT_SYMBOL_GPL(diag308);
182 189
183/* SYSFS */ 190/* SYSFS */
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c
index e6e077ae3990..7ce00e7a709a 100644
--- a/arch/s390/kernel/processor.c
+++ b/arch/s390/kernel/processor.c
@@ -11,6 +11,7 @@
11#include <linux/seq_file.h> 11#include <linux/seq_file.h>
12#include <linux/delay.h> 12#include <linux/delay.h>
13#include <linux/cpu.h> 13#include <linux/cpu.h>
14#include <asm/diag.h>
14#include <asm/elf.h> 15#include <asm/elf.h>
15#include <asm/lowcore.h> 16#include <asm/lowcore.h>
16#include <asm/param.h> 17#include <asm/param.h>
@@ -20,8 +21,10 @@ static DEFINE_PER_CPU(struct cpuid, cpu_id);
20 21
21void notrace cpu_relax(void) 22void notrace cpu_relax(void)
22{ 23{
23 if (!smp_cpu_mtid && MACHINE_HAS_DIAG44) 24 if (!smp_cpu_mtid && MACHINE_HAS_DIAG44) {
25 diag_stat_inc(DIAG_STAT_X044);
24 asm volatile("diag 0,0,0x44"); 26 asm volatile("diag 0,0,0x44");
27 }
25 barrier(); 28 barrier();
26} 29}
27EXPORT_SYMBOL(cpu_relax); 30EXPORT_SYMBOL(cpu_relax);
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index c6355e6f3fcc..f7db48b61dcf 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -33,6 +33,7 @@
33#include <linux/crash_dump.h> 33#include <linux/crash_dump.h>
34#include <linux/memblock.h> 34#include <linux/memblock.h>
35#include <asm/asm-offsets.h> 35#include <asm/asm-offsets.h>
36#include <asm/diag.h>
36#include <asm/switch_to.h> 37#include <asm/switch_to.h>
37#include <asm/facility.h> 38#include <asm/facility.h>
38#include <asm/ipl.h> 39#include <asm/ipl.h>
@@ -375,11 +376,14 @@ int smp_vcpu_scheduled(int cpu)
375 376
376void smp_yield_cpu(int cpu) 377void smp_yield_cpu(int cpu)
377{ 378{
378 if (MACHINE_HAS_DIAG9C) 379 if (MACHINE_HAS_DIAG9C) {
380 diag_stat_inc(DIAG_STAT_X09C);
379 asm volatile("diag %0,0,0x9c" 381 asm volatile("diag %0,0,0x9c"
380 : : "d" (pcpu_devices[cpu].address)); 382 : : "d" (pcpu_devices[cpu].address));
381 else if (MACHINE_HAS_DIAG44) 383 } else if (MACHINE_HAS_DIAG44) {
384 diag_stat_inc(DIAG_STAT_X044);
382 asm volatile("diag 0,0,0x44"); 385 asm volatile("diag 0,0,0x44");
386 }
383} 387}
384 388
385/* 389/*
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index 23c496957c22..18fccc303db7 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -18,6 +18,7 @@
18#include <linux/bootmem.h> 18#include <linux/bootmem.h>
19#include <linux/ctype.h> 19#include <linux/ctype.h>
20#include <linux/ioport.h> 20#include <linux/ioport.h>
21#include <asm/diag.h>
21#include <asm/page.h> 22#include <asm/page.h>
22#include <asm/pgtable.h> 23#include <asm/pgtable.h>
23#include <asm/ebcdic.h> 24#include <asm/ebcdic.h>
@@ -112,6 +113,7 @@ dcss_set_subcodes(void)
112 ry = DCSS_FINDSEGX; 113 ry = DCSS_FINDSEGX;
113 114
114 strcpy(name, "dummy"); 115 strcpy(name, "dummy");
116 diag_stat_inc(DIAG_STAT_X064);
115 asm volatile( 117 asm volatile(
116 " diag %0,%1,0x64\n" 118 " diag %0,%1,0x64\n"
117 "0: ipm %2\n" 119 "0: ipm %2\n"
@@ -205,6 +207,7 @@ dcss_diag(int *func, void *parameter,
205 ry = (unsigned long) *func; 207 ry = (unsigned long) *func;
206 208
207 /* 64-bit Diag x'64' new subcode, keep in 64-bit addressing mode */ 209 /* 64-bit Diag x'64' new subcode, keep in 64-bit addressing mode */
210 diag_stat_inc(DIAG_STAT_X064);
208 if (*func > DCSS_SEGEXT) 211 if (*func > DCSS_SEGEXT)
209 asm volatile( 212 asm volatile(
210 " diag %0,%1,0x64\n" 213 " diag %0,%1,0x64\n"
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index f985856a538b..77b3938d6bfa 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -30,6 +30,7 @@
30#include <linux/uaccess.h> 30#include <linux/uaccess.h>
31#include <linux/hugetlb.h> 31#include <linux/hugetlb.h>
32#include <asm/asm-offsets.h> 32#include <asm/asm-offsets.h>
33#include <asm/diag.h>
33#include <asm/pgtable.h> 34#include <asm/pgtable.h>
34#include <asm/irq.h> 35#include <asm/irq.h>
35#include <asm/mmu_context.h> 36#include <asm/mmu_context.h>
@@ -597,6 +598,7 @@ int pfault_init(void)
597 598
598 if (pfault_disable) 599 if (pfault_disable)
599 return -1; 600 return -1;
601 diag_stat_inc(DIAG_STAT_X258);
600 asm volatile( 602 asm volatile(
601 " diag %1,%0,0x258\n" 603 " diag %1,%0,0x258\n"
602 "0: j 2f\n" 604 "0: j 2f\n"
@@ -618,6 +620,7 @@ void pfault_fini(void)
618 620
619 if (pfault_disable) 621 if (pfault_disable)
620 return; 622 return;
623 diag_stat_inc(DIAG_STAT_X258);
621 asm volatile( 624 asm volatile(
622 " diag %0,0,0x258\n" 625 " diag %0,0,0x258\n"
623 "0:\n" 626 "0:\n"
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index c062f1620c58..cb61f300f8b5 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -21,6 +21,7 @@
21 21
22#include <asm/dasd.h> 22#include <asm/dasd.h>
23#include <asm/debug.h> 23#include <asm/debug.h>
24#include <asm/diag.h>
24#include <asm/ebcdic.h> 25#include <asm/ebcdic.h>
25#include <asm/io.h> 26#include <asm/io.h>
26#include <asm/irq.h> 27#include <asm/irq.h>
@@ -76,6 +77,7 @@ static inline int dia250(void *iob, int cmd)
76 int rc; 77 int rc;
77 78
78 rc = 3; 79 rc = 3;
80 diag_stat_inc(DIAG_STAT_X250);
79 asm volatile( 81 asm volatile(
80 " diag 2,%2,0x250\n" 82 " diag 2,%2,0x250\n"
81 "0: ipm %0\n" 83 "0: ipm %0\n"
diff --git a/drivers/s390/char/diag_ftp.c b/drivers/s390/char/diag_ftp.c
index 12db8db04cdd..a5ccbf6f0d36 100644
--- a/drivers/s390/char/diag_ftp.c
+++ b/drivers/s390/char/diag_ftp.c
@@ -15,6 +15,7 @@
15#include <linux/wait.h> 15#include <linux/wait.h>
16#include <linux/string.h> 16#include <linux/string.h>
17#include <asm/ctl_reg.h> 17#include <asm/ctl_reg.h>
18#include <asm/diag.h>
18 19
19#include "hmcdrv_ftp.h" 20#include "hmcdrv_ftp.h"
20#include "diag_ftp.h" 21#include "diag_ftp.h"
@@ -102,6 +103,7 @@ static int diag_ftp_2c4(struct diag_ftp_ldfpl *fpl,
102{ 103{
103 int rc; 104 int rc;
104 105
106 diag_stat_inc(DIAG_STAT_X2C4);
105 asm volatile( 107 asm volatile(
106 " diag %[addr],%[cmd],0x2c4\n" 108 " diag %[addr],%[cmd],0x2c4\n"
107 "0: j 2f\n" 109 "0: j 2f\n"
diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
index e9fae30fafda..b2a1a81e6fc8 100644
--- a/drivers/s390/virtio/virtio_ccw.c
+++ b/drivers/s390/virtio/virtio_ccw.c
@@ -28,6 +28,7 @@
28#include <linux/io.h> 28#include <linux/io.h>
29#include <linux/kvm_para.h> 29#include <linux/kvm_para.h>
30#include <linux/notifier.h> 30#include <linux/notifier.h>
31#include <asm/diag.h>
31#include <asm/setup.h> 32#include <asm/setup.h>
32#include <asm/irq.h> 33#include <asm/irq.h>
33#include <asm/cio.h> 34#include <asm/cio.h>
@@ -366,9 +367,9 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev,
366 kfree(thinint_area); 367 kfree(thinint_area);
367} 368}
368 369
369static inline long do_kvm_notify(struct subchannel_id schid, 370static inline long __do_kvm_notify(struct subchannel_id schid,
370 unsigned long queue_index, 371 unsigned long queue_index,
371 long cookie) 372 long cookie)
372{ 373{
373 register unsigned long __nr asm("1") = KVM_S390_VIRTIO_CCW_NOTIFY; 374 register unsigned long __nr asm("1") = KVM_S390_VIRTIO_CCW_NOTIFY;
374 register struct subchannel_id __schid asm("2") = schid; 375 register struct subchannel_id __schid asm("2") = schid;
@@ -383,6 +384,14 @@ static inline long do_kvm_notify(struct subchannel_id schid,
383 return __rc; 384 return __rc;
384} 385}
385 386
387static inline long do_kvm_notify(struct subchannel_id schid,
388 unsigned long queue_index,
389 long cookie)
390{
391 diag_stat_inc(DIAG_STAT_X500);
392 return __do_kvm_notify(schid, queue_index, cookie);
393}
394
386static bool virtio_ccw_kvm_notify(struct virtqueue *vq) 395static bool virtio_ccw_kvm_notify(struct virtqueue *vq)
387{ 396{
388 struct virtio_ccw_vq_info *info = vq->priv; 397 struct virtio_ccw_vq_info *info = vq->priv;
diff --git a/drivers/watchdog/diag288_wdt.c b/drivers/watchdog/diag288_wdt.c
index a9a5210143ae..3db9d0e0673d 100644
--- a/drivers/watchdog/diag288_wdt.c
+++ b/drivers/watchdog/diag288_wdt.c
@@ -29,6 +29,7 @@
29#include <linux/watchdog.h> 29#include <linux/watchdog.h>
30#include <linux/suspend.h> 30#include <linux/suspend.h>
31#include <asm/ebcdic.h> 31#include <asm/ebcdic.h>
32#include <asm/diag.h>
32#include <linux/io.h> 33#include <linux/io.h>
33#include <linux/uaccess.h> 34#include <linux/uaccess.h>
34 35
@@ -94,12 +95,14 @@ static int __diag288(unsigned int func, unsigned int timeout,
94static int __diag288_vm(unsigned int func, unsigned int timeout, 95static int __diag288_vm(unsigned int func, unsigned int timeout,
95 char *cmd, size_t len) 96 char *cmd, size_t len)
96{ 97{
98 diag_stat_inc(DIAG_STAT_X288);
97 return __diag288(func, timeout, virt_to_phys(cmd), len); 99 return __diag288(func, timeout, virt_to_phys(cmd), len);
98} 100}
99 101
100static int __diag288_lpar(unsigned int func, unsigned int timeout, 102static int __diag288_lpar(unsigned int func, unsigned int timeout,
101 unsigned long action) 103 unsigned long action)
102{ 104{
105 diag_stat_inc(DIAG_STAT_X288);
103 return __diag288(func, timeout, action, 0); 106 return __diag288(func, timeout, action, 0);
104} 107}
105 108
@@ -141,6 +144,7 @@ static int wdt_stop(struct watchdog_device *dev)
141{ 144{
142 int ret; 145 int ret;
143 146
147 diag_stat_inc(DIAG_STAT_X288);
144 ret = __diag288(WDT_FUNC_CANCEL, 0, 0, 0); 148 ret = __diag288(WDT_FUNC_CANCEL, 0, 0, 0);
145 return ret; 149 return ret;
146} 150}