| 
					
				 | 
			
			
				@@ -63,3 +63,68 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define SHIFT_TYPE(i)	(i & 0x60) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define SHIFT_LSL	0x00 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #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); 
			 |