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