Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1716392 > unrolled thread
| Started by | Aleksandar Markovic <aleksandar.markovic@rt-rk.com> |
|---|---|
| First post | 2017-08-21 14:30 +0200 |
| Last post | 2017-08-21 14:40 +0200 |
| Articles | 7 — 1 participant |
Back to article view | Back to linux.kernel
[PATCH v2 0/6] MIPS: math-emu: FP emulation fixes and improvements Aleksandar Markovic <aleksandar.markovic@rt-rk.com> - 2017-08-21 14:30 +0200
[PATCH v2 2/6] MIPS: math-emu: RINT.<D|S>: Fix several problems by reimplementation Aleksandar Markovic <aleksandar.markovic@rt-rk.com> - 2017-08-21 14:30 +0200
[PATCH v2 1/6] MIPS: math-emu: CMP.Sxxx.<D|S>: Prevent occurrences of SIGILL crashes Aleksandar Markovic <aleksandar.markovic@rt-rk.com> - 2017-08-21 14:30 +0200
[PATCH v2 3/6] MIPS: math-emu: CLASS.D: Zero bits 32-63 of the result Aleksandar Markovic <aleksandar.markovic@rt-rk.com> - 2017-08-21 14:40 +0200
[PATCH v2 4/6] MIPS: math-emu: Add FP emu debugfs statistics for branches Aleksandar Markovic <aleksandar.markovic@rt-rk.com> - 2017-08-21 14:40 +0200
[PATCH v2 5/6] MIPS: math-emu: Add FP emu debugfs clear functionality Aleksandar Markovic <aleksandar.markovic@rt-rk.com> - 2017-08-21 14:40 +0200
[PATCH v2 6/6] MIPS: math-emu: Add FP emu debugfs stats for individual instructions Aleksandar Markovic <aleksandar.markovic@rt-rk.com> - 2017-08-21 14:40 +0200
| From | Aleksandar Markovic <aleksandar.markovic@rt-rk.com> |
|---|---|
| Date | 2017-08-21 14:30 +0200 |
| Subject | [PATCH v2 0/6] MIPS: math-emu: FP emulation fixes and improvements |
| Message-ID | <ugU0a-4jm-5@gated-at.bofh.it> |
From: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
v1->v2:
- corrected a number of spelling and other minor mistakes in commit
messages
- rebased to the latest code
This series includes:
- a fix for certain SIGILL program crashes on issuing a valid CMP
instruction
- a fix for RINT emulation inaccuracies
- a fix for the output of CLASS.D instruction emulation
- several FP emulation debugfs statistics improvements
The patches in this series are logically and physically independent on
the patches previously sent in "Misc" series. This means that these
two series can be applied independently, in any order.
Aleksandar Markovic (6):
MIPS: math-emu: CMP.Sxxx.<D|S>: Prevent occurrences of SIGILL crashes
MIPS: math-emu: RINT.<D|S>: Fix several problems by reimplementation
MIPS: math-emu: CLASS.D: Zero bits 32-63 of the result
MIPS: math-emu: Add FP emu debugfs statistics for branches
MIPS: math-emu: Add FP emu debugfs clear functionality
MIPS: math-emu: Add FP emu debugfs stats for individual instructions
MAINTAINERS | 7 +
arch/mips/include/asm/fpu_emulator.h | 116 +++++++++++++
arch/mips/math-emu/Makefile | 6 +-
arch/mips/math-emu/cp1emu.c | 272 +++++++++++++++++++++++++++++-
arch/mips/math-emu/dp_rint.c | 89 ++++++++++
arch/mips/math-emu/ieee754.h | 2 +
arch/mips/math-emu/me-debugfs.c | 318 ++++++++++++++++++++++++++++++++++-
arch/mips/math-emu/sp_rint.c | 90 ++++++++++
8 files changed, 888 insertions(+), 12 deletions(-)
create mode 100644 arch/mips/math-emu/dp_rint.c
create mode 100644 arch/mips/math-emu/sp_rint.c
--
2.9.3
[toc] | [next] | [standalone]
| From | Aleksandar Markovic <aleksandar.markovic@rt-rk.com> |
|---|---|
| Date | 2017-08-21 14:30 +0200 |
| Subject | [PATCH v2 2/6] MIPS: math-emu: RINT.<D|S>: Fix several problems by reimplementation |
| Message-ID | <ugU0a-4jm-13@gated-at.bofh.it> |
| In reply to | #1716392 |
From: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
Reimplement RINT.<D|S> kernel emulation so that all RINT.<D|S>
specifications are met.
For the sake of simplicity, let's analyze RINT.S only. Prior to
this patch, RINT.S emulation was essentially implemented as (in
pseudocode) <output> = ieee754sp_flong(ieee754sp_tlong(<input>)),
where ieee754sp_tlong() and ieee754sp_flong() are functions
providing conversion from double to integer, and from integer
to double, respectively. On surface, this implementation looks
correct, but actually fails in many cases. Following problems
were detected:
1. NaN and infinity cases will not be handled properly. The
function ieee754sp_flong() never returns NaN nor infinity.
2. For RINT.S, for all inputs larger than LONG_MAX, and smaller
than FLT_MAX, the result will be wrong, and the overflow
exception will be erroneously set. A similar problem for
negative inputs exists as well.
3. For some rounding modes, for some negative inputs close to zero,
the return value will be zero, and should be -zero. This is
because ieee754sp_flong() never returns -zero.
This patch removes the problems above by implementing dedicated
functions for RINT.<D|S> emulation.
The core of the new function functionality is adapted version of
the core of the function ieee754sp_tlong(). However, there are many
details that are implemented to match RINT.<D|S> specification. It
should be said that the functionality of ieee754sp_tlong() actually
closely corresponds to CVT.L.S instruction, and it is used while
emulating CVT.L.S. However, RINT.S and CVT.L.S instructions differ
in many aspects. This patch fulfills missing support for RINT.<D|S>.
Signed-off-by: Miodrag Dinic <miodrag.dinic@imgtec.com>
Signed-off-by: Goran Ferenc <goran.ferenc@imgtec.com>
Signed-off-by: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
---
MAINTAINERS | 7 ++++
arch/mips/math-emu/Makefile | 6 ++-
arch/mips/math-emu/cp1emu.c | 6 +--
arch/mips/math-emu/dp_rint.c | 89 +++++++++++++++++++++++++++++++++++++++++++
arch/mips/math-emu/ieee754.h | 2 +
arch/mips/math-emu/sp_rint.c | 90 ++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 194 insertions(+), 6 deletions(-)
create mode 100644 arch/mips/math-emu/dp_rint.c
create mode 100644 arch/mips/math-emu/sp_rint.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 1c3feff..5a6a0e6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8802,6 +8802,13 @@ F: arch/mips/include/asm/mach-loongson32/
F: drivers/*/*loongson1*
F: drivers/*/*/*loongson1*
+MIPS RINT INSTRUCTION EMULATION
+M: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
+L: linux-mips@linux-mips.org
+S: Supported
+F: arch/mips/math-emu/sp_rint.c
+F: arch/mips/math-emu/dp_rint.c
+
MIROSOUND PCM20 FM RADIO RECEIVER DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile
index e9bbc2a..e9f10b8 100644
--- a/arch/mips/math-emu/Makefile
+++ b/arch/mips/math-emu/Makefile
@@ -4,9 +4,11 @@
obj-y += cp1emu.o ieee754dp.o ieee754sp.o ieee754.o \
dp_div.o dp_mul.o dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o \
- dp_tint.o dp_fint.o dp_maddf.o dp_2008class.o dp_fmin.o dp_fmax.o \
+ dp_tint.o dp_fint.o dp_rint.o dp_maddf.o dp_2008class.o dp_fmin.o \
+ dp_fmax.o \
sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_simple.o \
- sp_tint.o sp_fint.o sp_maddf.o sp_2008class.o sp_fmin.o sp_fmax.o \
+ sp_tint.o sp_fint.o sp_rint.o sp_maddf.o sp_2008class.o sp_fmin.o \
+ sp_fmax.o \
dsemul.o
lib-y += ieee754d.o \
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 520a5ac..cabcf2c 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -1805,8 +1805,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
return SIGILL;
SPFROMREG(fs, MIPSInst_FS(ir));
- rv.l = ieee754sp_tlong(fs);
- rv.s = ieee754sp_flong(rv.l);
+ rv.s = ieee754sp_rint(fs);
goto copcsr;
}
@@ -2134,8 +2133,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
return SIGILL;
DPFROMREG(fs, MIPSInst_FS(ir));
- rv.l = ieee754dp_tlong(fs);
- rv.d = ieee754dp_flong(rv.l);
+ rv.d = ieee754dp_rint(fs);
goto copcsr;
}
diff --git a/arch/mips/math-emu/dp_rint.c b/arch/mips/math-emu/dp_rint.c
new file mode 100644
index 0000000..c3b9077
--- /dev/null
+++ b/arch/mips/math-emu/dp_rint.c
@@ -0,0 +1,89 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * Copyright (C) 2017 Imagination Technologies, Ltd.
+ * Author: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.
+ */
+
+#include "ieee754dp.h"
+
+union ieee754dp ieee754dp_rint(union ieee754dp x)
+{
+ union ieee754dp ret;
+ u64 residue;
+ int sticky;
+ int round;
+ int odd;
+
+ COMPXDP;
+
+ ieee754_clearcx();
+
+ EXPLODEXDP;
+ FLUSHXDP;
+
+ if (xc == IEEE754_CLASS_SNAN)
+ return ieee754dp_nanxcpt(x);
+
+ if ((xc == IEEE754_CLASS_QNAN) ||
+ (xc == IEEE754_CLASS_INF) ||
+ (xc == IEEE754_CLASS_ZERO))
+ return x;
+
+ if (xe >= DP_FBITS)
+ return x;
+
+ if (xe < -1) {
+ residue = xm;
+ round = 0;
+ sticky = residue != 0;
+ xm = 0;
+ } else {
+ residue = xm << (64 - DP_FBITS + xe);
+ round = (residue >> 63) != 0;
+ sticky = (residue << 1) != 0;
+ xm >>= DP_FBITS - xe;
+ }
+
+ odd = (xm & 0x1) != 0x0;
+
+ switch (ieee754_csr.rm) {
+ case FPU_CSR_RN: /* toward nearest */
+ if (round && (sticky || odd))
+ xm++;
+ break;
+ case FPU_CSR_RZ: /* toward zero */
+ break;
+ case FPU_CSR_RU: /* toward +infinity */
+ if ((round || sticky) && !xs)
+ xm++;
+ break;
+ case FPU_CSR_RD: /* toward -infinity */
+ if ((round || sticky) && xs)
+ xm++;
+ break;
+ }
+
+ if (round || sticky)
+ ieee754_setcx(IEEE754_INEXACT);
+
+ ret = ieee754dp_flong(xm);
+ DPSIGN(ret) = xs;
+
+ return ret;
+}
diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h
index d3be351..92dc8fa 100644
--- a/arch/mips/math-emu/ieee754.h
+++ b/arch/mips/math-emu/ieee754.h
@@ -67,6 +67,7 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y);
union ieee754sp ieee754sp_fint(int x);
union ieee754sp ieee754sp_flong(s64 x);
union ieee754sp ieee754sp_fdp(union ieee754dp x);
+union ieee754sp ieee754sp_rint(union ieee754sp x);
int ieee754sp_tint(union ieee754sp x);
s64 ieee754sp_tlong(union ieee754sp x);
@@ -101,6 +102,7 @@ union ieee754dp ieee754dp_neg(union ieee754dp x);
union ieee754dp ieee754dp_fint(int x);
union ieee754dp ieee754dp_flong(s64 x);
union ieee754dp ieee754dp_fsp(union ieee754sp x);
+union ieee754dp ieee754dp_rint(union ieee754dp x);
int ieee754dp_tint(union ieee754dp x);
s64 ieee754dp_tlong(union ieee754dp x);
diff --git a/arch/mips/math-emu/sp_rint.c b/arch/mips/math-emu/sp_rint.c
new file mode 100644
index 0000000..70765b1
--- /dev/null
+++ b/arch/mips/math-emu/sp_rint.c
@@ -0,0 +1,90 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * Copyright (C) 2017 Imagination Technologies, Ltd.
+ * Author: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.
+ */
+
+#include "ieee754sp.h"
+
+union ieee754sp ieee754sp_rint(union ieee754sp x)
+{
+ union ieee754sp ret;
+ u32 residue;
+ int sticky;
+ int round;
+ int odd;
+
+ COMPXDP; /* <-- DP needed for 64-bit mantissa tmp */
+
+ ieee754_clearcx();
+
+ EXPLODEXSP;
+ FLUSHXSP;
+
+ if (xc == IEEE754_CLASS_SNAN)
+ return ieee754sp_nanxcpt(x);
+
+ if ((xc == IEEE754_CLASS_QNAN) ||
+ (xc == IEEE754_CLASS_INF) ||
+ (xc == IEEE754_CLASS_ZERO))
+ return x;
+
+ if (xe >= SP_FBITS)
+ return x;
+
+ if (xe < -1) {
+ residue = xm;
+ round = 0;
+ sticky = residue != 0;
+ xm = 0;
+ } else {
+ residue = xm << (xe + 1);
+ residue <<= 31 - SP_FBITS;
+ round = (residue >> 31) != 0;
+ sticky = (residue << 1) != 0;
+ xm >>= SP_FBITS - xe;
+ }
+
+ odd = (xm & 0x1) != 0x0;
+
+ switch (ieee754_csr.rm) {
+ case FPU_CSR_RN: /* toward nearest */
+ if (round && (sticky || odd))
+ xm++;
+ break;
+ case FPU_CSR_RZ: /* toward zero */
+ break;
+ case FPU_CSR_RU: /* toward +infinity */
+ if ((round || sticky) && !xs)
+ xm++;
+ break;
+ case FPU_CSR_RD: /* toward -infinity */
+ if ((round || sticky) && xs)
+ xm++;
+ break;
+ }
+
+ if (round || sticky)
+ ieee754_setcx(IEEE754_INEXACT);
+
+ ret = ieee754sp_flong(xm);
+ SPSIGN(ret) = xs;
+
+ return ret;
+}
--
2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Aleksandar Markovic <aleksandar.markovic@rt-rk.com> |
|---|---|
| Date | 2017-08-21 14:30 +0200 |
| Subject | [PATCH v2 1/6] MIPS: math-emu: CMP.Sxxx.<D|S>: Prevent occurrences of SIGILL crashes |
| Message-ID | <ugU0a-4jm-25@gated-at.bofh.it> |
| In reply to | #1716392 |
From: Aleksandar Markovic <aleksandar.markovic@imgtec.com> Fix CMP.Sxxx.<D|S> SIGILL crashes by fixing main switch/case statement in fpu_emul() function so that inadvertent fall-troughs are prevented. Consider, let's say, CMP.SAF.S instruction when one of inputs is zero and another input is a signaling NaN. The desired output is zero, and the exception flag "invalid operation" set. For such case, the main portion of the implementation is within "d_fmt" case of the main "switch/case" statement in fpu_emul() function. The execution will follow one of "if-else" branches that doesn't contain "goto cop1scr;" statement, and will therefore reach the end of "d_fmt" case. It will subsequently fall through to the next case, "l_fmt". After following similar pattern, the execution will fall through to the succeeding case, which is "default". The "default" case contains "return SIGILL;" statement only. This means that the caller application will crash with "illegal instruction" message. It is obvious that above described fall-throughs are unnecessary and harmful. This patch rectifies that behavior by providing "break;" statements at the end of cases "d_fmt" and "l_fmt". There are 22 instructions affected by this problem: CMP.<SAF|SEQ|SLE|SLT|SNE|SOR|SUEQ|SULE|SULT|SUN|SUNE>.<D|S>. Signed-off-by: Miodrag Dinic <miodrag.dinic@imgtec.com> Signed-off-by: Goran Ferenc <goran.ferenc@imgtec.com> Signed-off-by: Aleksandar Markovic <aleksandar.markovic@imgtec.com> --- arch/mips/math-emu/cp1emu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index f08a7b4..520a5ac 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -2394,6 +2394,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, break; } } + break; } case l_fmt: @@ -2468,6 +2469,8 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, break; } } + break; + default: return SIGILL; } -- 2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Aleksandar Markovic <aleksandar.markovic@rt-rk.com> |
|---|---|
| Date | 2017-08-21 14:40 +0200 |
| Subject | [PATCH v2 3/6] MIPS: math-emu: CLASS.D: Zero bits 32-63 of the result |
| Message-ID | <ugU9Q-4ml-25@gated-at.bofh.it> |
| In reply to | #1716392 |
From: Aleksandar Markovic <aleksandar.markovic@imgtec.com> Fix content of CLASS.D output bits 32-63 to match hardware behavior. Prior to this patch, bits 32-63 of CLASS.D output were not initialized, causing different 32-63 bits content of CLASS.D, based on circumstances. However, the hardware consistently returns all these bits zeroed. The documentation is not clear whether these bits should be zero or unpredictable. Since technically "all zero" case still can be viewed as belonging to "unpredictable" class of results, it is better to zero bits 32-63. Signed-off-by: Miodrag Dinic <miodrag.dinic@imgtec.com> Signed-off-by: Goran Ferenc <goran.ferenc@imgtec.com> Signed-off-by: Aleksandar Markovic <aleksandar.markovic@imgtec.com> --- arch/mips/math-emu/cp1emu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index cabcf2c..1ad15f8 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -2144,8 +2144,8 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, return SIGILL; DPFROMREG(fs, MIPSInst_FS(ir)); - rv.w = ieee754dp_2008class(fs); - rfmt = w_fmt; + rv.l = ieee754dp_2008class(fs); + rfmt = l_fmt; break; } -- 2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Aleksandar Markovic <aleksandar.markovic@rt-rk.com> |
|---|---|
| Date | 2017-08-21 14:40 +0200 |
| Subject | [PATCH v2 4/6] MIPS: math-emu: Add FP emu debugfs statistics for branches |
| Message-ID | <ugU9Q-4ml-31@gated-at.bofh.it> |
| In reply to | #1716392 |
From: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
Add FP emu debugfs counter for branches.
The new counter is displayed the same way as existing counter, and
its default path is /sys/kernel/debug/mips/fpuemustats/.
The limitation of this counter is that it counts only R6 branch
instructions BC1NEZ and BC1EQZ.
Signed-off-by: Miodrag Dinic <miodrag.dinic@imgtec.com>
Signed-off-by: Goran Ferenc <goran.ferenc@imgtec.com>
Signed-off-by: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
---
arch/mips/include/asm/fpu_emulator.h | 1 +
arch/mips/math-emu/cp1emu.c | 1 +
arch/mips/math-emu/me-debugfs.c | 1 +
3 files changed, 3 insertions(+)
diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h
index c05369e..7f5cf1f 100644
--- a/arch/mips/include/asm/fpu_emulator.h
+++ b/arch/mips/include/asm/fpu_emulator.h
@@ -36,6 +36,7 @@ struct mips_fpu_emulator_stats {
unsigned long emulated;
unsigned long loads;
unsigned long stores;
+ unsigned long branches;
unsigned long cp1ops;
unsigned long cp1xops;
unsigned long errors;
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 1ad15f8..40c74e1 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -1230,6 +1230,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
break;
}
branch_common:
+ MIPS_FPU_EMU_INC_STATS(branches);
set_delay_slot(xcp);
if (cond) {
/*
diff --git a/arch/mips/math-emu/me-debugfs.c b/arch/mips/math-emu/me-debugfs.c
index be650ed..78b26c8 100644
--- a/arch/mips/math-emu/me-debugfs.c
+++ b/arch/mips/math-emu/me-debugfs.c
@@ -53,6 +53,7 @@ do { \
FPU_STAT_CREATE(emulated);
FPU_STAT_CREATE(loads);
FPU_STAT_CREATE(stores);
+ FPU_STAT_CREATE(branches);
FPU_STAT_CREATE(cp1ops);
FPU_STAT_CREATE(cp1xops);
FPU_STAT_CREATE(errors);
--
2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Aleksandar Markovic <aleksandar.markovic@rt-rk.com> |
|---|---|
| Date | 2017-08-21 14:40 +0200 |
| Subject | [PATCH v2 5/6] MIPS: math-emu: Add FP emu debugfs clear functionality |
| Message-ID | <ugU9Q-4ml-33@gated-at.bofh.it> |
| In reply to | #1716392 |
From: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
Add capability for the user to clear all FP emu debugfs counters.
This is achieved by having a special debugfs file "fpuemustats_clear"
(under default location "/sys/kernel/debug/mips"). Each access to the
file results in setting all counters to zero (it is enough, let's say,
to issue a "cat /sys/kernel/debug/mips/fpuemustats_clear").
This functionality already exists for R2 emulation statistics,
but was missing for FP emulation statistics. The implementation in
this patch is consistent with its R2 emulation counterpart.
Signed-off-by: Miodrag Dinic <miodrag.dinic@imgtec.com>
Signed-off-by: Goran Ferenc <goran.ferenc@imgtec.com>
Signed-off-by: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
---
arch/mips/math-emu/me-debugfs.c | 38 +++++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/arch/mips/math-emu/me-debugfs.c b/arch/mips/math-emu/me-debugfs.c
index 78b26c8..f080493 100644
--- a/arch/mips/math-emu/me-debugfs.c
+++ b/arch/mips/math-emu/me-debugfs.c
@@ -28,15 +28,51 @@ static int fpuemu_stat_get(void *data, u64 *val)
}
DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n");
+static int fpuemustats_clear_show(struct seq_file *s, void *unused)
+{
+ __this_cpu_write((fpuemustats).emulated, 0);
+ __this_cpu_write((fpuemustats).loads, 0);
+ __this_cpu_write((fpuemustats).stores, 0);
+ __this_cpu_write((fpuemustats).branches, 0);
+ __this_cpu_write((fpuemustats).cp1ops, 0);
+ __this_cpu_write((fpuemustats).cp1xops, 0);
+ __this_cpu_write((fpuemustats).errors, 0);
+ __this_cpu_write((fpuemustats).ieee754_inexact, 0);
+ __this_cpu_write((fpuemustats).ieee754_underflow, 0);
+ __this_cpu_write((fpuemustats).ieee754_overflow, 0);
+ __this_cpu_write((fpuemustats).ieee754_zerodiv, 0);
+ __this_cpu_write((fpuemustats).ieee754_invalidop, 0);
+ __this_cpu_write((fpuemustats).ds_emul, 0);
+
+ return 0;
+}
+
+static int fpuemustats_clear_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, fpuemustats_clear_show, inode->i_private);
+}
+
+static const struct file_operations fpuemustats_clear_fops = {
+ .open = fpuemustats_clear_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static int __init debugfs_fpuemu(void)
{
- struct dentry *d, *dir;
+ struct dentry *d, *dir, *reset_file;
if (!mips_debugfs_dir)
return -ENODEV;
dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir);
if (!dir)
return -ENOMEM;
+ reset_file = debugfs_create_file("fpuemustats_clear", 0444,
+ mips_debugfs_dir, NULL,
+ &fpuemustats_clear_fops);
+ if (!reset_file)
+ return -ENOMEM;
#define FPU_EMU_STAT_OFFSET(m) \
offsetof(struct mips_fpu_emulator_stats, m)
--
2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Aleksandar Markovic <aleksandar.markovic@rt-rk.com> |
|---|---|
| Date | 2017-08-21 14:40 +0200 |
| Subject | [PATCH v2 6/6] MIPS: math-emu: Add FP emu debugfs stats for individual instructions |
| Message-ID | <ugU9Q-4ml-29@gated-at.bofh.it> |
| In reply to | #1716392 |
From: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
Add FP emulation debugfs statistics for individual instructions. The
debugfs files that contain counter values are placed in a separate
directory called "instructions". This means that the default path for
these new stat is "/sys/kernel/debug/mips/fpuemustats/instructions".
Each instruction counter is mapped to the debugfs file that has the
same name as instruction name. The lowercase is choosen as more
commonly used case for instruction names.
One example of usage:
mips_host::/sys/kernel/debug/mips/fpuemustats/instructions # grep "" *
The shortened output of this command is:
abs.d:34
abs.s:5711
add.d:10401
add.s:399307
bc1eqz:3199
...
...
...
sub.s:167211
trunc.l.d:375
trunc.l.s:8054
trunc.w.d:421
trunc.w.s:27032
The limitation of this patch is that it handles R6 FP emulation
instructions only. There are altogether 114 handled instructions.
Signed-off-by: Miodrag Dinic <miodrag.dinic@imgtec.com>
Signed-off-by: Goran Ferenc <goran.ferenc@imgtec.com>
Signed-off-by: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
---
arch/mips/include/asm/fpu_emulator.h | 115 ++++++++++++++
arch/mips/math-emu/cp1emu.c | 258 ++++++++++++++++++++++++++++++++
arch/mips/math-emu/me-debugfs.c | 281 ++++++++++++++++++++++++++++++++++-
3 files changed, 650 insertions(+), 4 deletions(-)
diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h
index 7f5cf1f..c7544de 100644
--- a/arch/mips/include/asm/fpu_emulator.h
+++ b/arch/mips/include/asm/fpu_emulator.h
@@ -46,6 +46,121 @@ struct mips_fpu_emulator_stats {
unsigned long ieee754_zerodiv;
unsigned long ieee754_invalidop;
unsigned long ds_emul;
+
+ unsigned long abs_s;
+ unsigned long abs_d;
+ unsigned long add_s;
+ unsigned long add_d;
+ unsigned long bc1eqz;
+ unsigned long bc1nez;
+ unsigned long ceil_w_s;
+ unsigned long ceil_w_d;
+ unsigned long ceil_l_s;
+ unsigned long ceil_l_d;
+ unsigned long class_s;
+ unsigned long class_d;
+ unsigned long cmp_af_s;
+ unsigned long cmp_af_d;
+ unsigned long cmp_eq_s;
+ unsigned long cmp_eq_d;
+ unsigned long cmp_le_s;
+ unsigned long cmp_le_d;
+ unsigned long cmp_lt_s;
+ unsigned long cmp_lt_d;
+ unsigned long cmp_ne_s;
+ unsigned long cmp_ne_d;
+ unsigned long cmp_or_s;
+ unsigned long cmp_or_d;
+ unsigned long cmp_ueq_s;
+ unsigned long cmp_ueq_d;
+ unsigned long cmp_ule_s;
+ unsigned long cmp_ule_d;
+ unsigned long cmp_ult_s;
+ unsigned long cmp_ult_d;
+ unsigned long cmp_un_s;
+ unsigned long cmp_un_d;
+ unsigned long cmp_une_s;
+ unsigned long cmp_une_d;
+ unsigned long cmp_saf_s;
+ unsigned long cmp_saf_d;
+ unsigned long cmp_seq_s;
+ unsigned long cmp_seq_d;
+ unsigned long cmp_sle_s;
+ unsigned long cmp_sle_d;
+ unsigned long cmp_slt_s;
+ unsigned long cmp_slt_d;
+ unsigned long cmp_sne_s;
+ unsigned long cmp_sne_d;
+ unsigned long cmp_sor_s;
+ unsigned long cmp_sor_d;
+ unsigned long cmp_sueq_s;
+ unsigned long cmp_sueq_d;
+ unsigned long cmp_sule_s;
+ unsigned long cmp_sule_d;
+ unsigned long cmp_sult_s;
+ unsigned long cmp_sult_d;
+ unsigned long cmp_sun_s;
+ unsigned long cmp_sun_d;
+ unsigned long cmp_sune_s;
+ unsigned long cmp_sune_d;
+ unsigned long cvt_d_l;
+ unsigned long cvt_d_s;
+ unsigned long cvt_d_w;
+ unsigned long cvt_l_s;
+ unsigned long cvt_l_d;
+ unsigned long cvt_s_d;
+ unsigned long cvt_s_l;
+ unsigned long cvt_s_w;
+ unsigned long cvt_w_s;
+ unsigned long cvt_w_d;
+ unsigned long div_s;
+ unsigned long div_d;
+ unsigned long floor_w_s;
+ unsigned long floor_w_d;
+ unsigned long floor_l_s;
+ unsigned long floor_l_d;
+ unsigned long maddf_s;
+ unsigned long maddf_d;
+ unsigned long max_s;
+ unsigned long max_d;
+ unsigned long maxa_s;
+ unsigned long maxa_d;
+ unsigned long min_s;
+ unsigned long min_d;
+ unsigned long mina_s;
+ unsigned long mina_d;
+ unsigned long mov_s;
+ unsigned long mov_d;
+ unsigned long msubf_s;
+ unsigned long msubf_d;
+ unsigned long mul_s;
+ unsigned long mul_d;
+ unsigned long neg_s;
+ unsigned long neg_d;
+ unsigned long recip_s;
+ unsigned long recip_d;
+ unsigned long rint_s;
+ unsigned long rint_d;
+ unsigned long round_w_s;
+ unsigned long round_w_d;
+ unsigned long round_l_s;
+ unsigned long round_l_d;
+ unsigned long rsqrt_s;
+ unsigned long rsqrt_d;
+ unsigned long sel_s;
+ unsigned long sel_d;
+ unsigned long seleqz_s;
+ unsigned long seleqz_d;
+ unsigned long selnez_s;
+ unsigned long selnez_d;
+ unsigned long sqrt_s;
+ unsigned long sqrt_d;
+ unsigned long sub_s;
+ unsigned long sub_d;
+ unsigned long trunc_w_s;
+ unsigned long trunc_w_d;
+ unsigned long trunc_l_s;
+ unsigned long trunc_l_d;
};
DECLARE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 40c74e1..b1aeb62 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -1195,9 +1195,11 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
bit0 = get_fpr32(fpr, 0) & 0x1;
switch (MIPSInst_RS(ir)) {
case bc1eqz_op:
+ MIPS_FPU_EMU_INC_STATS(bc1eqz);
cond = bit0 == 0;
break;
case bc1nez_op:
+ MIPS_FPU_EMU_INC_STATS(bc1nez);
cond = bit0 != 0;
break;
}
@@ -1683,15 +1685,19 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
switch (MIPSInst_FUNC(ir)) {
/* binary ops */
case fadd_op:
+ MIPS_FPU_EMU_INC_STATS(add_s);
handler.b = ieee754sp_add;
goto scopbop;
case fsub_op:
+ MIPS_FPU_EMU_INC_STATS(sub_s);
handler.b = ieee754sp_sub;
goto scopbop;
case fmul_op:
+ MIPS_FPU_EMU_INC_STATS(mul_s);
handler.b = ieee754sp_mul;
goto scopbop;
case fdiv_op:
+ MIPS_FPU_EMU_INC_STATS(div_s);
handler.b = ieee754sp_div;
goto scopbop;
@@ -1700,6 +1706,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_2_3_4_5_r)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(sqrt_s);
handler.u = ieee754sp_sqrt;
goto scopuop;
@@ -1712,6 +1719,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_4_5_64_r2_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(rsqrt_s);
handler.u = fpemu_sp_rsqrt;
goto scopuop;
@@ -1719,6 +1727,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_4_5_64_r2_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(recip_s);
handler.u = fpemu_sp_recip;
goto scopuop;
@@ -1755,6 +1764,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(seleqz_s);
SPFROMREG(rv.s, MIPSInst_FT(ir));
if (rv.w & 0x1)
rv.w = 0;
@@ -1766,6 +1776,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(selnez_s);
SPFROMREG(rv.s, MIPSInst_FT(ir));
if (rv.w & 0x1)
SPFROMREG(rv.s, MIPSInst_FS(ir));
@@ -1779,6 +1790,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(maddf_s);
SPFROMREG(ft, MIPSInst_FT(ir));
SPFROMREG(fs, MIPSInst_FS(ir));
SPFROMREG(fd, MIPSInst_FD(ir));
@@ -1792,6 +1804,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(msubf_s);
SPFROMREG(ft, MIPSInst_FT(ir));
SPFROMREG(fs, MIPSInst_FS(ir));
SPFROMREG(fd, MIPSInst_FD(ir));
@@ -1805,6 +1818,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(rint_s);
SPFROMREG(fs, MIPSInst_FS(ir));
rv.s = ieee754sp_rint(fs);
goto copcsr;
@@ -1816,6 +1830,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(class_s);
SPFROMREG(fs, MIPSInst_FS(ir));
rv.w = ieee754sp_2008class(fs);
rfmt = w_fmt;
@@ -1828,6 +1843,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(min_s);
SPFROMREG(ft, MIPSInst_FT(ir));
SPFROMREG(fs, MIPSInst_FS(ir));
rv.s = ieee754sp_fmin(fs, ft);
@@ -1840,6 +1856,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(mina_s);
SPFROMREG(ft, MIPSInst_FT(ir));
SPFROMREG(fs, MIPSInst_FS(ir));
rv.s = ieee754sp_fmina(fs, ft);
@@ -1852,6 +1869,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(max_s);
SPFROMREG(ft, MIPSInst_FT(ir));
SPFROMREG(fs, MIPSInst_FS(ir));
rv.s = ieee754sp_fmax(fs, ft);
@@ -1864,6 +1882,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(maxa_s);
SPFROMREG(ft, MIPSInst_FT(ir));
SPFROMREG(fs, MIPSInst_FS(ir));
rv.s = ieee754sp_fmaxa(fs, ft);
@@ -1871,15 +1890,18 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
}
case fabs_op:
+ MIPS_FPU_EMU_INC_STATS(abs_s);
handler.u = ieee754sp_abs;
goto scopuop;
case fneg_op:
+ MIPS_FPU_EMU_INC_STATS(neg_s);
handler.u = ieee754sp_neg;
goto scopuop;
case fmov_op:
/* an easy one */
+ MIPS_FPU_EMU_INC_STATS(mov_s);
SPFROMREG(rv.s, MIPSInst_FS(ir));
goto copcsr;
@@ -1922,12 +1944,14 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
return SIGILL; /* not defined */
case fcvtd_op:
+ MIPS_FPU_EMU_INC_STATS(cvt_d_s);
SPFROMREG(fs, MIPSInst_FS(ir));
rv.d = ieee754dp_fsp(fs);
rfmt = d_fmt;
goto copcsr;
case fcvtw_op:
+ MIPS_FPU_EMU_INC_STATS(cvt_w_s);
SPFROMREG(fs, MIPSInst_FS(ir));
rv.w = ieee754sp_tint(fs);
rfmt = w_fmt;
@@ -1940,6 +1964,15 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_2_3_4_5_r)
return SIGILL;
+ if (MIPSInst_FUNC(ir) == fceil_op)
+ MIPS_FPU_EMU_INC_STATS(ceil_w_s);
+ if (MIPSInst_FUNC(ir) == ffloor_op)
+ MIPS_FPU_EMU_INC_STATS(floor_w_s);
+ if (MIPSInst_FUNC(ir) == fround_op)
+ MIPS_FPU_EMU_INC_STATS(round_w_s);
+ if (MIPSInst_FUNC(ir) == ftrunc_op)
+ MIPS_FPU_EMU_INC_STATS(trunc_w_s);
+
oldrm = ieee754_csr.rm;
SPFROMREG(fs, MIPSInst_FS(ir));
ieee754_csr.rm = MIPSInst_FUNC(ir);
@@ -1952,6 +1985,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(sel_s);
SPFROMREG(fd, MIPSInst_FD(ir));
if (fd.bits & 0x1)
SPFROMREG(rv.s, MIPSInst_FT(ir));
@@ -1963,6 +1997,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_3_4_5_64_r2_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(cvt_l_s);
SPFROMREG(fs, MIPSInst_FS(ir));
rv.l = ieee754sp_tlong(fs);
rfmt = l_fmt;
@@ -1975,6 +2010,15 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_3_4_5_64_r2_r6)
return SIGILL;
+ if (MIPSInst_FUNC(ir) == fceill_op)
+ MIPS_FPU_EMU_INC_STATS(ceil_l_s);
+ if (MIPSInst_FUNC(ir) == ffloorl_op)
+ MIPS_FPU_EMU_INC_STATS(floor_l_s);
+ if (MIPSInst_FUNC(ir) == froundl_op)
+ MIPS_FPU_EMU_INC_STATS(round_l_s);
+ if (MIPSInst_FUNC(ir) == ftruncl_op)
+ MIPS_FPU_EMU_INC_STATS(trunc_l_s);
+
oldrm = ieee754_csr.rm;
SPFROMREG(fs, MIPSInst_FS(ir));
ieee754_csr.rm = MIPSInst_FUNC(ir);
@@ -2016,15 +2060,19 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
switch (MIPSInst_FUNC(ir)) {
/* binary ops */
case fadd_op:
+ MIPS_FPU_EMU_INC_STATS(add_d);
handler.b = ieee754dp_add;
goto dcopbop;
case fsub_op:
+ MIPS_FPU_EMU_INC_STATS(sub_d);
handler.b = ieee754dp_sub;
goto dcopbop;
case fmul_op:
+ MIPS_FPU_EMU_INC_STATS(mul_d);
handler.b = ieee754dp_mul;
goto dcopbop;
case fdiv_op:
+ MIPS_FPU_EMU_INC_STATS(div_d);
handler.b = ieee754dp_div;
goto dcopbop;
@@ -2033,6 +2081,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_2_3_4_5_r)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(sqrt_d);
handler.u = ieee754dp_sqrt;
goto dcopuop;
/*
@@ -2044,12 +2093,14 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_4_5_64_r2_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(rsqrt_d);
handler.u = fpemu_dp_rsqrt;
goto dcopuop;
case frecip_op:
if (!cpu_has_mips_4_5_64_r2_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(recip_d);
handler.u = fpemu_dp_recip;
goto dcopuop;
case fmovc_op:
@@ -2083,6 +2134,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(seleqz_d);
DPFROMREG(rv.d, MIPSInst_FT(ir));
if (rv.l & 0x1)
rv.l = 0;
@@ -2094,6 +2146,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(selnez_d);
DPFROMREG(rv.d, MIPSInst_FT(ir));
if (rv.l & 0x1)
DPFROMREG(rv.d, MIPSInst_FS(ir));
@@ -2107,6 +2160,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(maddf_d);
DPFROMREG(ft, MIPSInst_FT(ir));
DPFROMREG(fs, MIPSInst_FS(ir));
DPFROMREG(fd, MIPSInst_FD(ir));
@@ -2120,6 +2174,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(msubf_d);
DPFROMREG(ft, MIPSInst_FT(ir));
DPFROMREG(fs, MIPSInst_FS(ir));
DPFROMREG(fd, MIPSInst_FD(ir));
@@ -2133,6 +2188,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(rint_d);
DPFROMREG(fs, MIPSInst_FS(ir));
rv.d = ieee754dp_rint(fs);
goto copcsr;
@@ -2144,6 +2200,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(class_d);
DPFROMREG(fs, MIPSInst_FS(ir));
rv.l = ieee754dp_2008class(fs);
rfmt = l_fmt;
@@ -2156,6 +2213,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(min_d);
DPFROMREG(ft, MIPSInst_FT(ir));
DPFROMREG(fs, MIPSInst_FS(ir));
rv.d = ieee754dp_fmin(fs, ft);
@@ -2168,6 +2226,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(mina_d);
DPFROMREG(ft, MIPSInst_FT(ir));
DPFROMREG(fs, MIPSInst_FS(ir));
rv.d = ieee754dp_fmina(fs, ft);
@@ -2180,6 +2239,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(max_d);
DPFROMREG(ft, MIPSInst_FT(ir));
DPFROMREG(fs, MIPSInst_FS(ir));
rv.d = ieee754dp_fmax(fs, ft);
@@ -2192,6 +2252,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(maxa_d);
DPFROMREG(ft, MIPSInst_FT(ir));
DPFROMREG(fs, MIPSInst_FS(ir));
rv.d = ieee754dp_fmaxa(fs, ft);
@@ -2199,15 +2260,18 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
}
case fabs_op:
+ MIPS_FPU_EMU_INC_STATS(abs_d);
handler.u = ieee754dp_abs;
goto dcopuop;
case fneg_op:
+ MIPS_FPU_EMU_INC_STATS(neg_d);
handler.u = ieee754dp_neg;
goto dcopuop;
case fmov_op:
/* an easy one */
+ MIPS_FPU_EMU_INC_STATS(mov_d);
DPFROMREG(rv.d, MIPSInst_FS(ir));
goto copcsr;
@@ -2227,6 +2291,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
* unary conv ops
*/
case fcvts_op:
+ MIPS_FPU_EMU_INC_STATS(cvt_s_d);
DPFROMREG(fs, MIPSInst_FS(ir));
rv.s = ieee754sp_fdp(fs);
rfmt = s_fmt;
@@ -2236,6 +2301,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
return SIGILL; /* not defined */
case fcvtw_op:
+ MIPS_FPU_EMU_INC_STATS(cvt_w_d);
DPFROMREG(fs, MIPSInst_FS(ir));
rv.w = ieee754dp_tint(fs); /* wrong */
rfmt = w_fmt;
@@ -2248,6 +2314,15 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_2_3_4_5_r)
return SIGILL;
+ if (MIPSInst_FUNC(ir) == fceil_op)
+ MIPS_FPU_EMU_INC_STATS(ceil_w_d);
+ if (MIPSInst_FUNC(ir) == ffloor_op)
+ MIPS_FPU_EMU_INC_STATS(floor_w_d);
+ if (MIPSInst_FUNC(ir) == fround_op)
+ MIPS_FPU_EMU_INC_STATS(round_w_d);
+ if (MIPSInst_FUNC(ir) == ftrunc_op)
+ MIPS_FPU_EMU_INC_STATS(trunc_w_d);
+
oldrm = ieee754_csr.rm;
DPFROMREG(fs, MIPSInst_FS(ir));
ieee754_csr.rm = MIPSInst_FUNC(ir);
@@ -2260,6 +2335,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(sel_d);
DPFROMREG(fd, MIPSInst_FD(ir));
if (fd.bits & 0x1)
DPFROMREG(rv.d, MIPSInst_FT(ir));
@@ -2271,6 +2347,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_3_4_5_64_r2_r6)
return SIGILL;
+ MIPS_FPU_EMU_INC_STATS(cvt_l_d);
DPFROMREG(fs, MIPSInst_FS(ir));
rv.l = ieee754dp_tlong(fs);
rfmt = l_fmt;
@@ -2283,6 +2360,15 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (!cpu_has_mips_3_4_5_64_r2_r6)
return SIGILL;
+ if (MIPSInst_FUNC(ir) == fceill_op)
+ MIPS_FPU_EMU_INC_STATS(ceil_l_d);
+ if (MIPSInst_FUNC(ir) == ffloorl_op)
+ MIPS_FPU_EMU_INC_STATS(floor_l_d);
+ if (MIPSInst_FUNC(ir) == froundl_op)
+ MIPS_FPU_EMU_INC_STATS(round_l_d);
+ if (MIPSInst_FUNC(ir) == ftruncl_op)
+ MIPS_FPU_EMU_INC_STATS(trunc_l_d);
+
oldrm = ieee754_csr.rm;
DPFROMREG(fs, MIPSInst_FS(ir));
ieee754_csr.rm = MIPSInst_FUNC(ir);
@@ -2324,12 +2410,14 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
switch (MIPSInst_FUNC(ir)) {
case fcvts_op:
/* convert word to single precision real */
+ MIPS_FPU_EMU_INC_STATS(cvt_s_w);
SPFROMREG(fs, MIPSInst_FS(ir));
rv.s = ieee754sp_fint(fs.bits);
rfmt = s_fmt;
goto copcsr;
case fcvtd_op:
/* convert word to double precision real */
+ MIPS_FPU_EMU_INC_STATS(cvt_d_w);
SPFROMREG(fs, MIPSInst_FS(ir));
rv.d = ieee754dp_fint(fs.bits);
rfmt = d_fmt;
@@ -2349,6 +2437,90 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
(MIPSInst_FUNC(ir) & 0x20))
return SIGILL;
+ if (!sig) {
+ if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
+ switch (cmpop) {
+ case 0:
+ MIPS_FPU_EMU_INC_STATS(cmp_af_s);
+ break;
+ case 1:
+ MIPS_FPU_EMU_INC_STATS(cmp_un_s);
+ break;
+ case 2:
+ MIPS_FPU_EMU_INC_STATS(cmp_eq_s);
+ break;
+ case 3:
+ MIPS_FPU_EMU_INC_STATS(cmp_ueq_s);
+ break;
+ case 4:
+ MIPS_FPU_EMU_INC_STATS(cmp_lt_s);
+ break;
+ case 5:
+ MIPS_FPU_EMU_INC_STATS(cmp_ult_s);
+ break;
+ case 6:
+ MIPS_FPU_EMU_INC_STATS(cmp_le_s);
+ break;
+ case 7:
+ MIPS_FPU_EMU_INC_STATS(cmp_ule_s);
+ break;
+ }
+ } else {
+ switch (cmpop) {
+ case 1:
+ MIPS_FPU_EMU_INC_STATS(cmp_or_s);
+ break;
+ case 2:
+ MIPS_FPU_EMU_INC_STATS(cmp_une_s);
+ break;
+ case 3:
+ MIPS_FPU_EMU_INC_STATS(cmp_ne_s);
+ break;
+ }
+ }
+ } else {
+ if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
+ switch (cmpop) {
+ case 0:
+ MIPS_FPU_EMU_INC_STATS(cmp_saf_s);
+ break;
+ case 1:
+ MIPS_FPU_EMU_INC_STATS(cmp_sun_s);
+ break;
+ case 2:
+ MIPS_FPU_EMU_INC_STATS(cmp_seq_s);
+ break;
+ case 3:
+ MIPS_FPU_EMU_INC_STATS(cmp_sueq_s);
+ break;
+ case 4:
+ MIPS_FPU_EMU_INC_STATS(cmp_slt_s);
+ break;
+ case 5:
+ MIPS_FPU_EMU_INC_STATS(cmp_sult_s);
+ break;
+ case 6:
+ MIPS_FPU_EMU_INC_STATS(cmp_sle_s);
+ break;
+ case 7:
+ MIPS_FPU_EMU_INC_STATS(cmp_sule_s);
+ break;
+ }
+ } else {
+ switch (cmpop) {
+ case 1:
+ MIPS_FPU_EMU_INC_STATS(cmp_sor_s);
+ break;
+ case 2:
+ MIPS_FPU_EMU_INC_STATS(cmp_sune_s);
+ break;
+ case 3:
+ MIPS_FPU_EMU_INC_STATS(cmp_sne_s);
+ break;
+ }
+ }
+ }
+
/* fmt is w_fmt for single precision so fix it */
rfmt = s_fmt;
/* default to false */
@@ -2406,11 +2578,13 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
switch (MIPSInst_FUNC(ir)) {
case fcvts_op:
/* convert long to single precision real */
+ MIPS_FPU_EMU_INC_STATS(cvt_s_l);
rv.s = ieee754sp_flong(bits);
rfmt = s_fmt;
goto copcsr;
case fcvtd_op:
/* convert long to double precision real */
+ MIPS_FPU_EMU_INC_STATS(cvt_d_l);
rv.d = ieee754dp_flong(bits);
rfmt = d_fmt;
goto copcsr;
@@ -2424,6 +2598,90 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
(MIPSInst_FUNC(ir) & 0x20))
return SIGILL;
+ if (!sig) {
+ if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
+ switch (cmpop) {
+ case 0:
+ MIPS_FPU_EMU_INC_STATS(cmp_af_d);
+ break;
+ case 1:
+ MIPS_FPU_EMU_INC_STATS(cmp_un_d);
+ break;
+ case 2:
+ MIPS_FPU_EMU_INC_STATS(cmp_eq_d);
+ break;
+ case 3:
+ MIPS_FPU_EMU_INC_STATS(cmp_ueq_d);
+ break;
+ case 4:
+ MIPS_FPU_EMU_INC_STATS(cmp_lt_d);
+ break;
+ case 5:
+ MIPS_FPU_EMU_INC_STATS(cmp_ult_d);
+ break;
+ case 6:
+ MIPS_FPU_EMU_INC_STATS(cmp_le_d);
+ break;
+ case 7:
+ MIPS_FPU_EMU_INC_STATS(cmp_ule_d);
+ break;
+ }
+ } else {
+ switch (cmpop) {
+ case 1:
+ MIPS_FPU_EMU_INC_STATS(cmp_or_d);
+ break;
+ case 2:
+ MIPS_FPU_EMU_INC_STATS(cmp_une_d);
+ break;
+ case 3:
+ MIPS_FPU_EMU_INC_STATS(cmp_ne_d);
+ break;
+ }
+ }
+ } else {
+ if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
+ switch (cmpop) {
+ case 0:
+ MIPS_FPU_EMU_INC_STATS(cmp_saf_d);
+ break;
+ case 1:
+ MIPS_FPU_EMU_INC_STATS(cmp_sun_d);
+ break;
+ case 2:
+ MIPS_FPU_EMU_INC_STATS(cmp_seq_d);
+ break;
+ case 3:
+ MIPS_FPU_EMU_INC_STATS(cmp_sueq_d);
+ break;
+ case 4:
+ MIPS_FPU_EMU_INC_STATS(cmp_slt_d);
+ break;
+ case 5:
+ MIPS_FPU_EMU_INC_STATS(cmp_sult_d);
+ break;
+ case 6:
+ MIPS_FPU_EMU_INC_STATS(cmp_sle_d);
+ break;
+ case 7:
+ MIPS_FPU_EMU_INC_STATS(cmp_sule_d);
+ break;
+ }
+ } else {
+ switch (cmpop) {
+ case 1:
+ MIPS_FPU_EMU_INC_STATS(cmp_sor_d);
+ break;
+ case 2:
+ MIPS_FPU_EMU_INC_STATS(cmp_sune_d);
+ break;
+ case 3:
+ MIPS_FPU_EMU_INC_STATS(cmp_sne_d);
+ break;
+ }
+ }
+ }
+
/* fmt is l_fmt for double precision so fix it */
rfmt = d_fmt;
/* default to false */
diff --git a/arch/mips/math-emu/me-debugfs.c b/arch/mips/math-emu/me-debugfs.c
index f080493..8c0ec15 100644
--- a/arch/mips/math-emu/me-debugfs.c
+++ b/arch/mips/math-emu/me-debugfs.c
@@ -28,6 +28,26 @@ static int fpuemu_stat_get(void *data, u64 *val)
}
DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n");
+/*
+ * Used to obtain names for a debugfs instruction counter, given field name
+ * in fpuemustats structure. For example, for input "cmp_sueq_d", the output
+ * would be "cmp.sueq.d". This is needed since dots are not allowed to be
+ * used in structure field names, and are, on the other hand, desired to be
+ * used in debugfs item names to be clearly associated to corresponding
+ * MIPS FPU instructions.
+ */
+static void adjust_instruction_counter_name(char *out_name, char *in_name)
+{
+ int i = 0;
+
+ strcpy(out_name, in_name);
+ while (in_name[i] != '\0') {
+ if (out_name[i] == '_')
+ out_name[i] = '.';
+ i++;
+ }
+}
+
static int fpuemustats_clear_show(struct seq_file *s, void *unused)
{
__this_cpu_write((fpuemustats).emulated, 0);
@@ -44,6 +64,121 @@ static int fpuemustats_clear_show(struct seq_file *s, void *unused)
__this_cpu_write((fpuemustats).ieee754_invalidop, 0);
__this_cpu_write((fpuemustats).ds_emul, 0);
+ __this_cpu_write((fpuemustats).abs_s, 0);
+ __this_cpu_write((fpuemustats).abs_d, 0);
+ __this_cpu_write((fpuemustats).add_s, 0);
+ __this_cpu_write((fpuemustats).add_d, 0);
+ __this_cpu_write((fpuemustats).bc1eqz, 0);
+ __this_cpu_write((fpuemustats).bc1nez, 0);
+ __this_cpu_write((fpuemustats).ceil_w_s, 0);
+ __this_cpu_write((fpuemustats).ceil_w_d, 0);
+ __this_cpu_write((fpuemustats).ceil_l_s, 0);
+ __this_cpu_write((fpuemustats).ceil_l_d, 0);
+ __this_cpu_write((fpuemustats).class_s, 0);
+ __this_cpu_write((fpuemustats).class_d, 0);
+ __this_cpu_write((fpuemustats).cmp_af_s, 0);
+ __this_cpu_write((fpuemustats).cmp_af_d, 0);
+ __this_cpu_write((fpuemustats).cmp_eq_s, 0);
+ __this_cpu_write((fpuemustats).cmp_eq_d, 0);
+ __this_cpu_write((fpuemustats).cmp_le_s, 0);
+ __this_cpu_write((fpuemustats).cmp_le_d, 0);
+ __this_cpu_write((fpuemustats).cmp_lt_s, 0);
+ __this_cpu_write((fpuemustats).cmp_lt_d, 0);
+ __this_cpu_write((fpuemustats).cmp_ne_s, 0);
+ __this_cpu_write((fpuemustats).cmp_ne_d, 0);
+ __this_cpu_write((fpuemustats).cmp_or_s, 0);
+ __this_cpu_write((fpuemustats).cmp_or_d, 0);
+ __this_cpu_write((fpuemustats).cmp_ueq_s, 0);
+ __this_cpu_write((fpuemustats).cmp_ueq_d, 0);
+ __this_cpu_write((fpuemustats).cmp_ule_s, 0);
+ __this_cpu_write((fpuemustats).cmp_ule_d, 0);
+ __this_cpu_write((fpuemustats).cmp_ult_s, 0);
+ __this_cpu_write((fpuemustats).cmp_ult_d, 0);
+ __this_cpu_write((fpuemustats).cmp_un_s, 0);
+ __this_cpu_write((fpuemustats).cmp_un_d, 0);
+ __this_cpu_write((fpuemustats).cmp_une_s, 0);
+ __this_cpu_write((fpuemustats).cmp_une_d, 0);
+ __this_cpu_write((fpuemustats).cmp_saf_s, 0);
+ __this_cpu_write((fpuemustats).cmp_saf_d, 0);
+ __this_cpu_write((fpuemustats).cmp_seq_s, 0);
+ __this_cpu_write((fpuemustats).cmp_seq_d, 0);
+ __this_cpu_write((fpuemustats).cmp_sle_s, 0);
+ __this_cpu_write((fpuemustats).cmp_sle_d, 0);
+ __this_cpu_write((fpuemustats).cmp_slt_s, 0);
+ __this_cpu_write((fpuemustats).cmp_slt_d, 0);
+ __this_cpu_write((fpuemustats).cmp_sne_s, 0);
+ __this_cpu_write((fpuemustats).cmp_sne_d, 0);
+ __this_cpu_write((fpuemustats).cmp_sor_s, 0);
+ __this_cpu_write((fpuemustats).cmp_sor_d, 0);
+ __this_cpu_write((fpuemustats).cmp_sueq_s, 0);
+ __this_cpu_write((fpuemustats).cmp_sueq_d, 0);
+ __this_cpu_write((fpuemustats).cmp_sule_s, 0);
+ __this_cpu_write((fpuemustats).cmp_sule_d, 0);
+ __this_cpu_write((fpuemustats).cmp_sult_s, 0);
+ __this_cpu_write((fpuemustats).cmp_sult_d, 0);
+ __this_cpu_write((fpuemustats).cmp_sun_s, 0);
+ __this_cpu_write((fpuemustats).cmp_sun_d, 0);
+ __this_cpu_write((fpuemustats).cmp_sune_s, 0);
+ __this_cpu_write((fpuemustats).cmp_sune_d, 0);
+ __this_cpu_write((fpuemustats).cvt_d_l, 0);
+ __this_cpu_write((fpuemustats).cvt_d_s, 0);
+ __this_cpu_write((fpuemustats).cvt_d_w, 0);
+ __this_cpu_write((fpuemustats).cvt_l_s, 0);
+ __this_cpu_write((fpuemustats).cvt_l_d, 0);
+ __this_cpu_write((fpuemustats).cvt_s_d, 0);
+ __this_cpu_write((fpuemustats).cvt_s_l, 0);
+ __this_cpu_write((fpuemustats).cvt_s_w, 0);
+ __this_cpu_write((fpuemustats).cvt_w_s, 0);
+ __this_cpu_write((fpuemustats).cvt_w_d, 0);
+ __this_cpu_write((fpuemustats).div_s, 0);
+ __this_cpu_write((fpuemustats).div_d, 0);
+ __this_cpu_write((fpuemustats).floor_w_s, 0);
+ __this_cpu_write((fpuemustats).floor_w_d, 0);
+ __this_cpu_write((fpuemustats).floor_l_s, 0);
+ __this_cpu_write((fpuemustats).floor_l_d, 0);
+ __this_cpu_write((fpuemustats).maddf_s, 0);
+ __this_cpu_write((fpuemustats).maddf_d, 0);
+ __this_cpu_write((fpuemustats).max_s, 0);
+ __this_cpu_write((fpuemustats).max_d, 0);
+ __this_cpu_write((fpuemustats).maxa_s, 0);
+ __this_cpu_write((fpuemustats).maxa_d, 0);
+ __this_cpu_write((fpuemustats).min_s, 0);
+ __this_cpu_write((fpuemustats).min_d, 0);
+ __this_cpu_write((fpuemustats).mina_s, 0);
+ __this_cpu_write((fpuemustats).mina_d, 0);
+ __this_cpu_write((fpuemustats).mov_s, 0);
+ __this_cpu_write((fpuemustats).mov_d, 0);
+ __this_cpu_write((fpuemustats).msubf_s, 0);
+ __this_cpu_write((fpuemustats).msubf_d, 0);
+ __this_cpu_write((fpuemustats).mul_s, 0);
+ __this_cpu_write((fpuemustats).mul_d, 0);
+ __this_cpu_write((fpuemustats).neg_s, 0);
+ __this_cpu_write((fpuemustats).neg_d, 0);
+ __this_cpu_write((fpuemustats).recip_s, 0);
+ __this_cpu_write((fpuemustats).recip_d, 0);
+ __this_cpu_write((fpuemustats).rint_s, 0);
+ __this_cpu_write((fpuemustats).rint_d, 0);
+ __this_cpu_write((fpuemustats).round_w_s, 0);
+ __this_cpu_write((fpuemustats).round_w_d, 0);
+ __this_cpu_write((fpuemustats).round_l_s, 0);
+ __this_cpu_write((fpuemustats).round_l_d, 0);
+ __this_cpu_write((fpuemustats).rsqrt_s, 0);
+ __this_cpu_write((fpuemustats).rsqrt_d, 0);
+ __this_cpu_write((fpuemustats).sel_s, 0);
+ __this_cpu_write((fpuemustats).sel_d, 0);
+ __this_cpu_write((fpuemustats).seleqz_s, 0);
+ __this_cpu_write((fpuemustats).seleqz_d, 0);
+ __this_cpu_write((fpuemustats).selnez_s, 0);
+ __this_cpu_write((fpuemustats).selnez_d, 0);
+ __this_cpu_write((fpuemustats).sqrt_s, 0);
+ __this_cpu_write((fpuemustats).sqrt_d, 0);
+ __this_cpu_write((fpuemustats).sub_s, 0);
+ __this_cpu_write((fpuemustats).sub_d, 0);
+ __this_cpu_write((fpuemustats).trunc_w_s, 0);
+ __this_cpu_write((fpuemustats).trunc_w_d, 0);
+ __this_cpu_write((fpuemustats).trunc_l_s, 0);
+ __this_cpu_write((fpuemustats).trunc_l_d, 0);
+
return 0;
}
@@ -61,13 +196,18 @@ static const struct file_operations fpuemustats_clear_fops = {
static int __init debugfs_fpuemu(void)
{
- struct dentry *d, *dir, *reset_file;
+ struct dentry *fpuemu_debugfs_base_dir;
+ struct dentry *fpuemu_debugfs_inst_dir;
+ struct dentry *d, *reset_file;
if (!mips_debugfs_dir)
return -ENODEV;
- dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir);
- if (!dir)
+
+ fpuemu_debugfs_base_dir = debugfs_create_dir("fpuemustats",
+ mips_debugfs_dir);
+ if (!fpuemu_debugfs_base_dir)
return -ENOMEM;
+
reset_file = debugfs_create_file("fpuemustats_clear", 0444,
mips_debugfs_dir, NULL,
&fpuemustats_clear_fops);
@@ -79,7 +219,7 @@ static int __init debugfs_fpuemu(void)
#define FPU_STAT_CREATE(m) \
do { \
- d = debugfs_create_file(#m , S_IRUGO, dir, \
+ d = debugfs_create_file(#m, 0444, fpuemu_debugfs_base_dir, \
(void *)FPU_EMU_STAT_OFFSET(m), \
&fops_fpuemu_stat); \
if (!d) \
@@ -100,6 +240,139 @@ do { \
FPU_STAT_CREATE(ieee754_invalidop);
FPU_STAT_CREATE(ds_emul);
+ fpuemu_debugfs_inst_dir = debugfs_create_dir("instructions",
+ fpuemu_debugfs_base_dir);
+ if (!fpuemu_debugfs_inst_dir)
+ return -ENOMEM;
+
+#define FPU_STAT_CREATE_EX(m) \
+do { \
+ char name[32]; \
+ \
+ adjust_instruction_counter_name(name, #m); \
+ \
+ d = debugfs_create_file(name, 0444, fpuemu_debugfs_inst_dir, \
+ (void *)FPU_EMU_STAT_OFFSET(m), \
+ &fops_fpuemu_stat); \
+ if (!d) \
+ return -ENOMEM; \
+} while (0)
+
+ FPU_STAT_CREATE_EX(abs_s);
+ FPU_STAT_CREATE_EX(abs_d);
+ FPU_STAT_CREATE_EX(add_s);
+ FPU_STAT_CREATE_EX(add_d);
+ FPU_STAT_CREATE_EX(bc1eqz);
+ FPU_STAT_CREATE_EX(bc1nez);
+ FPU_STAT_CREATE_EX(ceil_w_s);
+ FPU_STAT_CREATE_EX(ceil_w_d);
+ FPU_STAT_CREATE_EX(ceil_l_s);
+ FPU_STAT_CREATE_EX(ceil_l_d);
+ FPU_STAT_CREATE_EX(class_s);
+ FPU_STAT_CREATE_EX(class_d);
+ FPU_STAT_CREATE_EX(cmp_af_s);
+ FPU_STAT_CREATE_EX(cmp_af_d);
+ FPU_STAT_CREATE_EX(cmp_eq_s);
+ FPU_STAT_CREATE_EX(cmp_eq_d);
+ FPU_STAT_CREATE_EX(cmp_le_s);
+ FPU_STAT_CREATE_EX(cmp_le_d);
+ FPU_STAT_CREATE_EX(cmp_lt_s);
+ FPU_STAT_CREATE_EX(cmp_lt_d);
+ FPU_STAT_CREATE_EX(cmp_ne_s);
+ FPU_STAT_CREATE_EX(cmp_ne_d);
+ FPU_STAT_CREATE_EX(cmp_or_s);
+ FPU_STAT_CREATE_EX(cmp_or_d);
+ FPU_STAT_CREATE_EX(cmp_ueq_s);
+ FPU_STAT_CREATE_EX(cmp_ueq_d);
+ FPU_STAT_CREATE_EX(cmp_ule_s);
+ FPU_STAT_CREATE_EX(cmp_ule_d);
+ FPU_STAT_CREATE_EX(cmp_ult_s);
+ FPU_STAT_CREATE_EX(cmp_ult_d);
+ FPU_STAT_CREATE_EX(cmp_un_s);
+ FPU_STAT_CREATE_EX(cmp_un_d);
+ FPU_STAT_CREATE_EX(cmp_une_s);
+ FPU_STAT_CREATE_EX(cmp_une_d);
+ FPU_STAT_CREATE_EX(cmp_saf_s);
+ FPU_STAT_CREATE_EX(cmp_saf_d);
+ FPU_STAT_CREATE_EX(cmp_seq_s);
+ FPU_STAT_CREATE_EX(cmp_seq_d);
+ FPU_STAT_CREATE_EX(cmp_sle_s);
+ FPU_STAT_CREATE_EX(cmp_sle_d);
+ FPU_STAT_CREATE_EX(cmp_slt_s);
+ FPU_STAT_CREATE_EX(cmp_slt_d);
+ FPU_STAT_CREATE_EX(cmp_sne_s);
+ FPU_STAT_CREATE_EX(cmp_sne_d);
+ FPU_STAT_CREATE_EX(cmp_sor_s);
+ FPU_STAT_CREATE_EX(cmp_sor_d);
+ FPU_STAT_CREATE_EX(cmp_sueq_s);
+ FPU_STAT_CREATE_EX(cmp_sueq_d);
+ FPU_STAT_CREATE_EX(cmp_sule_s);
+ FPU_STAT_CREATE_EX(cmp_sule_d);
+ FPU_STAT_CREATE_EX(cmp_sult_s);
+ FPU_STAT_CREATE_EX(cmp_sult_d);
+ FPU_STAT_CREATE_EX(cmp_sun_s);
+ FPU_STAT_CREATE_EX(cmp_sun_d);
+ FPU_STAT_CREATE_EX(cmp_sune_s);
+ FPU_STAT_CREATE_EX(cmp_sune_d);
+ FPU_STAT_CREATE_EX(cvt_d_l);
+ FPU_STAT_CREATE_EX(cvt_d_s);
+ FPU_STAT_CREATE_EX(cvt_d_w);
+ FPU_STAT_CREATE_EX(cvt_l_s);
+ FPU_STAT_CREATE_EX(cvt_l_d);
+ FPU_STAT_CREATE_EX(cvt_s_d);
+ FPU_STAT_CREATE_EX(cvt_s_l);
+ FPU_STAT_CREATE_EX(cvt_s_w);
+ FPU_STAT_CREATE_EX(cvt_w_s);
+ FPU_STAT_CREATE_EX(cvt_w_d);
+ FPU_STAT_CREATE_EX(div_s);
+ FPU_STAT_CREATE_EX(div_d);
+ FPU_STAT_CREATE_EX(floor_w_s);
+ FPU_STAT_CREATE_EX(floor_w_d);
+ FPU_STAT_CREATE_EX(floor_l_s);
+ FPU_STAT_CREATE_EX(floor_l_d);
+ FPU_STAT_CREATE_EX(maddf_s);
+ FPU_STAT_CREATE_EX(maddf_d);
+ FPU_STAT_CREATE_EX(max_s);
+ FPU_STAT_CREATE_EX(max_d);
+ FPU_STAT_CREATE_EX(maxa_s);
+ FPU_STAT_CREATE_EX(maxa_d);
+ FPU_STAT_CREATE_EX(min_s);
+ FPU_STAT_CREATE_EX(min_d);
+ FPU_STAT_CREATE_EX(mina_s);
+ FPU_STAT_CREATE_EX(mina_d);
+ FPU_STAT_CREATE_EX(mov_s);
+ FPU_STAT_CREATE_EX(mov_d);
+ FPU_STAT_CREATE_EX(msubf_s);
+ FPU_STAT_CREATE_EX(msubf_d);
+ FPU_STAT_CREATE_EX(mul_s);
+ FPU_STAT_CREATE_EX(mul_d);
+ FPU_STAT_CREATE_EX(neg_s);
+ FPU_STAT_CREATE_EX(neg_d);
+ FPU_STAT_CREATE_EX(recip_s);
+ FPU_STAT_CREATE_EX(recip_d);
+ FPU_STAT_CREATE_EX(rint_s);
+ FPU_STAT_CREATE_EX(rint_d);
+ FPU_STAT_CREATE_EX(round_w_s);
+ FPU_STAT_CREATE_EX(round_w_d);
+ FPU_STAT_CREATE_EX(round_l_s);
+ FPU_STAT_CREATE_EX(round_l_d);
+ FPU_STAT_CREATE_EX(rsqrt_s);
+ FPU_STAT_CREATE_EX(rsqrt_d);
+ FPU_STAT_CREATE_EX(sel_s);
+ FPU_STAT_CREATE_EX(sel_d);
+ FPU_STAT_CREATE_EX(seleqz_s);
+ FPU_STAT_CREATE_EX(seleqz_d);
+ FPU_STAT_CREATE_EX(selnez_s);
+ FPU_STAT_CREATE_EX(selnez_d);
+ FPU_STAT_CREATE_EX(sqrt_s);
+ FPU_STAT_CREATE_EX(sqrt_d);
+ FPU_STAT_CREATE_EX(sub_s);
+ FPU_STAT_CREATE_EX(sub_d);
+ FPU_STAT_CREATE_EX(trunc_w_s);
+ FPU_STAT_CREATE_EX(trunc_w_d);
+ FPU_STAT_CREATE_EX(trunc_l_s);
+ FPU_STAT_CREATE_EX(trunc_l_d);
+
return 0;
}
arch_initcall(debugfs_fpuemu);
--
2.9.3
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web