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