Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 177873
b: refs/heads/master
c: b6ee75e
h: refs/heads/master
i:
  177871: ea3d9ee
v: v3
  • Loading branch information
David Daney authored and Ralf Baechle committed Dec 17, 2009
1 parent 4e72a54 commit f422d3c
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 51 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 32028f1f7bce32e72183129dc55fc23656e7081c
refs/heads/master: b6ee75ed4fa201873d3a2b32dfce2dbd701a2de4
24 changes: 17 additions & 7 deletions trunk/arch/mips/include/asm/fpu_emulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,27 @@

#include <asm/break.h>
#include <asm/inst.h>
#include <asm/local.h>

#ifdef CONFIG_DEBUG_FS

struct mips_fpu_emulator_stats {
unsigned int emulated;
unsigned int loads;
unsigned int stores;
unsigned int cp1ops;
unsigned int cp1xops;
unsigned int errors;
local_t emulated;
local_t loads;
local_t stores;
local_t cp1ops;
local_t cp1xops;
local_t errors;
};

extern struct mips_fpu_emulator_stats fpuemustats;
DECLARE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);

#define MIPS_FPU_EMU_INC_STATS(M) \
cpu_local_wrap(__local_inc(&__get_cpu_var(fpuemustats).M))

#else
#define MIPS_FPU_EMU_INC_STATS(M) do { } while (0)
#endif /* CONFIG_DEBUG_FS */

extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir,
unsigned long cpc);
Expand Down
102 changes: 61 additions & 41 deletions trunk/arch/mips/math-emu/cp1emu.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
* better performance by compiling with -msoft-float!
*/
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/debugfs.h>

#include <asm/inst.h>
Expand Down Expand Up @@ -68,7 +69,9 @@ static int fpux_emu(struct pt_regs *,

/* Further private data for which no space exists in mips_fpu_struct */

struct mips_fpu_emulator_stats fpuemustats;
#ifdef CONFIG_DEBUG_FS
DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
#endif

/* Control registers */

Expand Down Expand Up @@ -209,7 +212,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
unsigned int cond;

if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
fpuemustats.errors++;
MIPS_FPU_EMU_INC_STATS(errors);
return SIGBUS;
}

Expand Down Expand Up @@ -240,7 +243,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
return SIGILL;
}
if (get_user(ir, (mips_instruction __user *) emulpc)) {
fpuemustats.errors++;
MIPS_FPU_EMU_INC_STATS(errors);
return SIGBUS;
}
/* __compute_return_epc() will have updated cp0_epc */
Expand All @@ -253,16 +256,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
}

emul:
fpuemustats.emulated++;
MIPS_FPU_EMU_INC_STATS(emulated);
switch (MIPSInst_OPCODE(ir)) {
case ldc1_op:{
u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
MIPSInst_SIMM(ir));
u64 val;

fpuemustats.loads++;
MIPS_FPU_EMU_INC_STATS(loads);
if (get_user(val, va)) {
fpuemustats.errors++;
MIPS_FPU_EMU_INC_STATS(errors);
return SIGBUS;
}
DITOREG(val, MIPSInst_RT(ir));
Expand All @@ -274,10 +277,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
MIPSInst_SIMM(ir));
u64 val;

fpuemustats.stores++;
MIPS_FPU_EMU_INC_STATS(stores);
DIFROMREG(val, MIPSInst_RT(ir));
if (put_user(val, va)) {
fpuemustats.errors++;
MIPS_FPU_EMU_INC_STATS(errors);
return SIGBUS;
}
break;
Expand All @@ -288,9 +291,9 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
MIPSInst_SIMM(ir));
u32 val;

fpuemustats.loads++;
MIPS_FPU_EMU_INC_STATS(loads);
if (get_user(val, va)) {
fpuemustats.errors++;
MIPS_FPU_EMU_INC_STATS(errors);
return SIGBUS;
}
SITOREG(val, MIPSInst_RT(ir));
Expand All @@ -302,10 +305,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
MIPSInst_SIMM(ir));
u32 val;

fpuemustats.stores++;
MIPS_FPU_EMU_INC_STATS(stores);
SIFROMREG(val, MIPSInst_RT(ir));
if (put_user(val, va)) {
fpuemustats.errors++;
MIPS_FPU_EMU_INC_STATS(errors);
return SIGBUS;
}
break;
Expand Down Expand Up @@ -429,7 +432,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)

if (get_user(ir,
(mips_instruction __user *) xcp->cp0_epc)) {
fpuemustats.errors++;
MIPS_FPU_EMU_INC_STATS(errors);
return SIGBUS;
}

Expand Down Expand Up @@ -595,7 +598,7 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
{
unsigned rcsr = 0; /* resulting csr */

fpuemustats.cp1xops++;
MIPS_FPU_EMU_INC_STATS(cp1xops);

switch (MIPSInst_FMA_FFMT(ir)) {
case s_fmt:{ /* 0 */
Expand All @@ -610,9 +613,9 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
xcp->regs[MIPSInst_FT(ir)]);

fpuemustats.loads++;
MIPS_FPU_EMU_INC_STATS(loads);
if (get_user(val, va)) {
fpuemustats.errors++;
MIPS_FPU_EMU_INC_STATS(errors);
return SIGBUS;
}
SITOREG(val, MIPSInst_FD(ir));
Expand All @@ -622,11 +625,11 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
xcp->regs[MIPSInst_FT(ir)]);

fpuemustats.stores++;
MIPS_FPU_EMU_INC_STATS(stores);

SIFROMREG(val, MIPSInst_FS(ir));
if (put_user(val, va)) {
fpuemustats.errors++;
MIPS_FPU_EMU_INC_STATS(errors);
return SIGBUS;
}
break;
Expand Down Expand Up @@ -687,9 +690,9 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
xcp->regs[MIPSInst_FT(ir)]);

fpuemustats.loads++;
MIPS_FPU_EMU_INC_STATS(loads);
if (get_user(val, va)) {
fpuemustats.errors++;
MIPS_FPU_EMU_INC_STATS(errors);
return SIGBUS;
}
DITOREG(val, MIPSInst_FD(ir));
Expand All @@ -699,10 +702,10 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
xcp->regs[MIPSInst_FT(ir)]);

fpuemustats.stores++;
MIPS_FPU_EMU_INC_STATS(stores);
DIFROMREG(val, MIPSInst_FS(ir));
if (put_user(val, va)) {
fpuemustats.errors++;
MIPS_FPU_EMU_INC_STATS(errors);
return SIGBUS;
}
break;
Expand Down Expand Up @@ -769,7 +772,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
#endif
} rv; /* resulting value */

fpuemustats.cp1ops++;
MIPS_FPU_EMU_INC_STATS(cp1ops);
switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
case s_fmt:{ /* 0 */
union {
Expand Down Expand Up @@ -1240,7 +1243,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
prevepc = xcp->cp0_epc;

if (get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) {
fpuemustats.errors++;
MIPS_FPU_EMU_INC_STATS(errors);
return SIGBUS;
}
if (insn == 0)
Expand Down Expand Up @@ -1276,33 +1279,50 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
}

#ifdef CONFIG_DEBUG_FS

static int fpuemu_stat_get(void *data, u64 *val)
{
int cpu;
unsigned long sum = 0;
for_each_online_cpu(cpu) {
struct mips_fpu_emulator_stats *ps;
local_t *pv;
ps = &per_cpu(fpuemustats, cpu);
pv = (void *)ps + (unsigned long)data;
sum += local_read(pv);
}
*val = sum;
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n");

extern struct dentry *mips_debugfs_dir;
static int __init debugfs_fpuemu(void)
{
struct dentry *d, *dir;
int i;
static struct {
const char *name;
unsigned int *v;
} vars[] __initdata = {
{ "emulated", &fpuemustats.emulated },
{ "loads", &fpuemustats.loads },
{ "stores", &fpuemustats.stores },
{ "cp1ops", &fpuemustats.cp1ops },
{ "cp1xops", &fpuemustats.cp1xops },
{ "errors", &fpuemustats.errors },
};

if (!mips_debugfs_dir)
return -ENODEV;
dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir);
if (!dir)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(vars); i++) {
d = debugfs_create_u32(vars[i].name, S_IRUGO, dir, vars[i].v);
if (!d)
return -ENOMEM;
}

#define FPU_STAT_CREATE(M) \
do { \
d = debugfs_create_file(#M , S_IRUGO, dir, \
(void *)offsetof(struct mips_fpu_emulator_stats, M), \
&fops_fpuemu_stat); \
if (!d) \
return -ENOMEM; \
} while (0)

FPU_STAT_CREATE(emulated);
FPU_STAT_CREATE(loads);
FPU_STAT_CREATE(stores);
FPU_STAT_CREATE(cp1ops);
FPU_STAT_CREATE(cp1xops);
FPU_STAT_CREATE(errors);

return 0;
}
__initcall(debugfs_fpuemu);
Expand Down
4 changes: 2 additions & 2 deletions trunk/arch/mips/math-emu/dsemul.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
err |= __put_user(cpc, &fr->epc);

if (unlikely(err)) {
fpuemustats.errors++;
MIPS_FPU_EMU_INC_STATS(errors);
return SIGBUS;
}

Expand Down Expand Up @@ -136,7 +136,7 @@ int do_dsemulret(struct pt_regs *xcp)
err |= __get_user(cookie, &fr->cookie);

if (unlikely(err || (insn != BREAK_MATH) || (cookie != BD_COOKIE))) {
fpuemustats.errors++;
MIPS_FPU_EMU_INC_STATS(errors);
return 0;
}

Expand Down

0 comments on commit f422d3c

Please sign in to comment.