|
@@ -63,3 +63,68 @@
|
|
#define SHIFT_TYPE(i) (i & 0x60)
|
|
#define SHIFT_TYPE(i) (i & 0x60)
|
|
#define SHIFT_LSL 0x00
|
|
#define SHIFT_LSL 0x00
|
|
#define SHIFT_LSR 0x20
|
|
#define SHIFT_LSR 0x20
|
|
|
|
+#define SHIFT_ASR 0x40
|
|
|
|
+#define SHIFT_RORRRX 0x60
|
|
|
|
+
|
|
|
|
+#define BAD_INSTR 0xdeadc0de
|
|
|
|
+
|
|
|
|
+/* Thumb-2 32 bit format per ARMv7 DDI0406A A6.3, either f800h,e800h,f800h */
|
|
|
|
+#define IS_T32(hi16) \
|
|
|
|
+ (((hi16) & 0xe000) == 0xe000 && ((hi16) & 0x1800))
|
|
|
|
+
|
|
|
|
+static unsigned long ai_user;
|
|
|
|
+static unsigned long ai_sys;
|
|
|
|
+static unsigned long ai_skipped;
|
|
|
|
+static unsigned long ai_half;
|
|
|
|
+static unsigned long ai_word;
|
|
|
|
+static unsigned long ai_dword;
|
|
|
|
+static unsigned long ai_multi;
|
|
|
|
+static int ai_usermode;
|
|
|
|
+
|
|
|
|
+core_param(alignment, ai_usermode, int, 0600);
|
|
|
|
+
|
|
|
|
+#define UM_WARN (1 << 0)
|
|
|
|
+#define UM_FIXUP (1 << 1)
|
|
|
|
+#define UM_SIGNAL (1 << 2)
|
|
|
|
+
|
|
|
|
+/* Return true if and only if the ARMv6 unaligned access model is in use. */
|
|
|
|
+static bool cpu_is_v6_unaligned(void)
|
|
|
|
+{
|
|
|
|
+ return cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int safe_usermode(int new_usermode, bool warn)
|
|
|
|
+{
|
|
|
|
+ /*
|
|
|
|
+ * ARMv6 and later CPUs can perform unaligned accesses for
|
|
|
|
+ * most single load and store instructions up to word size.
|
|
|
|
+ * LDM, STM, LDRD and STRD still need to be handled.
|
|
|
|
+ *
|
|
|
|
+ * Ignoring the alignment fault is not an option on these
|
|
|
|
+ * CPUs since we spin re-faulting the instruction without
|
|
|
|
+ * making any progress.
|
|
|
|
+ */
|
|
|
|
+ if (cpu_is_v6_unaligned() && !(new_usermode & (UM_FIXUP | UM_SIGNAL))) {
|
|
|
|
+ new_usermode |= UM_FIXUP;
|
|
|
|
+
|
|
|
|
+ if (warn)
|
|
|
|
+ printk(KERN_WARNING "alignment: ignoring faults is unsafe on this CPU. Defaulting to fixup mode.\n");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return new_usermode;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_PROC_FS
|
|
|
|
+static const char *usermode_action[] = {
|
|
|
|
+ "ignored",
|
|
|
|
+ "warn",
|
|
|
|
+ "fixup",
|
|
|
|
+ "fixup+warn",
|
|
|
|
+ "signal",
|
|
|
|
+ "signal+warn"
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static int alignment_proc_show(struct seq_file *m, void *v)
|
|
|
|
+{
|
|
|
|
+ seq_printf(m, "User:\t\t%lu\n", ai_user);
|
|
|
|
+ seq_printf(m, "System:\t\t%lu\n", ai_sys);
|