Sometimes I want to know what kind of (and how many times) FP
exceptions occurred in run time. Here is a patch to provide us these
informations via /proc/cpuinfo.
Any comments are welcome. (This patch is not tested on SMP)
diff -ur linux-sgi-cvs/arch/mips/config.in linux.new/arch/mips/config.in
--- linux-sgi-cvs/arch/mips/config.in Wed Nov 21 10:31:56 2001
+++ linux.new/arch/mips/config.in Wed Nov 21 15:45:44 2001
@@ -359,6 +359,7 @@
else
bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN
fi
+bool 'Support for FPU Exception statistics' CONFIG_MIPS_FPE_STATS
if [ "$CONFIG_PROC_FS" = "y" ]; then
define_bool CONFIG_KCORE_ELF y
diff -ur linux-sgi-cvs/arch/mips/kernel/proc.c linux.new/arch/mips/kernel/proc.c
--- linux-sgi-cvs/arch/mips/kernel/proc.c Mon Oct 22 10:29:56 2001
+++ linux.new/arch/mips/kernel/proc.c Wed Nov 21 15:43:24 2001
@@ -19,6 +19,10 @@
#ifndef CONFIG_CPU_HAS_LLSC
unsigned long ll_ops, sc_ops;
#endif
+#ifdef CONFIG_MIPS_FPE_STATS
+unsigned int fpu_exceptions[6];
+static char fpe_types[6] = {'I', 'U', 'O', 'Z', 'V', 'E'};
+#endif
/*
* BUFFER is PAGE_SIZE bytes long.
@@ -61,6 +65,9 @@
mach_nec_vr41xx_names};
unsigned int version = read_32bit_cp0_register(CP0_PRID);
int len;
+#ifdef CONFIG_MIPS_FPE_STATS
+ int i;
+#endif
len = sprintf(buffer, "cpu\t\t\t: MIPS\n");
len += sprintf(buffer + len, "cpu model\t\t: %s V%d.%d\n",
@@ -101,6 +108,14 @@
ll_ops);
len += sprintf(buffer + len, "sc emulations\t\t: %lu\n",
sc_ops);
+#endif
+#ifdef CONFIG_MIPS_FPE_STATS
+ len += sprintf(buffer + len, "fpu exceptions\t\t:");
+ for (i = 0; i < sizeof(fpu_exceptions) / sizeof(fpu_exceptions[0]);
i++) {
+ len += sprintf(buffer + len, " %u(%c)",
+ fpu_exceptions[i], fpe_types[i]);
+ }
+ len += sprintf(buffer + len, "\n");
#endif
return len;
}
diff -ur linux-sgi-cvs/arch/mips/kernel/traps.c
linux.new/arch/mips/kernel/traps.c
--- linux-sgi-cvs/arch/mips/kernel/traps.c Wed Nov 21 10:31:57 2001
+++ linux.new/arch/mips/kernel/traps.c Wed Nov 21 15:46:15 2001
@@ -461,6 +461,18 @@
*/
asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
{
+#ifdef CONFIG_MIPS_FPE_STATS
+ extern unsigned int fpu_exceptions[];
+ unsigned char fpe;
+ int i;
+ fpe = ((fcr31 & FPU_CSR_ALL_X) / FPU_CSR_INE_X) &
+ ((fcr31 | ~FPU_CSR_ALL_E) / FPU_CSR_INE_E);
+ for (i = 0; i < 6; i++) {
+ if (fpe & (1 << i))
+ fpu_exceptions[i]++;
+ }
+#endif
+
if (fcr31 & FPU_CSR_UNI_X) {
extern void save_fp(struct task_struct *);
extern void restore_fp(struct task_struct *);
---
Atsushi Nemoto
|