|
@@ -128,3 +128,132 @@ 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);
|
|
|
+ seq_printf(m, "Skipped:\t%lu\n", ai_skipped);
|
|
|
+ seq_printf(m, "Half:\t\t%lu\n", ai_half);
|
|
|
+ seq_printf(m, "Word:\t\t%lu\n", ai_word);
|
|
|
+ if (cpu_architecture() >= CPU_ARCH_ARMv5TE)
|
|
|
+ seq_printf(m, "DWord:\t\t%lu\n", ai_dword);
|
|
|
+ seq_printf(m, "Multi:\t\t%lu\n", ai_multi);
|
|
|
+ seq_printf(m, "User faults:\t%i (%s)\n", ai_usermode,
|
|
|
+ usermode_action[ai_usermode]);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int alignment_proc_open(struct inode *inode, struct file *file)
|
|
|
+{
|
|
|
+ return single_open(file, alignment_proc_show, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t alignment_proc_write(struct file *file, const char __user *buffer,
|
|
|
+ size_t count, loff_t *pos)
|
|
|
+{
|
|
|
+ char mode;
|
|
|
+
|
|
|
+ if (count > 0) {
|
|
|
+ if (get_user(mode, buffer))
|
|
|
+ return -EFAULT;
|
|
|
+ if (mode >= '0' && mode <= '5')
|
|
|
+ ai_usermode = safe_usermode(mode - '0', true);
|
|
|
+ }
|
|
|
+ return count;
|
|
|
+}
|
|
|
+
|
|
|
+static const struct file_operations alignment_proc_fops = {
|
|
|
+ .open = alignment_proc_open,
|
|
|
+ .read = seq_read,
|
|
|
+ .llseek = seq_lseek,
|
|
|
+ .release = single_release,
|
|
|
+ .write = alignment_proc_write,
|
|
|
+};
|
|
|
+#endif /* CONFIG_PROC_FS */
|
|
|
+
|
|
|
+union offset_union {
|
|
|
+ unsigned long un;
|
|
|
+ signed long sn;
|
|
|
+};
|
|
|
+
|
|
|
+#define TYPE_ERROR 0
|
|
|
+#define TYPE_FAULT 1
|
|
|
+#define TYPE_LDST 2
|
|
|
+#define TYPE_DONE 3
|
|
|
+
|
|
|
+#ifdef __ARMEB__
|
|
|
+#define BE 1
|
|
|
+#define FIRST_BYTE_16 "mov %1, %1, ror #8\n"
|
|
|
+#define FIRST_BYTE_32 "mov %1, %1, ror #24\n"
|
|
|
+#define NEXT_BYTE "ror #24"
|
|
|
+#else
|
|
|
+#define BE 0
|
|
|
+#define FIRST_BYTE_16
|
|
|
+#define FIRST_BYTE_32
|
|
|
+#define NEXT_BYTE "lsr #8"
|
|
|
+#endif
|
|
|
+
|
|
|
+#define __get8_unaligned_check(ins,val,addr,err) \
|
|
|
+ __asm__( \
|
|
|
+ ARM( "1: "ins" %1, [%2], #1\n" ) \
|
|
|
+ THUMB( "1: "ins" %1, [%2]\n" ) \
|
|
|
+ THUMB( " add %2, %2, #1\n" ) \
|
|
|
+ "2:\n" \
|
|
|
+ " .pushsection .fixup,\"ax\"\n" \
|
|
|
+ " .align 2\n" \
|
|
|
+ "3: mov %0, #1\n" \
|
|
|
+ " b 2b\n" \
|
|
|
+ " .popsection\n" \
|
|
|
+ " .pushsection __ex_table,\"a\"\n" \
|
|
|
+ " .align 3\n" \
|
|
|
+ " .long 1b, 3b\n" \
|
|
|
+ " .popsection\n" \
|
|
|
+ : "=r" (err), "=&r" (val), "=r" (addr) \
|
|
|
+ : "0" (err), "2" (addr))
|
|
|
+
|
|
|
+#define __get16_unaligned_check(ins,val,addr) \
|
|
|
+ do { \
|
|
|
+ unsigned int err = 0, v, a = addr; \
|
|
|
+ __get8_unaligned_check(ins,v,a,err); \
|
|
|
+ val = v << ((BE) ? 8 : 0); \
|
|
|
+ __get8_unaligned_check(ins,v,a,err); \
|
|
|
+ val |= v << ((BE) ? 0 : 8); \
|
|
|
+ if (err) \
|
|
|
+ goto fault; \
|
|
|
+ } while (0)
|
|
|
+
|
|
|
+#define get16_unaligned_check(val,addr) \
|
|
|
+ __get16_unaligned_check("ldrb",val,addr)
|
|
|
+
|
|
|
+#define get16t_unaligned_check(val,addr) \
|
|
|
+ __get16_unaligned_check("ldrbt",val,addr)
|
|
|
+
|
|
|
+#define __get32_unaligned_check(ins,val,addr) \
|
|
|
+ do { \
|
|
|
+ unsigned int err = 0, v, a = addr; \
|
|
|
+ __get8_unaligned_check(ins,v,a,err); \
|
|
|
+ val = v << ((BE) ? 24 : 0); \
|
|
|
+ __get8_unaligned_check(ins,v,a,err); \
|
|
|
+ val |= v << ((BE) ? 16 : 8); \
|
|
|
+ __get8_unaligned_check(ins,v,a,err); \
|
|
|
+ val |= v << ((BE) ? 8 : 16); \
|
|
|
+ __get8_unaligned_check(ins,v,a,err); \
|
|
|
+ val |= v << ((BE) ? 0 : 24); \
|
|
|
+ if (err) \
|
|
|
+ goto fault; \
|
|
|
+ } while (0)
|
|
|
+
|
|
|
+#define get32_unaligned_check(val,addr) \
|
|
|
+ __get32_unaligned_check("ldrb",val,addr)
|
|
|
+
|
|
|
+#define get32t_unaligned_check(val,addr) \
|
|
|
+ __get32_unaligned_check("ldrbt",val,addr)
|
|
|
+
|
|
|
+#define __put16_unaligned_check(ins,val,addr) \
|
|
|
+ do { \
|
|
|
+ unsigned int err = 0, v = val, a = addr; \
|
|
|
+ __asm__( FIRST_BYTE_16 \
|
|
|
+ ARM( "1: "ins" %1, [%2], #1\n" ) \
|
|
|
+ THUMB( "1: "ins" %1, [%2]\n" ) \
|
|
|
+ THUMB( " add %2, %2, #1\n" ) \
|
|
|
+ " mov %1, %1, "NEXT_BYTE"\n" \
|
|
|
+ "2: "ins" %1, [%2]\n" \
|
|
|
+ "3:\n" \
|
|
|
+ " .pushsection .fixup,\"ax\"\n" \
|