• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/arm/mm/
1/* Modified by Broadcom Corp. Portions Copyright (c) Broadcom Corp, 2012. */
2/*
3 *  linux/arch/arm/mm/alignment.c
4 *
5 *  Copyright (C) 1995  Linus Torvalds
6 *  Modifications for ARM processor (c) 1995-2001 Russell King
7 *  Thumb alignment fault fixups (c) 2004 MontaVista Software, Inc.
8 *  - Adapted from gdb/sim/arm/thumbemu.c -- Thumb instruction emulation.
9 *    Copyright (C) 1996, Cygnus Software Technologies Ltd.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15#include <linux/moduleparam.h>
16#include <linux/compiler.h>
17#include <linux/kernel.h>
18#include <linux/errno.h>
19#include <linux/string.h>
20#include <linux/proc_fs.h>
21#include <linux/seq_file.h>
22#include <linux/init.h>
23#include <linux/sched.h>
24#include <linux/uaccess.h>
25
26#include <asm/unaligned.h>
27
28#include "fault.h"
29
30/*
31 * 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998
32 * /proc/sys/debug/alignment, modified and integrated into
33 * Linux 2.1 by Russell King
34 *
35 * Speed optimisations and better fault handling by Russell King.
36 *
37 * *** NOTE ***
38 * This code is not portable to processors with late data abort handling.
39 */
40#define CODING_BITS(i)	(i & 0x0e000000)
41
42#define LDST_I_BIT(i)	(i & (1 << 26))		/* Immediate constant	*/
43#define LDST_P_BIT(i)	(i & (1 << 24))		/* Preindex		*/
44#define LDST_U_BIT(i)	(i & (1 << 23))		/* Add offset		*/
45#define LDST_W_BIT(i)	(i & (1 << 21))		/* Writeback		*/
46#define LDST_L_BIT(i)	(i & (1 << 20))		/* Load			*/
47
48#define LDST_P_EQ_U(i)	((((i) ^ ((i) >> 1)) & (1 << 23)) == 0)
49
50#define LDSTHD_I_BIT(i)	(i & (1 << 22))		/* double/half-word immed */
51#define LDM_S_BIT(i)	(i & (1 << 22))		/* write CPSR from SPSR	*/
52
53#define RN_BITS(i)	((i >> 16) & 15)	/* Rn			*/
54#define RD_BITS(i)	((i >> 12) & 15)	/* Rd			*/
55#define RM_BITS(i)	(i & 15)		/* Rm			*/
56
57#define REGMASK_BITS(i)	(i & 0xffff)
58#define OFFSET_BITS(i)	(i & 0x0fff)
59
60#define IS_SHIFT(i)	(i & 0x0ff0)
61#define SHIFT_BITS(i)	((i >> 7) & 0x1f)
62#define SHIFT_TYPE(i)	(i & 0x60)
63#define SHIFT_LSL	0x00
64#define SHIFT_LSR	0x20
65#define SHIFT_ASR	0x40
66#define SHIFT_RORRRX	0x60
67
68#define BAD_INSTR 	0xdeadc0de
69
70/* Thumb-2 32 bit format per ARMv7 DDI0406A A6.3, either f800h,e800h,f800h */
71#define IS_T32(hi16) \
72	(((hi16) & 0xe000) == 0xe000 && ((hi16) & 0x1800))
73
74static unsigned long ai_user;
75static unsigned long ai_sys;
76static unsigned long ai_skipped;
77static unsigned long ai_half;
78static unsigned long ai_word;
79static unsigned long ai_dword;
80static unsigned long ai_multi;
81static int ai_usermode;
82
83core_param(alignment, ai_usermode, int, 0600);
84
85#define UM_WARN		(1 << 0)
86#define UM_FIXUP	(1 << 1)
87#define UM_SIGNAL	(1 << 2)
88
89#ifdef CONFIG_PROC_FS
90static const char *usermode_action[] = {
91	"ignored",
92	"warn",
93	"fixup",
94	"fixup+warn",
95	"signal",
96	"signal+warn"
97};
98
99static int alignment_proc_show(struct seq_file *m, void *v)
100{
101	seq_printf(m, "User:\t\t%lu\n", ai_user);
102	seq_printf(m, "System:\t\t%lu\n", ai_sys);
103	seq_printf(m, "Skipped:\t%lu\n", ai_skipped);
104	seq_printf(m, "Half:\t\t%lu\n", ai_half);
105	seq_printf(m, "Word:\t\t%lu\n", ai_word);
106	if (cpu_architecture() >= CPU_ARCH_ARMv5TE)
107		seq_printf(m, "DWord:\t\t%lu\n", ai_dword);
108	seq_printf(m, "Multi:\t\t%lu\n", ai_multi);
109	seq_printf(m, "User faults:\t%i (%s)\n", ai_usermode,
110			usermode_action[ai_usermode]);
111
112	return 0;
113}
114
115static int alignment_proc_open(struct inode *inode, struct file *file)
116{
117	return single_open(file, alignment_proc_show, NULL);
118}
119
120static ssize_t alignment_proc_write(struct file *file, const char __user *buffer,
121				    size_t count, loff_t *pos)
122{
123	char mode;
124
125	if (count > 0) {
126		if (get_user(mode, buffer))
127			return -EFAULT;
128		if (mode >= '0' && mode <= '5')
129			ai_usermode = mode - '0';
130	}
131	return count;
132}
133
134static const struct file_operations alignment_proc_fops = {
135	.open		= alignment_proc_open,
136	.read		= seq_read,
137	.llseek		= seq_lseek,
138	.release	= single_release,
139	.write		= alignment_proc_write,
140};
141#endif /* CONFIG_PROC_FS */
142
143union offset_union {
144	unsigned long un;
145	  signed long sn;
146};
147
148#define TYPE_ERROR	0
149#define TYPE_FAULT	1
150#define TYPE_LDST	2
151#define TYPE_DONE	3
152
153#ifdef __ARMEB__
154#define BE		1
155#define FIRST_BYTE_16	"mov	%1, %1, ror #8\n"
156#define FIRST_BYTE_32	"mov	%1, %1, ror #24\n"
157#define NEXT_BYTE	"ror #24"
158#else
159#define BE		0
160#define FIRST_BYTE_16
161#define FIRST_BYTE_32
162#define NEXT_BYTE	"lsr #8"
163#endif
164
165#define __get8_unaligned_check(ins,val,addr,err)	\
166	__asm__(					\
167 ARM(	"1:	"ins"	%1, [%2], #1\n"	)		\
168 THUMB(	"1:	"ins"	%1, [%2]\n"	)		\
169 THUMB(	"	add	%2, %2, #1\n"	)		\
170	"2:\n"						\
171	"	.pushsection .fixup,\"ax\"\n"		\
172	"	.align	2\n"				\
173	"3:	mov	%0, #1\n"			\
174	"	b	2b\n"				\
175	"	.popsection\n"				\
176	"	.pushsection __ex_table,\"a\"\n"	\
177	"	.align	3\n"				\
178	"	.long	1b, 3b\n"			\
179	"	.popsection\n"				\
180	: "=r" (err), "=&r" (val), "=r" (addr)		\
181	: "0" (err), "2" (addr))
182
183#define __get16_unaligned_check(ins,val,addr)			\
184	do {							\
185		unsigned int err = 0, v, a = addr;		\
186		__get8_unaligned_check(ins,v,a,err);		\
187		val =  v << ((BE) ? 8 : 0);			\
188		__get8_unaligned_check(ins,v,a,err);		\
189		val |= v << ((BE) ? 0 : 8);			\
190		if (err)					\
191			goto fault;				\
192	} while (0)
193
194#define get16_unaligned_check(val,addr) \
195	__get16_unaligned_check("ldrb",val,addr)
196
197#define get16t_unaligned_check(val,addr) \
198	__get16_unaligned_check("ldrbt",val,addr)
199
200#define __get32_unaligned_check(ins,val,addr)			\
201	do {							\
202		unsigned int err = 0, v, a = addr;		\
203		__get8_unaligned_check(ins,v,a,err);		\
204		val =  v << ((BE) ? 24 :  0);			\
205		__get8_unaligned_check(ins,v,a,err);		\
206		val |= v << ((BE) ? 16 :  8);			\
207		__get8_unaligned_check(ins,v,a,err);		\
208		val |= v << ((BE) ?  8 : 16);			\
209		__get8_unaligned_check(ins,v,a,err);		\
210		val |= v << ((BE) ?  0 : 24);			\
211		if (err)					\
212			goto fault;				\
213	} while (0)
214
215#define get32_unaligned_check(val,addr) \
216	__get32_unaligned_check("ldrb",val,addr)
217
218#define get32t_unaligned_check(val,addr) \
219	__get32_unaligned_check("ldrbt",val,addr)
220
221#define __put16_unaligned_check(ins,val,addr)			\
222	do {							\
223		unsigned int err = 0, v = val, a = addr;	\
224		__asm__( FIRST_BYTE_16				\
225	 ARM(	"1:	"ins"	%1, [%2], #1\n"	)		\
226	 THUMB(	"1:	"ins"	%1, [%2]\n"	)		\
227	 THUMB(	"	add	%2, %2, #1\n"	)		\
228		"	mov	%1, %1, "NEXT_BYTE"\n"		\
229		"2:	"ins"	%1, [%2]\n"			\
230		"3:\n"						\
231		"	.pushsection .fixup,\"ax\"\n"		\
232		"	.align	2\n"				\
233		"4:	mov	%0, #1\n"			\
234		"	b	3b\n"				\
235		"	.popsection\n"				\
236		"	.pushsection __ex_table,\"a\"\n"	\
237		"	.align	3\n"				\
238		"	.long	1b, 4b\n"			\
239		"	.long	2b, 4b\n"			\
240		"	.popsection\n"				\
241		: "=r" (err), "=&r" (v), "=&r" (a)		\
242		: "0" (err), "1" (v), "2" (a));			\
243		if (err)					\
244			goto fault;				\
245	} while (0)
246
247#define put16_unaligned_check(val,addr)  \
248	__put16_unaligned_check("strb",val,addr)
249
250#define put16t_unaligned_check(val,addr) \
251	__put16_unaligned_check("strbt",val,addr)
252
253#define __put32_unaligned_check(ins,val,addr)			\
254	do {							\
255		unsigned int err = 0, v = val, a = addr;	\
256		__asm__( FIRST_BYTE_32				\
257	 ARM(	"1:	"ins"	%1, [%2], #1\n"	)		\
258	 THUMB(	"1:	"ins"	%1, [%2]\n"	)		\
259	 THUMB(	"	add	%2, %2, #1\n"	)		\
260		"	mov	%1, %1, "NEXT_BYTE"\n"		\
261	 ARM(	"2:	"ins"	%1, [%2], #1\n"	)		\
262	 THUMB(	"2:	"ins"	%1, [%2]\n"	)		\
263	 THUMB(	"	add	%2, %2, #1\n"	)		\
264		"	mov	%1, %1, "NEXT_BYTE"\n"		\
265	 ARM(	"3:	"ins"	%1, [%2], #1\n"	)		\
266	 THUMB(	"3:	"ins"	%1, [%2]\n"	)		\
267	 THUMB(	"	add	%2, %2, #1\n"	)		\
268		"	mov	%1, %1, "NEXT_BYTE"\n"		\
269		"4:	"ins"	%1, [%2]\n"			\
270		"5:\n"						\
271		"	.pushsection .fixup,\"ax\"\n"		\
272		"	.align	2\n"				\
273		"6:	mov	%0, #1\n"			\
274		"	b	5b\n"				\
275		"	.popsection\n"				\
276		"	.pushsection __ex_table,\"a\"\n"	\
277		"	.align	3\n"				\
278		"	.long	1b, 6b\n"			\
279		"	.long	2b, 6b\n"			\
280		"	.long	3b, 6b\n"			\
281		"	.long	4b, 6b\n"			\
282		"	.popsection\n"				\
283		: "=r" (err), "=&r" (v), "=&r" (a)		\
284		: "0" (err), "1" (v), "2" (a));			\
285		if (err)					\
286			goto fault;				\
287	} while (0)
288
289#define put32_unaligned_check(val,addr) \
290	__put32_unaligned_check("strb", val, addr)
291
292#define put32t_unaligned_check(val,addr) \
293	__put32_unaligned_check("strbt", val, addr)
294
295static void
296do_alignment_finish_ldst(unsigned long addr, unsigned long instr, struct pt_regs *regs, union offset_union offset)
297{
298	if (!LDST_U_BIT(instr))
299		offset.un = -offset.un;
300
301	if (!LDST_P_BIT(instr))
302		addr += offset.un;
303
304	if (!LDST_P_BIT(instr) || LDST_W_BIT(instr))
305		regs->uregs[RN_BITS(instr)] = addr;
306}
307
308static int
309do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *regs)
310{
311	unsigned int rd = RD_BITS(instr);
312
313	ai_half += 1;
314
315	if (user_mode(regs))
316		goto user;
317
318	if (LDST_L_BIT(instr)) {
319		unsigned long val;
320		get16_unaligned_check(val, addr);
321
322		/* signed half-word? */
323		if (instr & 0x40)
324			val = (signed long)((signed short) val);
325
326		regs->uregs[rd] = val;
327	} else
328		put16_unaligned_check(regs->uregs[rd], addr);
329
330	return TYPE_LDST;
331
332 user:
333	if (LDST_L_BIT(instr)) {
334		unsigned long val;
335		get16t_unaligned_check(val, addr);
336
337		/* signed half-word? */
338		if (instr & 0x40)
339			val = (signed long)((signed short) val);
340
341		regs->uregs[rd] = val;
342	} else
343		put16t_unaligned_check(regs->uregs[rd], addr);
344
345	return TYPE_LDST;
346
347 fault:
348	return TYPE_FAULT;
349}
350
351static int
352do_alignment_ldrdstrd(unsigned long addr, unsigned long instr,
353		      struct pt_regs *regs)
354{
355	unsigned int rd = RD_BITS(instr);
356	unsigned int rd2;
357	int load;
358
359	if ((instr & 0xfe000000) == 0xe8000000) {
360		/* ARMv7 Thumb-2 32-bit LDRD/STRD */
361		rd2 = (instr >> 8) & 0xf;
362		load = !!(LDST_L_BIT(instr));
363	} else if (((rd & 1) == 1) || (rd == 14))
364		goto bad;
365	else {
366		load = ((instr & 0xf0) == 0xd0);
367		rd2 = rd + 1;
368	}
369
370	ai_dword += 1;
371
372	if (user_mode(regs))
373		goto user;
374
375	if (load) {
376		unsigned long val;
377		get32_unaligned_check(val, addr);
378		regs->uregs[rd] = val;
379		get32_unaligned_check(val, addr + 4);
380		regs->uregs[rd2] = val;
381	} else {
382		put32_unaligned_check(regs->uregs[rd], addr);
383		put32_unaligned_check(regs->uregs[rd2], addr + 4);
384	}
385
386	return TYPE_LDST;
387
388 user:
389	if (load) {
390		unsigned long val;
391		get32t_unaligned_check(val, addr);
392		regs->uregs[rd] = val;
393		get32t_unaligned_check(val, addr + 4);
394		regs->uregs[rd2] = val;
395	} else {
396		put32t_unaligned_check(regs->uregs[rd], addr);
397		put32t_unaligned_check(regs->uregs[rd2], addr + 4);
398	}
399
400	return TYPE_LDST;
401 bad:
402	return TYPE_ERROR;
403 fault:
404	return TYPE_FAULT;
405}
406
407static int
408do_alignment_ldrstr(unsigned long addr, unsigned long instr, struct pt_regs *regs)
409{
410	unsigned int rd = RD_BITS(instr);
411
412	ai_word += 1;
413
414	if ((!LDST_P_BIT(instr) && LDST_W_BIT(instr)) || user_mode(regs))
415		goto trans;
416
417	if (LDST_L_BIT(instr)) {
418		unsigned int val;
419		get32_unaligned_check(val, addr);
420		regs->uregs[rd] = val;
421	} else
422		put32_unaligned_check(regs->uregs[rd], addr);
423	return TYPE_LDST;
424
425 trans:
426	if (LDST_L_BIT(instr)) {
427		unsigned int val;
428		get32t_unaligned_check(val, addr);
429		regs->uregs[rd] = val;
430	} else
431		put32t_unaligned_check(regs->uregs[rd], addr);
432	return TYPE_LDST;
433
434 fault:
435	return TYPE_FAULT;
436}
437
438/*
439 * LDM/STM alignment handler.
440 *
441 * There are 4 variants of this instruction:
442 *
443 * B = rn pointer before instruction, A = rn pointer after instruction
444 *              ------ increasing address ----->
445 *	        |    | r0 | r1 | ... | rx |    |
446 * PU = 01             B                    A
447 * PU = 11        B                    A
448 * PU = 00        A                    B
449 * PU = 10             A                    B
450 */
451static int
452do_alignment_ldmstm(unsigned long addr, unsigned long instr, struct pt_regs *regs)
453{
454	unsigned int rd, rn, correction, nr_regs, regbits;
455	unsigned long eaddr, newaddr;
456
457	if (LDM_S_BIT(instr))
458		goto bad;
459
460	correction = 4; /* processor implementation defined */
461	regs->ARM_pc += correction;
462
463	ai_multi += 1;
464
465	/* count the number of registers in the mask to be transferred */
466	nr_regs = hweight16(REGMASK_BITS(instr)) * 4;
467
468	rn = RN_BITS(instr);
469	newaddr = eaddr = regs->uregs[rn];
470
471	if (!LDST_U_BIT(instr))
472		nr_regs = -nr_regs;
473	newaddr += nr_regs;
474	if (!LDST_U_BIT(instr))
475		eaddr = newaddr;
476
477	if (LDST_P_EQ_U(instr))	/* U = P */
478		eaddr += 4;
479
480	/*
481	 * For alignment faults on the ARM922T/ARM920T the MMU  makes
482	 * the FSR (and hence addr) equal to the updated base address
483	 * of the multiple access rather than the restored value.
484	 * Switch this message off if we've got a ARM92[02], otherwise
485	 * [ls]dm alignment faults are noisy!
486	 */
487#if !(defined CONFIG_CPU_ARM922T)  && !(defined CONFIG_CPU_ARM920T)
488	/*
489	 * This is a "hint" - we already have eaddr worked out by the
490	 * processor for us.
491	 */
492	if (addr != eaddr) {
493		printk(KERN_ERR "LDMSTM: PC = %08lx, instr = %08lx, "
494			"addr = %08lx, eaddr = %08lx\n",
495			 instruction_pointer(regs), instr, addr, eaddr);
496		show_regs(regs);
497	}
498#endif
499
500	if (user_mode(regs)) {
501		for (regbits = REGMASK_BITS(instr), rd = 0; regbits;
502		     regbits >>= 1, rd += 1)
503			if (regbits & 1) {
504				if (LDST_L_BIT(instr)) {
505					unsigned int val;
506					get32t_unaligned_check(val, eaddr);
507					regs->uregs[rd] = val;
508				} else
509					put32t_unaligned_check(regs->uregs[rd], eaddr);
510				eaddr += 4;
511			}
512	} else {
513		for (regbits = REGMASK_BITS(instr), rd = 0; regbits;
514		     regbits >>= 1, rd += 1)
515			if (regbits & 1) {
516				if (LDST_L_BIT(instr)) {
517					unsigned int val;
518					get32_unaligned_check(val, eaddr);
519					regs->uregs[rd] = val;
520				} else
521					put32_unaligned_check(regs->uregs[rd], eaddr);
522				eaddr += 4;
523			}
524	}
525
526	if (LDST_W_BIT(instr))
527		regs->uregs[rn] = newaddr;
528	if (!LDST_L_BIT(instr) || !(REGMASK_BITS(instr) & (1 << 15)))
529		regs->ARM_pc -= correction;
530	return TYPE_DONE;
531
532fault:
533	regs->ARM_pc -= correction;
534	return TYPE_FAULT;
535
536bad:
537	printk(KERN_ERR "Alignment trap: not handling ldm with s-bit set\n");
538	return TYPE_ERROR;
539}
540
541/*
542 * Convert Thumb ld/st instruction forms to equivalent ARM instructions so
543 * we can reuse ARM userland alignment fault fixups for Thumb.
544 *
545 * This implementation was initially based on the algorithm found in
546 * gdb/sim/arm/thumbemu.c. It is basically just a code reduction of same
547 * to convert only Thumb ld/st instruction forms to equivalent ARM forms.
548 *
549 * NOTES:
550 * 1. Comments below refer to ARM ARM DDI0100E Thumb Instruction sections.
551 * 2. If for some reason we're passed an non-ld/st Thumb instruction to
552 *    decode, we return 0xdeadc0de. This should never happen under normal
553 *    circumstances but if it does, we've got other problems to deal with
554 *    elsewhere and we obviously can't fix those problems here.
555 */
556
557static unsigned long
558thumb2arm(u16 tinstr)
559{
560	u32 L = (tinstr & (1<<11)) >> 11;
561
562	switch ((tinstr & 0xf800) >> 11) {
563	/* 6.5.1 Format 1: */
564	case 0x6000 >> 11:				/* 7.1.52 STR(1) */
565	case 0x6800 >> 11:				/* 7.1.26 LDR(1) */
566	case 0x7000 >> 11:				/* 7.1.55 STRB(1) */
567	case 0x7800 >> 11:				/* 7.1.30 LDRB(1) */
568		return 0xe5800000 |
569			((tinstr & (1<<12)) << (22-12)) |	/* fixup */
570			(L<<20) |				/* L==1? */
571			((tinstr & (7<<0)) << (12-0)) |		/* Rd */
572			((tinstr & (7<<3)) << (16-3)) |		/* Rn */
573			((tinstr & (31<<6)) >>			/* immed_5 */
574				(6 - ((tinstr & (1<<12)) ? 0 : 2)));
575	case 0x8000 >> 11:				/* 7.1.57 STRH(1) */
576	case 0x8800 >> 11:				/* 7.1.32 LDRH(1) */
577		return 0xe1c000b0 |
578			(L<<20) |				/* L==1? */
579			((tinstr & (7<<0)) << (12-0)) |		/* Rd */
580			((tinstr & (7<<3)) << (16-3)) |		/* Rn */
581			((tinstr & (7<<6)) >> (6-1)) |	 /* immed_5[2:0] */
582			((tinstr & (3<<9)) >> (9-8));	 /* immed_5[4:3] */
583
584	/* 6.5.1 Format 2: */
585	case 0x5000 >> 11:
586	case 0x5800 >> 11:
587		{
588			static const u32 subset[8] = {
589				0xe7800000,		/* 7.1.53 STR(2) */
590				0xe18000b0,		/* 7.1.58 STRH(2) */
591				0xe7c00000,		/* 7.1.56 STRB(2) */
592				0xe19000d0,		/* 7.1.34 LDRSB */
593				0xe7900000,		/* 7.1.27 LDR(2) */
594				0xe19000b0,		/* 7.1.33 LDRH(2) */
595				0xe7d00000,		/* 7.1.31 LDRB(2) */
596				0xe19000f0		/* 7.1.35 LDRSH */
597			};
598			return subset[(tinstr & (7<<9)) >> 9] |
599			    ((tinstr & (7<<0)) << (12-0)) |	/* Rd */
600			    ((tinstr & (7<<3)) << (16-3)) |	/* Rn */
601			    ((tinstr & (7<<6)) >> (6-0));	/* Rm */
602		}
603
604	/* 6.5.1 Format 3: */
605	case 0x4800 >> 11:				/* 7.1.28 LDR(3) */
606		/* NOTE: This case is not technically possible. We're
607		 *	 loading 32-bit memory data via PC relative
608		 *	 addressing mode. So we can and should eliminate
609		 *	 this case. But I'll leave it here for now.
610		 */
611		return 0xe59f0000 |
612		    ((tinstr & (7<<8)) << (12-8)) |		/* Rd */
613		    ((tinstr & 255) << (2-0));			/* immed_8 */
614
615	/* 6.5.1 Format 4: */
616	case 0x9000 >> 11:				/* 7.1.54 STR(3) */
617	case 0x9800 >> 11:				/* 7.1.29 LDR(4) */
618		return 0xe58d0000 |
619			(L<<20) |				/* L==1? */
620			((tinstr & (7<<8)) << (12-8)) |		/* Rd */
621			((tinstr & 255) << 2);			/* immed_8 */
622
623	/* 6.6.1 Format 1: */
624	case 0xc000 >> 11:				/* 7.1.51 STMIA */
625	case 0xc800 >> 11:				/* 7.1.25 LDMIA */
626		{
627			u32 Rn = (tinstr & (7<<8)) >> 8;
628			u32 W = ((L<<Rn) & (tinstr&255)) ? 0 : 1<<21;
629
630			return 0xe8800000 | W | (L<<20) | (Rn<<16) |
631				(tinstr&255);
632		}
633
634	/* 6.6.1 Format 2: */
635	case 0xb000 >> 11:				/* 7.1.48 PUSH */
636	case 0xb800 >> 11:				/* 7.1.47 POP */
637		if ((tinstr & (3 << 9)) == 0x0400) {
638			static const u32 subset[4] = {
639				0xe92d0000,	/* STMDB sp!,{registers} */
640				0xe92d4000,	/* STMDB sp!,{registers,lr} */
641				0xe8bd0000,	/* LDMIA sp!,{registers} */
642				0xe8bd8000	/* LDMIA sp!,{registers,pc} */
643			};
644			return subset[(L<<1) | ((tinstr & (1<<8)) >> 8)] |
645			    (tinstr & 255);		/* register_list */
646		}
647		/* Else fall through for illegal instruction case */
648
649	default:
650		return BAD_INSTR;
651	}
652}
653
654/*
655 * Convert Thumb-2 32 bit LDM, STM, LDRD, STRD to equivalent instruction
656 * handlable by ARM alignment handler, also find the corresponding handler,
657 * so that we can reuse ARM userland alignment fault fixups for Thumb.
658 *
659 * @pinstr: original Thumb-2 instruction; returns new handlable instruction
660 * @regs: register context.
661 * @poffset: return offset from faulted addr for later writeback
662 *
663 * NOTES:
664 * 1. Comments below refer to ARMv7 DDI0406A Thumb Instruction sections.
665 * 2. Register name Rt from ARMv7 is same as Rd from ARMv6 (Rd is Rt)
666 */
667static void *
668do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,
669			    union offset_union *poffset)
670{
671	unsigned long instr = *pinstr;
672	u16 tinst1 = (instr >> 16) & 0xffff;
673	u16 tinst2 = instr & 0xffff;
674	poffset->un = 0;
675
676	switch (tinst1 & 0xffe0) {
677	/* A6.3.5 Load/Store multiple */
678	case 0xe880:		/* STM/STMIA/STMEA,LDM/LDMIA, PUSH/POP T2 */
679	case 0xe8a0:		/* ...above writeback version */
680	case 0xe900:		/* STMDB/STMFD, LDMDB/LDMEA */
681	case 0xe920:		/* ...above writeback version */
682		/* no need offset decision since handler calculates it */
683		return do_alignment_ldmstm;
684
685	case 0xf840:		/* POP/PUSH T3 (single register) */
686		if (RN_BITS(instr) == 13 && (tinst2 & 0x09ff) == 0x0904) {
687			u32 L = !!(LDST_L_BIT(instr));
688			const u32 subset[2] = {
689				0xe92d0000,	/* STMDB sp!,{registers} */
690				0xe8bd0000,	/* LDMIA sp!,{registers} */
691			};
692			*pinstr = subset[L] | (1<<RD_BITS(instr));
693			return do_alignment_ldmstm;
694		}
695		/* Else fall through for illegal instruction case */
696		break;
697
698	/* A6.3.6 Load/store double, STRD/LDRD(immed, lit, reg) */
699	case 0xe860:
700	case 0xe960:
701	case 0xe8e0:
702	case 0xe9e0:
703		poffset->un = (tinst2 & 0xff) << 2;
704	case 0xe940:
705	case 0xe9c0:
706		return do_alignment_ldrdstrd;
707
708	/*
709	 * No need to handle load/store instructions up to word size
710	 * since ARMv6 and later CPUs can perform unaligned accesses.
711	 */
712	default:
713		break;
714	}
715	return NULL;
716}
717
718static int
719do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
720{
721	union offset_union offset = { 0 };
722	unsigned long instr = 0, instrptr;
723	int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs);
724	unsigned int type;
725	mm_segment_t fs;
726	unsigned int fault;
727	u16 tinstr = 0;
728	int isize = 4;
729	int thumb2_32b = 0;
730
731	instrptr = instruction_pointer(regs);
732
733	fs = get_fs();
734	set_fs(KERNEL_DS);
735	if (thumb_mode(regs)) {
736		fault = __get_user(tinstr, (u16 *)(instrptr & ~1));
737		if (!fault) {
738			if (cpu_architecture() >= CPU_ARCH_ARMv7 &&
739			    IS_T32(tinstr)) {
740				/* Thumb-2 32-bit */
741				u16 tinst2 = 0;
742				fault = __get_user(tinst2, (u16 *)(instrptr+2));
743				instr = (tinstr << 16) | tinst2;
744				thumb2_32b = 1;
745			} else {
746				isize = 2;
747				instr = thumb2arm(tinstr);
748			}
749		}
750	} else
751		fault = __get_user(instr, (u32 *)instrptr);
752	set_fs(fs);
753
754	if (fault) {
755		type = TYPE_FAULT;
756		goto bad_or_fault;
757	}
758
759	if (user_mode(regs))
760		goto user;
761
762	ai_sys += 1;
763
764 fixup:
765
766	regs->ARM_pc += isize;
767
768	switch (CODING_BITS(instr)) {
769	case 0x00000000:	/* 3.13.4 load/store instruction extensions */
770		if (LDSTHD_I_BIT(instr))
771			offset.un = (instr & 0xf00) >> 4 | (instr & 15);
772		else
773			offset.un = regs->uregs[RM_BITS(instr)];
774
775		if ((instr & 0x000000f0) == 0x000000b0 || /* LDRH, STRH */
776		    (instr & 0x001000f0) == 0x001000f0)   /* LDRSH */
777			handler = do_alignment_ldrhstrh;
778		else if ((instr & 0x001000f0) == 0x000000d0 || /* LDRD */
779			 (instr & 0x001000f0) == 0x000000f0)   /* STRD */
780			handler = do_alignment_ldrdstrd;
781		else if ((instr & 0x01f00ff0) == 0x01000090) /* SWP */
782			goto swp;
783		else
784			goto bad;
785		break;
786
787	case 0x04000000:	/* ldr or str immediate */
788		offset.un = OFFSET_BITS(instr);
789		handler = do_alignment_ldrstr;
790		break;
791
792	case 0x06000000:	/* ldr or str register */
793		offset.un = regs->uregs[RM_BITS(instr)];
794
795		if (IS_SHIFT(instr)) {
796			unsigned int shiftval = SHIFT_BITS(instr);
797
798			switch(SHIFT_TYPE(instr)) {
799			case SHIFT_LSL:
800				offset.un <<= shiftval;
801				break;
802
803			case SHIFT_LSR:
804				offset.un >>= shiftval;
805				break;
806
807			case SHIFT_ASR:
808				offset.sn >>= shiftval;
809				break;
810
811			case SHIFT_RORRRX:
812				if (shiftval == 0) {
813					offset.un >>= 1;
814					if (regs->ARM_cpsr & PSR_C_BIT)
815						offset.un |= 1 << 31;
816				} else
817					offset.un = offset.un >> shiftval |
818							  offset.un << (32 - shiftval);
819				break;
820			}
821		}
822		handler = do_alignment_ldrstr;
823		break;
824
825	case 0x08000000:	/* ldm or stm, or thumb-2 32bit instruction */
826		if (thumb2_32b)
827			handler = do_alignment_t32_to_handler(&instr, regs, &offset);
828		else
829			handler = do_alignment_ldmstm;
830		break;
831
832	default:
833		goto bad;
834	}
835
836	if (!handler)
837		goto bad;
838	type = handler(addr, instr, regs);
839
840	if (type == TYPE_ERROR || type == TYPE_FAULT) {
841		regs->ARM_pc -= isize;
842		goto bad_or_fault;
843	}
844
845	if (type == TYPE_LDST)
846		do_alignment_finish_ldst(addr, instr, regs, offset);
847
848	return 0;
849
850 bad_or_fault:
851	if (type == TYPE_ERROR)
852		goto bad;
853	/*
854	 * We got a fault - fix it up, or die.
855	 */
856	do_bad_area(addr, fsr, regs);
857	return 0;
858
859 swp:
860	printk(KERN_ERR "Alignment trap: not handling swp instruction\n");
861
862 bad:
863	/*
864	 * Oops, we didn't handle the instruction.
865	 */
866	printk(KERN_ERR "Alignment trap: not handling instruction "
867		"%0*lx at [<%08lx>]\n",
868		isize << 1,
869		isize == 2 ? tinstr : instr, instrptr);
870	ai_skipped += 1;
871	return 1;
872
873 user:
874	ai_user += 1;
875
876	if (ai_usermode & UM_WARN)
877		printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%0*lx "
878		       "Address=0x%08lx FSR 0x%03x\n", current->comm,
879			task_pid_nr(current), instrptr,
880			isize << 1,
881			isize == 2 ? tinstr : instr,
882		        addr, fsr);
883
884	if (ai_usermode & UM_FIXUP)
885		goto fixup;
886
887	if (ai_usermode & UM_SIGNAL)
888		force_sig(SIGBUS, current);
889	else {
890		/*
891		 * We're about to disable the alignment trap and return to
892		 * user space.  But if an interrupt occurs before actually
893		 * reaching user space, then the IRQ vector entry code will
894		 * notice that we were still in kernel space and therefore
895		 * the alignment trap won't be re-enabled in that case as it
896		 * is presumed to be always on from kernel space.
897		 * Let's prevent that race by disabling interrupts here (they
898		 * are disabled on the way back to user space anyway in
899		 * entry-common.S) and disable the alignment trap only if
900		 * there is no work pending for this thread.
901		 */
902		raw_local_irq_disable();
903		if (!(current_thread_info()->flags & _TIF_WORK_MASK))
904			set_cr(cr_no_alignment);
905	}
906
907	return 0;
908}
909
910/*
911 * This needs to be done after sysctl_init, otherwise sys/ will be
912 * overwritten.  Actually, this shouldn't be in sys/ at all since
913 * it isn't a sysctl, and it doesn't contain sysctl information.
914 * We now locate it in /proc/cpu/alignment instead.
915 */
916static int __init alignment_init(void)
917{
918#ifdef CONFIG_PROC_FS
919	struct proc_dir_entry *res;
920
921	res = proc_create("cpu/alignment", S_IWUSR | S_IRUGO, NULL,
922			  &alignment_proc_fops);
923	if (!res)
924		return -ENOMEM;
925#endif
926
927	/*
928	 * ARMv6 and later CPUs can perform unaligned accesses for
929	 * most single load and store instructions up to word size.
930	 * LDM, STM, LDRD and STRD still need to be handled.
931	 *
932	 * Ignoring the alignment fault is not an option on these
933	 * CPUs since we spin re-faulting the instruction without
934	 * making any progress.
935	 */
936	if (cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U)) {
937		cr_alignment &= ~CR_A;
938		cr_no_alignment &= ~CR_A;
939		set_cr(cr_alignment);
940		ai_usermode = UM_FIXUP;
941	}
942
943	hook_fault_code(1, do_alignment, SIGBUS, BUS_ADRALN,
944			"alignment exception");
945
946	/*
947	 * ARMv6K and ARMv7 use fault status 3 (0b00011) as Access Flag section
948	 * fault, not as alignment error.
949	 *
950	 * TODO: handle ARMv6K properly. Runtime check for 'K' extension is
951	 * needed.
952	 */
953	if (cpu_architecture() <= CPU_ARCH_ARMv6) {
954		hook_fault_code(3, do_alignment, SIGBUS, BUS_ADRALN,
955				"alignment exception");
956	}
957
958	return 0;
959}
960
961fs_initcall(alignment_init);
962