1 #include <linux/cpumask.h> 2 #include <linux/debugfs.h> 3 #include <linux/fs.h> 4 #include <linux/init.h> 5 #include <linux/percpu.h> 6 #include <linux/types.h> 7 #include <asm/debug.h> 8 #include <asm/fpu_emulator.h> 9 #include <asm/local.h> 10 11 DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats); 12 13 static int fpuemu_stat_get(void *data, u64 *val) 14 { 15 int cpu; 16 unsigned long sum = 0; 17 18 for_each_online_cpu(cpu) { 19 struct mips_fpu_emulator_stats *ps; 20 local_t *pv; 21 22 ps = &per_cpu(fpuemustats, cpu); 23 pv = (void *)ps + (unsigned long)data; 24 sum += local_read(pv); 25 } 26 *val = sum; 27 return 0; 28 } 29 DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n"); 30 31 static int fpuemustats_clear_show(struct seq_file *s, void *unused) 32 { 33 __this_cpu_write((fpuemustats).emulated, 0); 34 __this_cpu_write((fpuemustats).loads, 0); 35 __this_cpu_write((fpuemustats).stores, 0); 36 __this_cpu_write((fpuemustats).branches, 0); 37 __this_cpu_write((fpuemustats).cp1ops, 0); 38 __this_cpu_write((fpuemustats).cp1xops, 0); 39 __this_cpu_write((fpuemustats).errors, 0); 40 __this_cpu_write((fpuemustats).ieee754_inexact, 0); 41 __this_cpu_write((fpuemustats).ieee754_underflow, 0); 42 __this_cpu_write((fpuemustats).ieee754_overflow, 0); 43 __this_cpu_write((fpuemustats).ieee754_zerodiv, 0); 44 __this_cpu_write((fpuemustats).ieee754_invalidop, 0); 45 __this_cpu_write((fpuemustats).ds_emul, 0); 46 47 return 0; 48 } 49 50 static int fpuemustats_clear_open(struct inode *inode, struct file *file) 51 { 52 return single_open(file, fpuemustats_clear_show, inode->i_private); 53 } 54 55 static const struct file_operations fpuemustats_clear_fops = { 56 .open = fpuemustats_clear_open, 57 .read = seq_read, 58 .llseek = seq_lseek, 59 .release = single_release, 60 }; 61 62 static int __init debugfs_fpuemu(void) 63 { 64 struct dentry *d, *dir, *reset_file; 65 66 if (!mips_debugfs_dir) 67 return -ENODEV; 68 dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir); 69 if (!dir) 70 return -ENOMEM; 71 reset_file = debugfs_create_file("fpuemustats_clear", 0444, 72 mips_debugfs_dir, NULL, 73 &fpuemustats_clear_fops); 74 if (!reset_file) 75 return -ENOMEM; 76 77 #define FPU_EMU_STAT_OFFSET(m) \ 78 offsetof(struct mips_fpu_emulator_stats, m) 79 80 #define FPU_STAT_CREATE(m) \ 81 do { \ 82 d = debugfs_create_file(#m , S_IRUGO, dir, \ 83 (void *)FPU_EMU_STAT_OFFSET(m), \ 84 &fops_fpuemu_stat); \ 85 if (!d) \ 86 return -ENOMEM; \ 87 } while (0) 88 89 FPU_STAT_CREATE(emulated); 90 FPU_STAT_CREATE(loads); 91 FPU_STAT_CREATE(stores); 92 FPU_STAT_CREATE(branches); 93 FPU_STAT_CREATE(cp1ops); 94 FPU_STAT_CREATE(cp1xops); 95 FPU_STAT_CREATE(errors); 96 FPU_STAT_CREATE(ieee754_inexact); 97 FPU_STAT_CREATE(ieee754_underflow); 98 FPU_STAT_CREATE(ieee754_overflow); 99 FPU_STAT_CREATE(ieee754_zerodiv); 100 FPU_STAT_CREATE(ieee754_invalidop); 101 FPU_STAT_CREATE(ds_emul); 102 103 return 0; 104 } 105 arch_initcall(debugfs_fpuemu); 106