summaryrefslogtreecommitdiff
path: root/arch/arc/kernel/traps.c
diff options
context:
space:
mode:
authorVineet Gupta <vgupta@synopsys.com>2013-01-23 16:30:36 +0530
committerVineet Gupta <vgupta@synopsys.com>2013-02-15 23:16:06 +0530
commit2e651ea1596b0ee25af4fcdc4cd13cbb33ffc254 (patch)
tree51210f1cd80327a00e2fd4b0d20849b6329925d6 /arch/arc/kernel/traps.c
parentbf14e3b979a01cd7298d631736f965fe83c6e2bc (diff)
ARC: Unaligned access emulation
ARC700 doesn't natively support unaligned access, but can be emulated -Unaligned Access Exception -Disassembly at the Fault address to find the exact insn (long/short) Also per Arnd's comment, we runtime control it using 2 sysctl knobs: * SYSCTL_ARCH_UNALIGN_ALLOW: Runtime enable/disble * SYSCTL_ARCH_UNALIGN_NO_WARN: Warn on each emulation attempt Originally contributed by Tim Yao <tim.yao@amlogic.com> Signed-off-by: Vineet Gupta <vgupta@synopsys.com> Cc: Tim Yao <tim.yao@amlogic.com> Acked-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/arc/kernel/traps.c')
-rw-r--r--arch/arc/kernel/traps.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c
index c6396b48fcd2..ec802c52a1ca 100644
--- a/arch/arc/kernel/traps.c
+++ b/arch/arc/kernel/traps.c
@@ -7,6 +7,9 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
+ * vineetg: May 2011
+ * -user-space unaligned access emulation
+ *
* Rahul Trivedi: Codito Technologies 2004
*/
@@ -16,6 +19,7 @@
#include <asm/ptrace.h>
#include <asm/setup.h>
#include <asm/kprobes.h>
+#include <asm/unaligned.h>
void __init trap_init(void)
{
@@ -79,7 +83,29 @@ DO_ERROR_INFO(SIGILL, "Illegal Insn (or Seq)", insterror_is_error, ILL_ILLOPC)
DO_ERROR_INFO(SIGBUS, "Invalid Mem Access", do_memory_error, BUS_ADRERR)
DO_ERROR_INFO(SIGTRAP, "Breakpoint Set", trap_is_brkpt, TRAP_BRKPT)
+#ifdef CONFIG_ARC_MISALIGN_ACCESS
+/*
+ * Entry Point for Misaligned Data access Exception, for emulating in software
+ */
+int do_misaligned_access(unsigned long cause, unsigned long address,
+ struct pt_regs *regs, struct callee_regs *cregs)
+{
+ if (misaligned_fixup(address, regs, cause, cregs) != 0) {
+ siginfo_t info;
+
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRALN;
+ info.si_addr = (void __user *)address;
+ return handle_exception(cause, "Misaligned Access", regs,
+ &info);
+ }
+ return 0;
+}
+
+#else
DO_ERROR_INFO(SIGSEGV, "Misaligned Access", do_misaligned_access, SEGV_ACCERR)
+#endif
/*
* Entry point for miscll errors such as Nested Exceptions