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
Signed-off-by: Vineet Gupta
Cc: Tim Yao
---
arch/arc/Kconfig | 11 ++
arch/arc/include/asm/Kbuild |1 -
arch/arc/include/asm/ptrace.h|3 +
arch/arc/include/asm/unaligned.h | 29 +
arch/arc/kernel/Makefile |1 +
arch/arc/kernel/disasm.c |2 +-
arch/arc/kernel/entry.S | 13 ++
arch/arc/kernel/traps.c | 26
arch/arc/kernel/unaligned.c | 245 ++
9 files changed, 329 insertions(+), 2 deletions(-)
create mode 100644 arch/arc/include/asm/unaligned.h
create mode 100644 arch/arc/kernel/unaligned.c
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index c34f3c3..d735de8 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -341,6 +341,17 @@ config ARC_CURR_IN_REG
This reserved Register R25 to point to Current Task in
kernel mode. This saves memory access for each such access
+
+config ARC_MISALIGN_ACCESS
+ bool "Emulate unaligned memory access (userspace only)"
+ default N
+ select SYSCTL_ARCH_UNALIGN_NO_WARN
+ select SYSCTL_ARCH_UNALIGN_ALLOW
+ help
+ This enables misaligned 16 & 32 bit memory access from user space.
+ Use ONLY-IF-ABS-NECESSARY as it will be very slow and also can hide
+ potential bugs in code
+
config ARC_STACK_NONEXEC
bool "Make stack non-executable"
default n
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 78e982d..b24089c 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -52,7 +52,6 @@ generic-y += topology.h
generic-y += trace_clock.h
generic-y += types.h
generic-y += ucontext.h
-generic-y += unaligned.h
generic-y += user.h
generic-y += vga.h
generic-y += xor.h
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index e4e1ac6..fd68c4b 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -127,6 +127,9 @@ struct user_regs_struct {
sp; \
})
+/* return 1 if PC in delay slot */
+#define delay_mode(regs) ((regs->status32 & STATUS_DE_MASK) == STATUS_DE_MASK)
+
#define in_syscall(regs) (regs->orig_r8 & orig_r8_IS_SCALL)
#define in_brkpt_trap(regs) (regs->orig_r8 & orig_r8_IS_BRKPT)
diff --git a/arch/arc/include/asm/unaligned.h b/arch/arc/include/asm/unaligned.h
new file mode 100644
index 000..5dbe63f
--- /dev/null
+++ b/arch/arc/include/asm/unaligned.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _ASM_ARC_UNALIGNED_H
+#define _ASM_ARC_UNALIGNED_H
+
+/* ARC700 can't handle unaligned Data accesses. */
+
+#include
+#include
+
+#ifdef CONFIG_ARC_MISALIGN_ACCESS
+int misaligned_fixup(unsigned long address, struct pt_regs *regs,
+unsigned long cause, struct callee_regs *cregs);
+#else
+static inline int
+misaligned_fixup(unsigned long address, struct pt_regs *regs,
+unsigned long cause, struct callee_regs *cregs)
+{
+ return 0;
+}
+#endif
+
+#endif /* _ASM_ARC_UNALIGNED_H */
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
index f11318f..eda40d7 100644
--- a/arch/arc/kernel/Makefile
+++ b/arch/arc/kernel/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MODULES) += arcksyms.o module.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_ARC_DW2_UNWIND) += unwind.o
obj-$(CONFIG_KPROBES) += kprobes.o
+obj-$(CONFIG_ARC_MISALIGN_ACCESS) += unaligned.o
obj-$(CONFIG_ARC_FPU_SAVE_RESTORE) += fpu.o
CFLAGS_fpu.o += -mdpfp
diff --git a/arch/arc/kernel/disasm.c b/arch/arc/kernel/disasm.c
index 51bad8f..2f39028 100644
--- a/arch/arc/kernel/disasm.c
+++ b/arch/arc/kernel/disasm.c
@@ -15,7 +15,7 @@
#include
#include
-#if defined(CONFIG_KGDB) || defined(CONFIG_MISALIGN_ACCESS) || \
+#if defined(CONFIG_KGDB) || defined(CONFIG_ARC_MISALIGN_ACCESS) || \
defined(CONFIG_KPROBES)
/* disasm_instr: Analyses instruction at addr, stores
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index 7e392d4..0ef234e 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -12,6 +12,9 @@
* needed before task_pt_regs was invented. This saves a branch per call
* and more importantly allows clean invocation of post-syscall ptrace hook
*
+ * vineetg: May