Commit 1ec2772e authored by Martin Schwidefsky's avatar Martin Schwidefsky

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: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent acdc9fc9
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/diag.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include "hypfs.h" #include "hypfs.h"
...@@ -336,7 +337,7 @@ static inline __u64 phys_cpu__ctidx(enum diag204_format type, void *hdr) ...@@ -336,7 +337,7 @@ static inline __u64 phys_cpu__ctidx(enum diag204_format type, void *hdr)
/* Diagnose 204 functions */ /* Diagnose 204 functions */
static int diag204(unsigned long subcode, unsigned long size, void *addr) static inline int __diag204(unsigned long subcode, unsigned long size, void *addr)
{ {
register unsigned long _subcode asm("0") = subcode; register unsigned long _subcode asm("0") = subcode;
register unsigned long _size asm("1") = size; register unsigned long _size asm("1") = size;
...@@ -351,6 +352,12 @@ static int diag204(unsigned long subcode, unsigned long size, void *addr) ...@@ -351,6 +352,12 @@ static int diag204(unsigned long subcode, unsigned long size, void *addr)
return _size; return _size;
} }
static int diag204(unsigned long subcode, unsigned long size, void *addr)
{
diag_stat_inc(DIAG_STAT_X204);
return __diag204(subcode, size, addr);
}
/* /*
* For the old diag subcode 4 with simple data format we have to use real * For the old diag subcode 4 with simple data format we have to use real
* memory. If we use subcode 6 or 7 with extended data format, we can (and * 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,6 +512,7 @@ static int diag224(void *ptr)
{ {
int rc = -EOPNOTSUPP; int rc = -EOPNOTSUPP;
diag_stat_inc(DIAG_STAT_X224);
asm volatile( asm volatile(
" diag %1,%2,0x224\n" " diag %1,%2,0x224\n"
"0: lhi %0,0x0\n" "0: lhi %0,0x0\n"
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <asm/diag.h>
#include <asm/hypfs.h> #include <asm/hypfs.h>
#include "hypfs.h" #include "hypfs.h"
...@@ -18,6 +19,7 @@ ...@@ -18,6 +19,7 @@
*/ */
static void diag0c(struct hypfs_diag0c_entry *entry) static void diag0c(struct hypfs_diag0c_entry *entry)
{ {
diag_stat_inc(DIAG_STAT_X00C);
asm volatile ( asm volatile (
" sam31\n" " sam31\n"
" diag %0,%0,0x0c\n" " diag %0,%0,0x0c\n"
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <asm/compat.h> #include <asm/compat.h>
#include <asm/diag.h>
#include <asm/sclp.h> #include <asm/sclp.h>
#include "hypfs.h" #include "hypfs.h"
...@@ -22,7 +23,7 @@ ...@@ -22,7 +23,7 @@
#define DIAG304_CMD_MAX 2 #define DIAG304_CMD_MAX 2
static unsigned long hypfs_sprp_diag304(void *data, unsigned long cmd) static inline unsigned long __hypfs_sprp_diag304(void *data, unsigned long cmd)
{ {
register unsigned long _data asm("2") = (unsigned long) data; register unsigned long _data asm("2") = (unsigned long) data;
register unsigned long _rc asm("3"); register unsigned long _rc asm("3");
...@@ -34,6 +35,12 @@ static unsigned long hypfs_sprp_diag304(void *data, unsigned long cmd) ...@@ -34,6 +35,12 @@ static unsigned long hypfs_sprp_diag304(void *data, unsigned long cmd)
return _rc; return _rc;
} }
static unsigned long hypfs_sprp_diag304(void *data, unsigned long cmd)
{
diag_stat_inc(DIAG_STAT_X304);
return __hypfs_sprp_diag304(data, cmd);
}
static void hypfs_sprp_free(const void *data) static void hypfs_sprp_free(const void *data)
{ {
free_page((unsigned long) data); free_page((unsigned long) data);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <asm/diag.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include <asm/timex.h> #include <asm/timex.h>
#include "hypfs.h" #include "hypfs.h"
...@@ -66,6 +67,7 @@ static int diag2fc(int size, char* query, void *addr) ...@@ -66,6 +67,7 @@ static int diag2fc(int size, char* query, void *addr)
memset(parm_list.aci_grp, 0x40, NAME_LEN); memset(parm_list.aci_grp, 0x40, NAME_LEN);
rc = -1; rc = -1;
diag_stat_inc(DIAG_STAT_X2FC);
asm volatile( asm volatile(
" diag %0,%1,0x2fc\n" " diag %0,%1,0x2fc\n"
"0:\n" "0:\n"
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#ifndef _ASM_S390_APPLDATA_H #ifndef _ASM_S390_APPLDATA_H
#define _ASM_S390_APPLDATA_H #define _ASM_S390_APPLDATA_H
#include <asm/diag.h>
#include <asm/io.h> #include <asm/io.h>
#define APPLDATA_START_INTERVAL_REC 0x80 #define APPLDATA_START_INTERVAL_REC 0x80
...@@ -53,6 +54,7 @@ static inline int appldata_asm(struct appldata_product_id *id, ...@@ -53,6 +54,7 @@ static inline int appldata_asm(struct appldata_product_id *id,
parm_list.buffer_length = length; parm_list.buffer_length = length;
parm_list.product_id_addr = (unsigned long) id; parm_list.product_id_addr = (unsigned long) id;
parm_list.buffer_addr = virt_to_phys(buffer); parm_list.buffer_addr = virt_to_phys(buffer);
diag_stat_inc(DIAG_STAT_X0DC);
asm volatile( asm volatile(
" diag %1,%0,0xdc" " diag %1,%0,0xdc"
: "=d" (ry) : "=d" (ry)
......
...@@ -8,6 +8,42 @@ ...@@ -8,6 +8,42 @@
#ifndef _ASM_S390_DIAG_H #ifndef _ASM_S390_DIAG_H
#define _ASM_S390_DIAG_H #define _ASM_S390_DIAG_H
#include <linux/percpu.h>
enum diag_stat_enum {
DIAG_STAT_X008,
DIAG_STAT_X00C,
DIAG_STAT_X010,
DIAG_STAT_X014,
DIAG_STAT_X044,
DIAG_STAT_X064,
DIAG_STAT_X09C,
DIAG_STAT_X0DC,
DIAG_STAT_X204,
DIAG_STAT_X210,
DIAG_STAT_X224,
DIAG_STAT_X250,
DIAG_STAT_X258,
DIAG_STAT_X288,
DIAG_STAT_X2C4,
DIAG_STAT_X2FC,
DIAG_STAT_X304,
DIAG_STAT_X308,
DIAG_STAT_X500,
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]);
}
/* /*
* Diagnose 10: Release page range * Diagnose 10: Release page range
*/ */
...@@ -18,6 +54,7 @@ static inline void diag10_range(unsigned long start_pfn, unsigned long num_pfn) ...@@ -18,6 +54,7 @@ static inline void diag10_range(unsigned long start_pfn, unsigned long num_pfn)
start_addr = start_pfn << PAGE_SHIFT; start_addr = start_pfn << PAGE_SHIFT;
end_addr = (start_pfn + num_pfn - 1) << PAGE_SHIFT; end_addr = (start_pfn + num_pfn - 1) << PAGE_SHIFT;
diag_stat_inc(DIAG_STAT_X010);
asm volatile( asm volatile(
"0: diag %0,%1,0x10\n" "0: diag %0,%1,0x10\n"
"1:\n" "1:\n"
......
...@@ -27,10 +27,9 @@ ...@@ -27,10 +27,9 @@
#define __S390_KVM_PARA_H #define __S390_KVM_PARA_H
#include <uapi/asm/kvm_para.h> #include <uapi/asm/kvm_para.h>
#include <asm/diag.h>
static inline long __kvm_hypercall0(unsigned long nr)
static inline long kvm_hypercall0(unsigned long nr)
{ {
register unsigned long __nr asm("1") = nr; register unsigned long __nr asm("1") = nr;
register long __rc asm("2"); register long __rc asm("2");
...@@ -40,7 +39,13 @@ static inline long kvm_hypercall0(unsigned long nr) ...@@ -40,7 +39,13 @@ static inline long kvm_hypercall0(unsigned long nr)
return __rc; return __rc;
} }
static inline long kvm_hypercall1(unsigned long nr, unsigned long p1) static inline long kvm_hypercall0(unsigned long nr)
{
diag_stat_inc(DIAG_STAT_X500);
return __kvm_hypercall0(nr);
}
static inline long __kvm_hypercall1(unsigned long nr, unsigned long p1)
{ {
register unsigned long __nr asm("1") = nr; register unsigned long __nr asm("1") = nr;
register unsigned long __p1 asm("2") = p1; register unsigned long __p1 asm("2") = p1;
...@@ -51,7 +56,13 @@ static inline long kvm_hypercall1(unsigned long nr, unsigned long p1) ...@@ -51,7 +56,13 @@ static inline long kvm_hypercall1(unsigned long nr, unsigned long p1)
return __rc; return __rc;
} }
static inline long kvm_hypercall2(unsigned long nr, unsigned long p1, static inline long kvm_hypercall1(unsigned long nr, unsigned long p1)
{
diag_stat_inc(DIAG_STAT_X500);
return __kvm_hypercall1(nr, p1);
}
static inline long __kvm_hypercall2(unsigned long nr, unsigned long p1,
unsigned long p2) unsigned long p2)
{ {
register unsigned long __nr asm("1") = nr; register unsigned long __nr asm("1") = nr;
...@@ -65,7 +76,14 @@ static inline long kvm_hypercall2(unsigned long nr, unsigned long p1, ...@@ -65,7 +76,14 @@ static inline long kvm_hypercall2(unsigned long nr, unsigned long p1,
return __rc; return __rc;
} }
static inline long kvm_hypercall3(unsigned long nr, unsigned long p1, static inline long kvm_hypercall2(unsigned long nr, unsigned long p1,
unsigned long p2)
{
diag_stat_inc(DIAG_STAT_X500);
return __kvm_hypercall2(nr, p1, p2);
}
static inline long __kvm_hypercall3(unsigned long nr, unsigned long p1,
unsigned long p2, unsigned long p3) unsigned long p2, unsigned long p3)
{ {
register unsigned long __nr asm("1") = nr; register unsigned long __nr asm("1") = nr;
...@@ -80,8 +98,14 @@ static inline long kvm_hypercall3(unsigned long nr, unsigned long p1, ...@@ -80,8 +98,14 @@ static inline long kvm_hypercall3(unsigned long nr, unsigned long p1,
return __rc; return __rc;
} }
static inline long kvm_hypercall3(unsigned long nr, unsigned long p1,
unsigned long p2, unsigned long p3)
{
diag_stat_inc(DIAG_STAT_X500);
return __kvm_hypercall3(nr, p1, p2, p3);
}
static inline long kvm_hypercall4(unsigned long nr, unsigned long p1, static inline long __kvm_hypercall4(unsigned long nr, unsigned long p1,
unsigned long p2, unsigned long p3, unsigned long p2, unsigned long p3,
unsigned long p4) unsigned long p4)
{ {
...@@ -98,7 +122,15 @@ static inline long kvm_hypercall4(unsigned long nr, unsigned long p1, ...@@ -98,7 +122,15 @@ static inline long kvm_hypercall4(unsigned long nr, unsigned long p1,
return __rc; return __rc;
} }
static inline long kvm_hypercall5(unsigned long nr, unsigned long p1, static inline long kvm_hypercall4(unsigned long nr, unsigned long p1,
unsigned long p2, unsigned long p3,
unsigned long p4)
{
diag_stat_inc(DIAG_STAT_X500);
return __kvm_hypercall4(nr, p1, p2, p3, p4);
}
static inline long __kvm_hypercall5(unsigned long nr, unsigned long p1,
unsigned long p2, unsigned long p3, unsigned long p2, unsigned long p3,
unsigned long p4, unsigned long p5) unsigned long p4, unsigned long p5)
{ {
...@@ -116,7 +148,15 @@ static inline long kvm_hypercall5(unsigned long nr, unsigned long p1, ...@@ -116,7 +148,15 @@ static inline long kvm_hypercall5(unsigned long nr, unsigned long p1,
return __rc; return __rc;
} }
static inline long kvm_hypercall6(unsigned long nr, unsigned long p1, static inline long kvm_hypercall5(unsigned long nr, unsigned long p1,
unsigned long p2, unsigned long p3,
unsigned long p4, unsigned long p5)
{
diag_stat_inc(DIAG_STAT_X500);
return __kvm_hypercall5(nr, p1, p2, p3, p4, p5);
}
static inline long __kvm_hypercall6(unsigned long nr, unsigned long p1,
unsigned long p2, unsigned long p3, unsigned long p2, unsigned long p3,
unsigned long p4, unsigned long p5, unsigned long p4, unsigned long p5,
unsigned long p6) unsigned long p6)
...@@ -137,6 +177,15 @@ static inline long kvm_hypercall6(unsigned long nr, unsigned long p1, ...@@ -137,6 +177,15 @@ static inline long kvm_hypercall6(unsigned long nr, unsigned long p1,
return __rc; return __rc;
} }
static inline long kvm_hypercall6(unsigned long nr, unsigned long p1,
unsigned long p2, unsigned long p3,
unsigned long p4, unsigned long p5,
unsigned long p6)
{
diag_stat_inc(DIAG_STAT_X500);
return __kvm_hypercall6(nr, p1, p2, p3, p4, p5, p6);
}
/* kvm on s390 is always paravirtualization enabled */ /* kvm on s390 is always paravirtualization enabled */
static inline int kvm_para_available(void) static inline int kvm_para_available(void)
{ {
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/string.h> #include <linux/string.h>
#include <asm/diag.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include <asm/cpcmd.h> #include <asm/cpcmd.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -70,6 +71,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) ...@@ -70,6 +71,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
memcpy(cpcmd_buf, cmd, cmdlen); memcpy(cpcmd_buf, cmd, cmdlen);
ASCEBC(cpcmd_buf, cmdlen); ASCEBC(cpcmd_buf, cmdlen);
diag_stat_inc(DIAG_STAT_X008);
if (response) { if (response) {
memset(response, 0, rlen); memset(response, 0, rlen);
response_len = rlen; response_len = rlen;
......
...@@ -6,12 +6,119 @@ ...@@ -6,12 +6,119 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/cpu.h>
#include <linux/seq_file.h>
#include <linux/debugfs.h>
#include <asm/diag.h> #include <asm/diag.h>
DEFINE_PER_CPU(struct diag_stat, diag_stat);
EXPORT_PER_CPU_SYMBOL(diag_stat);
struct diag_desc {
int code;
char *name;
};
static const struct diag_desc diag_map[NR_DIAG_STAT] = {
[DIAG_STAT_X008] = { .code = 0x008, .name = "Console Function" },
[DIAG_STAT_X00C] = { .code = 0x00c, .name = "Pseudo Timer" },
[DIAG_STAT_X010] = { .code = 0x010, .name = "Release Pages" },
[DIAG_STAT_X014] = { .code = 0x014, .name = "Spool File Services" },
[DIAG_STAT_X044] = { .code = 0x044, .name = "Voluntary Timeslice End" },
[DIAG_STAT_X064] = { .code = 0x064, .name = "NSS Manipulation" },
[DIAG_STAT_X09C] = { .code = 0x09c, .name = "Relinquish Timeslice" },
[DIAG_STAT_X0DC] = { .code = 0x0dc, .name = "Appldata Control" },
[DIAG_STAT_X204] = { .code = 0x204, .name = "Logical-CPU Utilization" },
[DIAG_STAT_X210] = { .code = 0x210, .name = "Device Information" },
[DIAG_STAT_X224] = { .code = 0x224, .name = "EBCDIC-Name Table" },
[DIAG_STAT_X250] = { .code = 0x250, .name = "Block I/O" },
[DIAG_STAT_X258] = { .code = 0x258, .name = "Page-Reference Services" },
[DIAG_STAT_X288] = { .code = 0x288, .name = "Time Bomb" },
[DIAG_STAT_X2C4] = { .code = 0x2c4, .name = "FTP Services" },
[DIAG_STAT_X2FC] = { .code = 0x2fc, .name = "Guest Performance Data" },
[DIAG_STAT_X304] = { .code = 0x304, .name = "Partition-Resource Service" },
[DIAG_STAT_X308] = { .code = 0x308, .name = "List-Directed IPL" },
[DIAG_STAT_X500] = { .code = 0x500, .name = "Virtio Service" },
};
static int show_diag_stat(struct seq_file *m, void *v)
{
struct diag_stat *stat;
unsigned long n = (unsigned long) v - 1;
int cpu, prec, tmp;
get_online_cpus();
if (n == 0) {
seq_puts(m, " ");
for_each_online_cpu(cpu) {
prec = 10;
for (tmp = 10; cpu >= tmp; tmp *= 10)
prec--;
seq_printf(m, "%*s%d", prec, "CPU", cpu);
}
seq_putc(m, '\n');
} else if (n <= NR_DIAG_STAT) {
seq_printf(m, "diag %03x:", diag_map[n-1].code);
for_each_online_cpu(cpu) {
stat = &per_cpu(diag_stat, cpu);
seq_printf(m, " %10u", stat->counter[n-1]);
}
seq_printf(m, " %s\n", diag_map[n-1].name);
}
put_online_cpus();
return 0;
}
static void *show_diag_stat_start(struct seq_file *m, loff_t *pos)
{
return *pos <= nr_cpu_ids ? (void *)((unsigned long) *pos + 1) : NULL;
}
static void *show_diag_stat_next(struct seq_file *m, void *v, loff_t *pos)
{
++*pos;
return show_diag_stat_start(m, pos);
}
static void show_diag_stat_stop(struct seq_file *m, void *v)
{
}
static const struct seq_operations show_diag_stat_sops = {
.start = show_diag_stat_start,
.next = show_diag_stat_next,
.stop = show_diag_stat_stop,
.show = show_diag_stat,
};
static int show_diag_stat_open(struct inode *inode, struct file *file)
{
return seq_open(file, &show_diag_stat_sops);
}
static const struct file_operations show_diag_stat_fops = {
.open = show_diag_stat_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
static int __init show_diag_stat_init(void)
{
debugfs_create_file("diag_stat", 0400, NULL, NULL,
&show_diag_stat_fops);
return 0;
}
device_initcall(show_diag_stat_init);
/* /*
* Diagnose 14: Input spool file manipulation * Diagnose 14: Input spool file manipulation
*/ */
int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode) static inline int __diag14(unsigned long rx, unsigned long ry1,
unsigned long subcode)
{ {
register unsigned long _ry1 asm("2") = ry1; register unsigned long _ry1 asm("2") = ry1;
register unsigned long _ry2 asm("3") = subcode; register unsigned long _ry2 asm("3") = subcode;
...@@ -29,6 +136,12 @@ int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode) ...@@ -29,6 +136,12 @@ int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode)
return rc; return rc;
} }
int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode)
{
diag_stat_inc(DIAG_STAT_X014);
return __diag14(rx, ry1, subcode);
}
EXPORT_SYMBOL(diag14); EXPORT_SYMBOL(diag14);
/* /*
...@@ -48,6 +161,7 @@ int diag210(struct diag210 *addr) ...@@ -48,6 +161,7 @@ int diag210(struct diag210 *addr)
spin_lock_irqsave(&diag210_lock, flags); spin_lock_irqsave(&diag210_lock, flags);
diag210_tmp = *addr; diag210_tmp = *addr;
diag_stat_inc(DIAG_STAT_X210);
asm volatile( asm volatile(
" lhi %0,-1\n" " lhi %0,-1\n"
" sam31\n" " sam31\n"
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/pfn.h> #include <linux/pfn.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/diag.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include <asm/ipl.h> #include <asm/ipl.h>
#include <asm/lowcore.h> #include <asm/lowcore.h>
...@@ -286,6 +287,7 @@ static __init void detect_diag9c(void) ...@@ -286,6 +287,7 @@ static __init void detect_diag9c(void)
int rc; int rc;
cpu_address = stap(); cpu_address = stap();
diag_stat_inc(DIAG_STAT_X09C);
asm volatile( asm volatile(
" diag %2,0,0x9c\n" " diag %2,0,0x9c\n"
"0: la %0,0\n" "0: la %0,0\n"
...@@ -300,6 +302,7 @@ static __init void detect_diag44(void) ...@@ -300,6 +302,7 @@ static __init void detect_diag44(void)
{ {
int rc; int rc;
diag_stat_inc(DIAG_STAT_X044);
asm volatile( asm volatile(
" diag 0,0,0x44\n" " diag 0,0,0x44\n"
"0: la %0,0\n" "0: la %0,0\n"
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/crash_dump.h> #include <linux/crash_dump.h>
#include <linux/debug_locks.h> #include <linux/debug_locks.h>
#include <asm/diag.h>
#include <asm/ipl.h> #include <asm/ipl.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/setup.h> #include <asm/setup.h>
...@@ -165,7 +166,7 @@ static struct ipl_parameter_block *dump_block_ccw; ...@@ -165,7 +166,7 @@ static struct ipl_parameter_block *dump_block_ccw;
static struct sclp_ipl_info sclp_ipl_info; static struct sclp_ipl_info sclp_ipl_info;
int diag308(unsigned long subcode, void *addr) static inline int __diag308(unsigned long subcode, void *addr)
{ {
register unsigned long _addr asm("0") = (unsigned long) addr; register unsigned long _addr asm("0") = (unsigned long) addr;
register unsigned long _rc asm("1") = 0; register unsigned long _rc asm("1") = 0;
...@@ -178,6 +179,12 @@ int diag308(unsigned long subcode, void *addr) ...@@ -178,6 +179,12 @@ int diag308(unsigned long subcode, void *addr)
: "d" (subcode) : "cc", "memory"); : "d" (subcode) : "cc", "memory");
return _rc; return _rc;
} }
int diag308(unsigned long subcode, void *addr)
{
diag_stat_inc(DIAG_STAT_X308);
return __diag308(subcode, addr);
}
EXPORT_SYMBOL_GPL(diag308); EXPORT_SYMBOL_GPL(diag308);
/* SYSFS */ /* SYSFS */
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <asm/diag.h>
#include <asm/elf.h> #include <asm/elf.h>
#include <asm/lowcore.h> #include <asm/lowcore.h>
#include <asm/param.h> #include <asm/param.h>
...@@ -20,8 +21,10 @@ static DEFINE_PER_CPU(struct cpuid, cpu_id); ...@@ -20,8 +21,10 @@ static DEFINE_PER_CPU(struct cpuid, cpu_id);
void notrace cpu_relax(void) void notrace cpu_relax(void)
{ {
if (!smp_cpu_mtid && MACHINE_HAS_DIAG44) if (!smp_cpu_mtid && MACHINE_HAS_DIAG44) {
diag_stat_inc(DIAG_STAT_X044);
asm volatile("diag 0,0,0x44"); asm volatile("diag 0,0,0x44");
}
barrier(); barrier();
} }
EXPORT_SYMBOL(cpu_relax); EXPORT_SYMBOL(cpu_relax);
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <linux/crash_dump.h> #include <linux/crash_dump.h>
#include <linux/memblock.h> #include <linux/memblock.h>
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
#include <asm/diag.h>
#include <asm/switch_to.h> #include <asm/switch_to.h>
#include <asm/facility.h> #include <asm/facility.h>
#include <asm/ipl.h> #include <asm/ipl.h>
...@@ -375,11 +376,14 @@ int smp_vcpu_scheduled(int cpu) ...@@ -375,11 +376,14 @@ int smp_vcpu_scheduled(int cpu)
void smp_yield_cpu(int cpu) void smp_yield_cpu(int cpu)
{ {
if (MACHINE_HAS_DIAG9C) if (MACHINE_HAS_DIAG9C) {
diag_stat_inc(DIAG_STAT_X09C);
asm volatile("diag %0,0,0x9c" asm volatile("diag %0,0,0x9c"
: : "d" (pcpu_devices[cpu].address)); : : "d" (pcpu_devices[cpu].address));
else if (MACHINE_HAS_DIAG44) } else if (MACHINE_HAS_DIAG44) {
diag_stat_inc(DIAG_STAT_X044);
asm volatile("diag 0,0,0x44"); asm volatile("diag 0,0,0x44");
}
} }
/* /*
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <asm/diag.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
...@@ -112,6 +113,7 @@ dcss_set_subcodes(void) ...@@ -112,6 +113,7 @@ dcss_set_subcodes(void)
ry = DCSS_FINDSEGX; ry = DCSS_FINDSEGX;
strcpy(name, "dummy"); strcpy(name, "dummy");
diag_stat_inc(DIAG_STAT_X064);
asm volatile( asm volatile(
" diag %0,%1,0x64\n" " diag %0,%1,0x64\n"
"0: ipm %2\n" "0: ipm %2\n"
...@@ -205,6 +207,7 @@ dcss_diag(int *func, void *parameter, ...@@ -205,6 +207,7 @@ dcss_diag(int *func, void *parameter,
ry = (unsigned long) *func; ry = (unsigned long) *func;
/* 64-bit Diag x'64' new subcode, keep in 64-bit addressing mode */ /* 64-bit Diag x'64' new subcode, keep in 64-bit addressing mode */
diag_stat_inc(DIAG_STAT_X064);
if (*func > DCSS_SEGEXT) if (*func > DCSS_SEGEXT)
asm volatile( asm volatile(
" diag %0,%1,0x64\n" " diag %0,%1,0x64\n"
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/hugetlb.h> #include <linux/hugetlb.h>
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
#include <asm/diag.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
...@@ -597,6 +598,7 @@ int pfault_init(void) ...@@ -597,6 +598,7 @@ int pfault_init(void)
if (pfault_disable) if (pfault_disable)
return -1; return -1;
diag_stat_inc(DIAG_STAT_X258);
asm volatile( asm volatile(
" diag %1,%0,0x258\n" " diag %1,%0,0x258\n"
"0: j 2f\n" "0: j 2f\n"
...@@ -618,6 +620,7 @@ void pfault_fini(void) ...@@ -618,6 +620,7 @@ void pfault_fini(void)
if (pfault_disable) if (pfault_disable)
return; return;
diag_stat_inc(DIAG_STAT_X258);
asm volatile( asm volatile(
" diag %0,0,0x258\n" " diag %0,0,0x258\n"
"0:\n" "0:\n"
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <asm/dasd.h> #include <asm/dasd.h>
#include <asm/debug.h> #include <asm/debug.h>
#include <asm/diag.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -76,6 +77,7 @@ static inline int dia250(void *iob, int cmd) ...@@ -76,6 +77,7 @@ static inline int dia250(void *iob, int cmd)
int rc; int rc;
rc = 3; rc = 3;
diag_stat_inc(DIAG_STAT_X250);
asm volatile( asm volatile(
" diag 2,%2,0x250\n" " diag 2,%2,0x250\n"
"0: ipm %0\n" "0: ipm %0\n"
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/string.h> #include <linux/string.h>
#include <asm/ctl_reg.h> #include <asm/ctl_reg.h>
#include <asm/diag.h>
#include "hmcdrv_ftp.h" #include "hmcdrv_ftp.h"
#include "diag_ftp.h" #include "diag_ftp.h"
...@@ -102,6 +103,7 @@ static int diag_ftp_2c4(struct diag_ftp_ldfpl *fpl, ...@@ -102,6 +103,7 @@ static int diag_ftp_2c4(struct diag_ftp_ldfpl *fpl,
{ {
int rc; int rc;
diag_stat_inc(DIAG_STAT_X2C4);
asm volatile( asm volatile(
" diag %[addr],%[cmd],0x2c4\n" " diag %[addr],%[cmd],0x2c4\n"
"0: j 2f\n" "0: j 2f\n"
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/kvm_para.h> #include <linux/kvm_para.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <asm/diag.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/cio.h> #include <asm/cio.h>
...@@ -366,9 +367,9 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev, ...@@ -366,9 +367,9 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev,
kfree(thinint_area); kfree(thinint_area);
} }
static inline long do_kvm_notify(struct subchannel_id schid, static inline long __do_kvm_notify(struct subchannel_id schid,
unsigned long queue_index, unsigned long queue_index,
long cookie) long cookie)
{ {
register unsigned long __nr asm("1") = KVM_S390_VIRTIO_CCW_NOTIFY; register unsigned long __nr asm("1") = KVM_S390_VIRTIO_CCW_NOTIFY;
register struct subchannel_id __schid asm("2") = schid; register struct subchannel_id __schid asm("2") = schid;
...@@ -383,6 +384,14 @@ static inline long do_kvm_notify(struct subchannel_id schid, ...@@ -383,6 +384,14 @@ static inline long do_kvm_notify(struct subchannel_id schid,
return __rc; return __rc;
} }
static inline long do_kvm_notify(struct subchannel_id schid,
unsigned long queue_index,
long cookie)
{
diag_stat_inc(DIAG_STAT_X500);
return __do_kvm_notify(schid, queue_index, cookie);
}
static bool virtio_ccw_kvm_notify(struct virtqueue *vq) static bool virtio_ccw_kvm_notify(struct virtqueue *vq)
{ {
struct virtio_ccw_vq_info *info = vq->priv; struct virtio_ccw_vq_info *info = vq->priv;
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include <asm/diag.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
...@@ -94,12 +95,14 @@ static int __diag288(unsigned int func, unsigned int timeout, ...@@ -94,12 +95,14 @@ static int __diag288(unsigned int func, unsigned int timeout,
static int __diag288_vm(unsigned int func, unsigned int timeout, static int __diag288_vm(unsigned int func, unsigned int timeout,
char *cmd, size_t len) char *cmd, size_t len)
{ {
diag_stat_inc(DIAG_STAT_X288);
return __diag288(func, timeout, virt_to_phys(cmd), len); return __diag288(func, timeout, virt_to_phys(cmd), len);
} }
static int __diag288_lpar(unsigned int func, unsigned int timeout, static int __diag288_lpar(unsigned int func, unsigned int timeout,
unsigned long action) unsigned long action)
{ {
diag_stat_inc(DIAG_STAT_X288);
return __diag288(func, timeout, action, 0); return __diag288(func, timeout, action, 0);
} }
...@@ -141,6 +144,7 @@ static int wdt_stop(struct watchdog_device *dev) ...@@ -141,6 +144,7 @@ static int wdt_stop(struct watchdog_device *dev)
{ {
int ret; int ret;
diag_stat_inc(DIAG_STAT_X288);
ret = __diag288(WDT_FUNC_CANCEL, 0, 0, 0); ret = __diag288(WDT_FUNC_CANCEL, 0, 0, 0);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment