On Tue, 06 Mar 2007 00:51:43 +0900 (JST), Atsushi Nemoto <anemo@xxxxxxxxxxxxx> wrote: > Currently a number of unaligned instructions is counted but not used. > Add /sys/kernel/mips/unaligned_instructions file to show the value. Updated against current git tree. Subject: [PATCH] Add some sysfs files to debug unaligned accesses Currently a number of unaligned instructions is counted but not used. Add /sys/kernel/mips/unaligned_instructions file to show the value. And add /sys/kernel/mips/unaligned_action to control behavior upon an unaligned access. Possible actions are: quiet: silently fixup the unaligned access. signal: send SIGBUS. show: dump registers, process name, etc. and fixup. Signed-off-by: Atsushi Nemoto <anemo@xxxxxxxxxxxxx> --- arch/mips/kernel/setup.c | 14 ++++++++ arch/mips/kernel/unaligned.c | 70 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 4975da0..1c8629c 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -574,3 +574,17 @@ __setup("nodsp", dsp_disable); unsigned long kernelsp[NR_CPUS]; unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3; + +static struct attribute *mips_attrs[] = { + NULL +}; +static struct attribute_group mips_attr_group = { + .name = "mips", + .attrs = mips_attrs, +}; + +static int __init sysfs_mips(void) +{ + return sysfs_create_group(&kernel_subsys.kobj, &mips_attr_group); +} +arch_initcall(sysfs_mips); diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index a7d49ae..bdead88 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -87,9 +87,14 @@ #define STR(x) __STR(x) #define __STR(x) #x -#ifdef CONFIG_PROC_FS -unsigned long unaligned_instructions; +#ifdef CONFIG_SYSFS +static unsigned long unaligned_instructions; +static int unaligned_action; +static const char *unaligned_actions[] = {"quiet", "signal", "show"}; +#else +#define unaligned_action 0 #endif +extern void show_registers(struct pt_regs *regs); static inline int emulate_load_store_insn(struct pt_regs *regs, void __user *addr, unsigned int __user *pc, @@ -459,7 +464,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs, goto sigill; } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SYSFS unaligned_instructions++; #endif @@ -516,6 +521,10 @@ asmlinkage void do_ade(struct pt_regs *regs) pc = (unsigned int __user *) exception_epc(regs); if (user_mode(regs) && (current->thread.mflags & MF_FIXADE) == 0) goto sigbus; + if (unaligned_action == 1) + goto sigbus; + else if (unaligned_action == 2) + show_registers(regs); /* * Do branch emulation only if we didn't forward the exception. @@ -546,3 +555,58 @@ sigbus: * XXX On return from the signal handler we should advance the epc */ } + +#ifdef CONFIG_SYSFS +static ssize_t unaligned_instructions_show(struct kset *kset, char *buf) +{ + return sprintf(buf, "%lu\n", unaligned_instructions); +} + +static ssize_t unaligned_action_show(struct kset *kset, char *buf) +{ + int i; + char *s = buf; + + for (i = 0; i < ARRAY_SIZE(unaligned_actions); i++) { + if (i == unaligned_action) + s += sprintf(s, "[%s] ", unaligned_actions[i]); + else + s += sprintf(s, "%s ", unaligned_actions[i]); + } + s += sprintf(s, "\n"); + return s - buf; +} + +static ssize_t unaligned_action_store(struct kset *kset, + const char *buf, size_t count) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(unaligned_actions); i++) { + if (!strncmp(buf, unaligned_actions[i], + min(count, strlen(unaligned_actions[i])))) { + unaligned_action = i; + return count; + } + } + return -EINVAL; +} + +#define __ATTR_RW(_name) __ATTR(_name, 0644, _name##_show, _name##_store) +static struct subsys_attribute unaligned_attrs[] = { + __ATTR_RO(unaligned_instructions), + __ATTR_RW(unaligned_action), +}; + +static int __init sysfs_unaligned(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(unaligned_attrs); i++) + sysfs_add_file_to_group(&kernel_subsys.kobj, + &unaligned_attrs[i].attr, + "mips"); + return 0; +} +__initcall(sysfs_unaligned); +#endif