xref: /linux/arch/mips/math-emu/me-debugfs.c (revision 25ad8db632ec54c60daad9107ddf25a2a608a450)
185c51c51SRalf Baechle #include <linux/cpumask.h>
285c51c51SRalf Baechle #include <linux/debugfs.h>
385c51c51SRalf Baechle #include <linux/fs.h>
485c51c51SRalf Baechle #include <linux/init.h>
585c51c51SRalf Baechle #include <linux/percpu.h>
685c51c51SRalf Baechle #include <linux/types.h>
775dcfc1dSPaul Burton #include <asm/debug.h>
885c51c51SRalf Baechle #include <asm/fpu_emulator.h>
985c51c51SRalf Baechle #include <asm/local.h>
1085c51c51SRalf Baechle 
1185c51c51SRalf Baechle DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
1285c51c51SRalf Baechle 
1385c51c51SRalf Baechle static int fpuemu_stat_get(void *data, u64 *val)
1485c51c51SRalf Baechle {
1585c51c51SRalf Baechle 	int cpu;
1685c51c51SRalf Baechle 	unsigned long sum = 0;
1785c51c51SRalf Baechle 
1885c51c51SRalf Baechle 	for_each_online_cpu(cpu) {
1985c51c51SRalf Baechle 		struct mips_fpu_emulator_stats *ps;
2085c51c51SRalf Baechle 		local_t *pv;
2185c51c51SRalf Baechle 
2285c51c51SRalf Baechle 		ps = &per_cpu(fpuemustats, cpu);
2385c51c51SRalf Baechle 		pv = (void *)ps + (unsigned long)data;
2485c51c51SRalf Baechle 		sum += local_read(pv);
2585c51c51SRalf Baechle 	}
2685c51c51SRalf Baechle 	*val = sum;
2785c51c51SRalf Baechle 	return 0;
2885c51c51SRalf Baechle }
2985c51c51SRalf Baechle DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n");
3085c51c51SRalf Baechle 
31*25ad8db6SAleksandar Markovic static int fpuemustats_clear_show(struct seq_file *s, void *unused)
32*25ad8db6SAleksandar Markovic {
33*25ad8db6SAleksandar Markovic 	__this_cpu_write((fpuemustats).emulated, 0);
34*25ad8db6SAleksandar Markovic 	__this_cpu_write((fpuemustats).loads, 0);
35*25ad8db6SAleksandar Markovic 	__this_cpu_write((fpuemustats).stores, 0);
36*25ad8db6SAleksandar Markovic 	__this_cpu_write((fpuemustats).branches, 0);
37*25ad8db6SAleksandar Markovic 	__this_cpu_write((fpuemustats).cp1ops, 0);
38*25ad8db6SAleksandar Markovic 	__this_cpu_write((fpuemustats).cp1xops, 0);
39*25ad8db6SAleksandar Markovic 	__this_cpu_write((fpuemustats).errors, 0);
40*25ad8db6SAleksandar Markovic 	__this_cpu_write((fpuemustats).ieee754_inexact, 0);
41*25ad8db6SAleksandar Markovic 	__this_cpu_write((fpuemustats).ieee754_underflow, 0);
42*25ad8db6SAleksandar Markovic 	__this_cpu_write((fpuemustats).ieee754_overflow, 0);
43*25ad8db6SAleksandar Markovic 	__this_cpu_write((fpuemustats).ieee754_zerodiv, 0);
44*25ad8db6SAleksandar Markovic 	__this_cpu_write((fpuemustats).ieee754_invalidop, 0);
45*25ad8db6SAleksandar Markovic 	__this_cpu_write((fpuemustats).ds_emul, 0);
46*25ad8db6SAleksandar Markovic 
47*25ad8db6SAleksandar Markovic 	return 0;
48*25ad8db6SAleksandar Markovic }
49*25ad8db6SAleksandar Markovic 
50*25ad8db6SAleksandar Markovic static int fpuemustats_clear_open(struct inode *inode, struct file *file)
51*25ad8db6SAleksandar Markovic {
52*25ad8db6SAleksandar Markovic 	return single_open(file, fpuemustats_clear_show, inode->i_private);
53*25ad8db6SAleksandar Markovic }
54*25ad8db6SAleksandar Markovic 
55*25ad8db6SAleksandar Markovic static const struct file_operations fpuemustats_clear_fops = {
56*25ad8db6SAleksandar Markovic 	.open                   = fpuemustats_clear_open,
57*25ad8db6SAleksandar Markovic 	.read			= seq_read,
58*25ad8db6SAleksandar Markovic 	.llseek			= seq_lseek,
59*25ad8db6SAleksandar Markovic 	.release		= single_release,
60*25ad8db6SAleksandar Markovic };
61*25ad8db6SAleksandar Markovic 
6285c51c51SRalf Baechle static int __init debugfs_fpuemu(void)
6385c51c51SRalf Baechle {
64*25ad8db6SAleksandar Markovic 	struct dentry *d, *dir, *reset_file;
6585c51c51SRalf Baechle 
6685c51c51SRalf Baechle 	if (!mips_debugfs_dir)
6785c51c51SRalf Baechle 		return -ENODEV;
6885c51c51SRalf Baechle 	dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir);
6985c51c51SRalf Baechle 	if (!dir)
7085c51c51SRalf Baechle 		return -ENOMEM;
71*25ad8db6SAleksandar Markovic 	reset_file = debugfs_create_file("fpuemustats_clear", 0444,
72*25ad8db6SAleksandar Markovic 					 mips_debugfs_dir, NULL,
73*25ad8db6SAleksandar Markovic 					 &fpuemustats_clear_fops);
74*25ad8db6SAleksandar Markovic 	if (!reset_file)
75*25ad8db6SAleksandar Markovic 		return -ENOMEM;
7685c51c51SRalf Baechle 
7747fa0c02SRalf Baechle #define FPU_EMU_STAT_OFFSET(m)						\
7847fa0c02SRalf Baechle 	offsetof(struct mips_fpu_emulator_stats, m)
7947fa0c02SRalf Baechle 
8047fa0c02SRalf Baechle #define FPU_STAT_CREATE(m)						\
8185c51c51SRalf Baechle do {									\
8247fa0c02SRalf Baechle 	d = debugfs_create_file(#m , S_IRUGO, dir,			\
8347fa0c02SRalf Baechle 				(void *)FPU_EMU_STAT_OFFSET(m),		\
8485c51c51SRalf Baechle 				&fops_fpuemu_stat);			\
8585c51c51SRalf Baechle 	if (!d)								\
8685c51c51SRalf Baechle 		return -ENOMEM;						\
8785c51c51SRalf Baechle } while (0)
8885c51c51SRalf Baechle 
8985c51c51SRalf Baechle 	FPU_STAT_CREATE(emulated);
9085c51c51SRalf Baechle 	FPU_STAT_CREATE(loads);
9185c51c51SRalf Baechle 	FPU_STAT_CREATE(stores);
92ae5f3f5bSAleksandar Markovic 	FPU_STAT_CREATE(branches);
9385c51c51SRalf Baechle 	FPU_STAT_CREATE(cp1ops);
9485c51c51SRalf Baechle 	FPU_STAT_CREATE(cp1xops);
9585c51c51SRalf Baechle 	FPU_STAT_CREATE(errors);
96c4103526SDeng-Cheng Zhu 	FPU_STAT_CREATE(ieee754_inexact);
97c4103526SDeng-Cheng Zhu 	FPU_STAT_CREATE(ieee754_underflow);
98c4103526SDeng-Cheng Zhu 	FPU_STAT_CREATE(ieee754_overflow);
99c4103526SDeng-Cheng Zhu 	FPU_STAT_CREATE(ieee754_zerodiv);
100c4103526SDeng-Cheng Zhu 	FPU_STAT_CREATE(ieee754_invalidop);
1012707cd29SDavid Daney 	FPU_STAT_CREATE(ds_emul);
10285c51c51SRalf Baechle 
10385c51c51SRalf Baechle 	return 0;
10485c51c51SRalf Baechle }
1051249ed35SRalf Baechle arch_initcall(debugfs_fpuemu);
106