linux/arch/sh/kernel/traps_64.c
<<
>>
Prefs
   1/*
   2 * arch/sh/kernel/traps_64.c
   3 *
   4 * Copyright (C) 2000, 2001  Paolo Alberelli
   5 * Copyright (C) 2003, 2004  Paul Mundt
   6 * Copyright (C) 2003, 2004  Richard Curnow
   7 *
   8 * This file is subject to the terms and conditions of the GNU General Public
   9 * License.  See the file "COPYING" in the main directory of this archive
  10 * for more details.
  11 */
  12#include <linux/sched.h>
  13#include <linux/kernel.h>
  14#include <linux/string.h>
  15#include <linux/errno.h>
  16#include <linux/ptrace.h>
  17#include <linux/timer.h>
  18#include <linux/mm.h>
  19#include <linux/smp.h>
  20#include <linux/init.h>
  21#include <linux/delay.h>
  22#include <linux/spinlock.h>
  23#include <linux/kallsyms.h>
  24#include <linux/interrupt.h>
  25#include <linux/sysctl.h>
  26#include <linux/module.h>
  27#include <linux/perf_event.h>
  28#include <asm/uaccess.h>
  29#include <asm/io.h>
  30#include <asm/alignment.h>
  31#include <asm/processor.h>
  32#include <asm/pgtable.h>
  33#include <asm/fpu.h>
  34
  35static int read_opcode(reg_size_t pc, insn_size_t *result_opcode, int from_user_mode)
  36{
  37        int get_user_error;
  38        unsigned long aligned_pc;
  39        insn_size_t opcode;
  40
  41        if ((pc & 3) == 1) {
  42                /* SHmedia */
  43                aligned_pc = pc & ~3;
  44                if (from_user_mode) {
  45                        if (!access_ok(VERIFY_READ, aligned_pc, sizeof(insn_size_t))) {
  46                                get_user_error = -EFAULT;
  47                        } else {
  48                                get_user_error = __get_user(opcode, (insn_size_t *)aligned_pc);
  49                                *result_opcode = opcode;
  50                        }
  51                        return get_user_error;
  52                } else {
  53                        /* If the fault was in the kernel, we can either read
  54                         * this directly, or if not, we fault.
  55                        */
  56                        *result_opcode = *(insn_size_t *)aligned_pc;
  57                        return 0;
  58                }
  59        } else if ((pc & 1) == 0) {
  60                /* SHcompact */
  61                /* TODO : provide handling for this.  We don't really support
  62                   user-mode SHcompact yet, and for a kernel fault, this would
  63                   have to come from a module built for SHcompact.  */
  64                return -EFAULT;
  65        } else {
  66                /* misaligned */
  67                return -EFAULT;
  68        }
  69}
  70
  71static int address_is_sign_extended(__u64 a)
  72{
  73        __u64 b;
  74#if (NEFF == 32)
  75        b = (__u64)(__s64)(__s32)(a & 0xffffffffUL);
  76        return (b == a) ? 1 : 0;
  77#else
  78#error "Sign extend check only works for NEFF==32"
  79#endif
  80}
  81
  82/* return -1 for fault, 0 for OK */
  83static int generate_and_check_address(struct pt_regs *regs,
  84                                      insn_size_t opcode,
  85                                      int displacement_not_indexed,
  86                                      int width_shift,
  87                                      __u64 *address)
  88{
  89        __u64 base_address, addr;
  90        int basereg;
  91
  92        switch (1 << width_shift) {
  93        case 1: inc_unaligned_byte_access(); break;
  94        case 2: inc_unaligned_word_access(); break;
  95        case 4: inc_unaligned_dword_access(); break;
  96        case 8: inc_unaligned_multi_access(); break;
  97        }
  98
  99        basereg = (opcode >> 20) & 0x3f;
 100        base_address = regs->regs[basereg];
 101        if (displacement_not_indexed) {
 102                __s64 displacement;
 103                displacement = (opcode >> 10) & 0x3ff;
 104                displacement = ((displacement << 54) >> 54); /* sign extend */
 105                addr = (__u64)((__s64)base_address + (displacement << width_shift));
 106        } else {
 107                __u64 offset;
 108                int offsetreg;
 109                offsetreg = (opcode >> 10) & 0x3f;
 110                offset = regs->regs[offsetreg];
 111                addr = base_address + offset;
 112        }
 113
 114        /* Check sign extended */
 115        if (!address_is_sign_extended(addr))
 116                return -1;
 117
 118        /* Check accessible.  For misaligned access in the kernel, assume the
 119           address is always accessible (and if not, just fault when the
 120           load/store gets done.) */
 121        if (user_mode(regs)) {
 122                inc_unaligned_user_access();
 123
 124                if (addr >= TASK_SIZE)
 125                        return -1;
 126        } else
 127                inc_unaligned_kernel_access();
 128
 129        *address = addr;
 130
 131        perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, addr);
 132        unaligned_fixups_notify(current, opcode, regs);
 133
 134        return 0;
 135}
 136
 137static void misaligned_kernel_word_load(__u64 address, int do_sign_extend, __u64 *result)
 138{
 139        unsigned short x;
 140        unsigned char *p, *q;
 141        p = (unsigned char *) (int) address;
 142        q = (unsigned char *) &x;
 143        q[0] = p[0];
 144        q[1] = p[1];
 145
 146        if (do_sign_extend) {
 147                *result = (__u64)(__s64) *(short *) &x;
 148        } else {
 149                *result = (__u64) x;
 150        }
 151}
 152
 153static void misaligned_kernel_word_store(__u64 address, __u64 value)
 154{
 155        unsigned short x;
 156        unsigned char *p, *q;
 157        p = (unsigned char *) (int) address;
 158        q = (unsigned char *) &x;
 159
 160        x = (__u16) value;
 161        p[0] = q[0];
 162        p[1] = q[1];
 163}
 164
 165static int misaligned_load(struct pt_regs *regs,
 166                           insn_size_t opcode,
 167                           int displacement_not_indexed,
 168                           int width_shift,
 169                           int do_sign_extend)
 170{
 171        /* Return -1 for a fault, 0 for OK */
 172        int error;
 173        int destreg;
 174        __u64 address;
 175
 176        error = generate_and_check_address(regs, opcode,
 177                        displacement_not_indexed, width_shift, &address);
 178        if (error < 0)
 179                return error;
 180
 181        destreg = (opcode >> 4) & 0x3f;
 182        if (user_mode(regs)) {
 183                __u64 buffer;
 184
 185                if (!access_ok(VERIFY_READ, (unsigned long) address, 1UL<<width_shift)) {
 186                        return -1;
 187                }
 188
 189                if (__copy_user(&buffer, (const void *)(int)address, (1 << width_shift)) > 0) {
 190                        return -1; /* fault */
 191                }
 192                switch (width_shift) {
 193                case 1:
 194                        if (do_sign_extend) {
 195                                regs->regs[destreg] = (__u64)(__s64) *(__s16 *) &buffer;
 196                        } else {
 197                                regs->regs[destreg] = (__u64) *(__u16 *) &buffer;
 198                        }
 199                        break;
 200                case 2:
 201                        regs->regs[destreg] = (__u64)(__s64) *(__s32 *) &buffer;
 202                        break;
 203                case 3:
 204                        regs->regs[destreg] = buffer;
 205                        break;
 206                default:
 207                        printk("Unexpected width_shift %d in misaligned_load, PC=%08lx\n",
 208                                width_shift, (unsigned long) regs->pc);
 209                        break;
 210                }
 211        } else {
 212                /* kernel mode - we can take short cuts since if we fault, it's a genuine bug */
 213                __u64 lo, hi;
 214
 215                switch (width_shift) {
 216                case 1:
 217                        misaligned_kernel_word_load(address, do_sign_extend, &regs->regs[destreg]);
 218                        break;
 219                case 2:
 220                        asm ("ldlo.l %1, 0, %0" : "=r" (lo) : "r" (address));
 221                        asm ("ldhi.l %1, 3, %0" : "=r" (hi) : "r" (address));
 222                        regs->regs[destreg] = lo | hi;
 223                        break;
 224                case 3:
 225                        asm ("ldlo.q %1, 0, %0" : "=r" (lo) : "r" (address));
 226                        asm ("ldhi.q %1, 7, %0" : "=r" (hi) : "r" (address));
 227                        regs->regs[destreg] = lo | hi;
 228                        break;
 229
 230                default:
 231                        printk("Unexpected width_shift %d in misaligned_load, PC=%08lx\n",
 232                                width_shift, (unsigned long) regs->pc);
 233                        break;
 234                }
 235        }
 236
 237        return 0;
 238}
 239
 240static int misaligned_store(struct pt_regs *regs,
 241                            insn_size_t opcode,
 242                            int displacement_not_indexed,
 243                            int width_shift)
 244{
 245        /* Return -1 for a fault, 0 for OK */
 246        int error;
 247        int srcreg;
 248        __u64 address;
 249
 250        error = generate_and_check_address(regs, opcode,
 251                        displacement_not_indexed, width_shift, &address);
 252        if (error < 0)
 253                return error;
 254
 255        srcreg = (opcode >> 4) & 0x3f;
 256        if (user_mode(regs)) {
 257                __u64 buffer;
 258
 259                if (!access_ok(VERIFY_WRITE, (unsigned long) address, 1UL<<width_shift)) {
 260                        return -1;
 261                }
 262
 263                switch (width_shift) {
 264                case 1:
 265                        *(__u16 *) &buffer = (__u16) regs->regs[srcreg];
 266                        break;
 267                case 2:
 268                        *(__u32 *) &buffer = (__u32) regs->regs[srcreg];
 269                        break;
 270                case 3:
 271                        buffer = regs->regs[srcreg];
 272                        break;
 273                default:
 274                        printk("Unexpected width_shift %d in misaligned_store, PC=%08lx\n",
 275                                width_shift, (unsigned long) regs->pc);
 276                        break;
 277                }
 278
 279                if (__copy_user((void *)(int)address, &buffer, (1 << width_shift)) > 0) {
 280                        return -1; /* fault */
 281                }
 282        } else {
 283                /* kernel mode - we can take short cuts since if we fault, it's a genuine bug */
 284                __u64 val = regs->regs[srcreg];
 285
 286                switch (width_shift) {
 287                case 1:
 288                        misaligned_kernel_word_store(address, val);
 289                        break;
 290                case 2:
 291                        asm ("stlo.l %1, 0, %0" : : "r" (val), "r" (address));
 292                        asm ("sthi.l %1, 3, %0" : : "r" (val), "r" (address));
 293                        break;
 294                case 3:
 295                        asm ("stlo.q %1, 0, %0" : : "r" (val), "r" (address));
 296                        asm ("sthi.q %1, 7, %0" : : "r" (val), "r" (address));
 297                        break;
 298
 299                default:
 300                        printk("Unexpected width_shift %d in misaligned_store, PC=%08lx\n",
 301                                width_shift, (unsigned long) regs->pc);
 302                        break;
 303                }
 304        }
 305
 306        return 0;
 307}
 308
 309/* Never need to fix up misaligned FPU accesses within the kernel since that's a real
 310   error. */
 311static int misaligned_fpu_load(struct pt_regs *regs,
 312                           insn_size_t opcode,
 313                           int displacement_not_indexed,
 314                           int width_shift,
 315                           int do_paired_load)
 316{
 317        /* Return -1 for a fault, 0 for OK */
 318        int error;
 319        int destreg;
 320        __u64 address;
 321
 322        error = generate_and_check_address(regs, opcode,
 323                        displacement_not_indexed, width_shift, &address);
 324        if (error < 0)
 325                return error;
 326
 327        destreg = (opcode >> 4) & 0x3f;
 328        if (user_mode(regs)) {
 329                __u64 buffer;
 330                __u32 buflo, bufhi;
 331
 332                if (!access_ok(VERIFY_READ, (unsigned long) address, 1UL<<width_shift)) {
 333                        return -1;
 334                }
 335
 336                if (__copy_user(&buffer, (const void *)(int)address, (1 << width_shift)) > 0) {
 337                        return -1; /* fault */
 338                }
 339                /* 'current' may be the current owner of the FPU state, so
 340                   context switch the registers into memory so they can be
 341                   indexed by register number. */
 342                if (last_task_used_math == current) {
 343                        enable_fpu();
 344                        save_fpu(current);
 345                        disable_fpu();
 346                        last_task_used_math = NULL;
 347                        regs->sr |= SR_FD;
 348                }
 349
 350                buflo = *(__u32*) &buffer;
 351                bufhi = *(1 + (__u32*) &buffer);
 352
 353                switch (width_shift) {
 354                case 2:
 355                        current->thread.xstate->hardfpu.fp_regs[destreg] = buflo;
 356                        break;
 357                case 3:
 358                        if (do_paired_load) {
 359                                current->thread.xstate->hardfpu.fp_regs[destreg] = buflo;
 360                                current->thread.xstate->hardfpu.fp_regs[destreg+1] = bufhi;
 361                        } else {
 362#if defined(CONFIG_CPU_LITTLE_ENDIAN)
 363                                current->thread.xstate->hardfpu.fp_regs[destreg] = bufhi;
 364                                current->thread.xstate->hardfpu.fp_regs[destreg+1] = buflo;
 365#else
 366                                current->thread.xstate->hardfpu.fp_regs[destreg] = buflo;
 367                                current->thread.xstate->hardfpu.fp_regs[destreg+1] = bufhi;
 368#endif
 369                        }
 370                        break;
 371                default:
 372                        printk("Unexpected width_shift %d in misaligned_fpu_load, PC=%08lx\n",
 373                                width_shift, (unsigned long) regs->pc);
 374                        break;
 375                }
 376                return 0;
 377        } else {
 378                die ("Misaligned FPU load inside kernel", regs, 0);
 379                return -1;
 380        }
 381}
 382
 383static int misaligned_fpu_store(struct pt_regs *regs,
 384                           insn_size_t opcode,
 385                           int displacement_not_indexed,
 386                           int width_shift,
 387                           int do_paired_load)
 388{
 389        /* Return -1 for a fault, 0 for OK */
 390        int error;
 391        int srcreg;
 392        __u64 address;
 393
 394        error = generate_and_check_address(regs, opcode,
 395                        displacement_not_indexed, width_shift, &address);
 396        if (error < 0)
 397                return error;
 398
 399        srcreg = (opcode >> 4) & 0x3f;
 400        if (user_mode(regs)) {
 401                __u64 buffer;
 402                /* Initialise these to NaNs. */
 403                __u32 buflo=0xffffffffUL, bufhi=0xffffffffUL;
 404
 405                if (!access_ok(VERIFY_WRITE, (unsigned long) address, 1UL<<width_shift)) {
 406                        return -1;
 407                }
 408
 409                /* 'current' may be the current owner of the FPU state, so
 410                   context switch the registers into memory so they can be
 411                   indexed by register number. */
 412                if (last_task_used_math == current) {
 413                        enable_fpu();
 414                        save_fpu(current);
 415                        disable_fpu();
 416                        last_task_used_math = NULL;
 417                        regs->sr |= SR_FD;
 418                }
 419
 420                switch (width_shift) {
 421                case 2:
 422                        buflo = current->thread.xstate->hardfpu.fp_regs[srcreg];
 423                        break;
 424                case 3:
 425                        if (do_paired_load) {
 426                                buflo = current->thread.xstate->hardfpu.fp_regs[srcreg];
 427                                bufhi = current->thread.xstate->hardfpu.fp_regs[srcreg+1];
 428                        } else {
 429#if defined(CONFIG_CPU_LITTLE_ENDIAN)
 430                                bufhi = current->thread.xstate->hardfpu.fp_regs[srcreg];
 431                                buflo = current->thread.xstate->hardfpu.fp_regs[srcreg+1];
 432#else
 433                                buflo = current->thread.xstate->hardfpu.fp_regs[srcreg];
 434                                bufhi = current->thread.xstate->hardfpu.fp_regs[srcreg+1];
 435#endif
 436                        }
 437                        break;
 438                default:
 439                        printk("Unexpected width_shift %d in misaligned_fpu_store, PC=%08lx\n",
 440                                width_shift, (unsigned long) regs->pc);
 441                        break;
 442                }
 443
 444                *(__u32*) &buffer = buflo;
 445                *(1 + (__u32*) &buffer) = bufhi;
 446                if (__copy_user((void *)(int)address, &buffer, (1 << width_shift)) > 0) {
 447                        return -1; /* fault */
 448                }
 449                return 0;
 450        } else {
 451                die ("Misaligned FPU load inside kernel", regs, 0);
 452                return -1;
 453        }
 454}
 455
 456static int misaligned_fixup(struct pt_regs *regs)
 457{
 458        insn_size_t opcode;
 459        int error;
 460        int major, minor;
 461        unsigned int user_action;
 462
 463        user_action = unaligned_user_action();
 464        if (!(user_action & UM_FIXUP))
 465                return -1;
 466
 467        error = read_opcode(regs->pc, &opcode, user_mode(regs));
 468        if (error < 0) {
 469                return error;
 470        }
 471        major = (opcode >> 26) & 0x3f;
 472        minor = (opcode >> 16) & 0xf;
 473
 474        switch (major) {
 475                case (0x84>>2): /* LD.W */
 476                        error = misaligned_load(regs, opcode, 1, 1, 1);
 477                        break;
 478                case (0xb0>>2): /* LD.UW */
 479                        error = misaligned_load(regs, opcode, 1, 1, 0);
 480                        break;
 481                case (0x88>>2): /* LD.L */
 482                        error = misaligned_load(regs, opcode, 1, 2, 1);
 483                        break;
 484                case (0x8c>>2): /* LD.Q */
 485                        error = misaligned_load(regs, opcode, 1, 3, 0);
 486                        break;
 487
 488                case (0xa4>>2): /* ST.W */
 489                        error = misaligned_store(regs, opcode, 1, 1);
 490                        break;
 491                case (0xa8>>2): /* ST.L */
 492                        error = misaligned_store(regs, opcode, 1, 2);
 493                        break;
 494                case (0xac>>2): /* ST.Q */
 495                        error = misaligned_store(regs, opcode, 1, 3);
 496                        break;
 497
 498                case (0x40>>2): /* indexed loads */
 499                        switch (minor) {
 500                                case 0x1: /* LDX.W */
 501                                        error = misaligned_load(regs, opcode, 0, 1, 1);
 502                                        break;
 503                                case 0x5: /* LDX.UW */
 504                                        error = misaligned_load(regs, opcode, 0, 1, 0);
 505                                        break;
 506                                case 0x2: /* LDX.L */
 507                                        error = misaligned_load(regs, opcode, 0, 2, 1);
 508                                        break;
 509                                case 0x3: /* LDX.Q */
 510                                        error = misaligned_load(regs, opcode, 0, 3, 0);
 511                                        break;
 512                                default:
 513                                        error = -1;
 514                                        break;
 515                        }
 516                        break;
 517
 518                case (0x60>>2): /* indexed stores */
 519                        switch (minor) {
 520                                case 0x1: /* STX.W */
 521                                        error = misaligned_store(regs, opcode, 0, 1);
 522                                        break;
 523                                case 0x2: /* STX.L */
 524                                        error = misaligned_store(regs, opcode, 0, 2);
 525                                        break;
 526                                case 0x3: /* STX.Q */
 527                                        error = misaligned_store(regs, opcode, 0, 3);
 528                                        break;
 529                                default:
 530                                        error = -1;
 531                                        break;
 532                        }
 533                        break;
 534
 535                case (0x94>>2): /* FLD.S */
 536                        error = misaligned_fpu_load(regs, opcode, 1, 2, 0);
 537                        break;
 538                case (0x98>>2): /* FLD.P */
 539                        error = misaligned_fpu_load(regs, opcode, 1, 3, 1);
 540                        break;
 541                case (0x9c>>2): /* FLD.D */
 542                        error = misaligned_fpu_load(regs, opcode, 1, 3, 0);
 543                        break;
 544                case (0x1c>>2): /* floating indexed loads */
 545                        switch (minor) {
 546                        case 0x8: /* FLDX.S */
 547                                error = misaligned_fpu_load(regs, opcode, 0, 2, 0);
 548                                break;
 549                        case 0xd: /* FLDX.P */
 550                                error = misaligned_fpu_load(regs, opcode, 0, 3, 1);
 551                                break;
 552                        case 0x9: /* FLDX.D */
 553                                error = misaligned_fpu_load(regs, opcode, 0, 3, 0);
 554                                break;
 555                        default:
 556                                error = -1;
 557                                break;
 558                        }
 559                        break;
 560                case (0xb4>>2): /* FLD.S */
 561                        error = misaligned_fpu_store(regs, opcode, 1, 2, 0);
 562                        break;
 563                case (0xb8>>2): /* FLD.P */
 564                        error = misaligned_fpu_store(regs, opcode, 1, 3, 1);
 565                        break;
 566                case (0xbc>>2): /* FLD.D */
 567                        error = misaligned_fpu_store(regs, opcode, 1, 3, 0);
 568                        break;
 569                case (0x3c>>2): /* floating indexed stores */
 570                        switch (minor) {
 571                        case 0x8: /* FSTX.S */
 572                                error = misaligned_fpu_store(regs, opcode, 0, 2, 0);
 573                                break;
 574                        case 0xd: /* FSTX.P */
 575                                error = misaligned_fpu_store(regs, opcode, 0, 3, 1);
 576                                break;
 577                        case 0x9: /* FSTX.D */
 578                                error = misaligned_fpu_store(regs, opcode, 0, 3, 0);
 579                                break;
 580                        default:
 581                                error = -1;
 582                                break;
 583                        }
 584                        break;
 585
 586                default:
 587                        /* Fault */
 588                        error = -1;
 589                        break;
 590        }
 591
 592        if (error < 0) {
 593                return error;
 594        } else {
 595                regs->pc += 4; /* Skip the instruction that's just been emulated */
 596                return 0;
 597        }
 598}
 599
 600static void do_unhandled_exception(int signr, char *str, unsigned long error,
 601                                   struct pt_regs *regs)
 602{
 603        if (user_mode(regs))
 604                force_sig(signr, current);
 605
 606        die_if_no_fixup(str, regs, error);
 607}
 608
 609#define DO_ERROR(signr, str, name) \
 610asmlinkage void do_##name(unsigned long error_code, struct pt_regs *regs) \
 611{ \
 612        do_unhandled_exception(signr, str, error_code, regs); \
 613}
 614
 615DO_ERROR(SIGILL,  "illegal slot instruction", illegal_slot_inst)
 616DO_ERROR(SIGSEGV, "address error (exec)", address_error_exec)
 617
 618#if defined(CONFIG_SH64_ID2815_WORKAROUND)
 619
 620#define OPCODE_INVALID      0
 621#define OPCODE_USER_VALID   1
 622#define OPCODE_PRIV_VALID   2
 623
 624/* getcon/putcon - requires checking which control register is referenced. */
 625#define OPCODE_CTRL_REG     3
 626
 627/* Table of valid opcodes for SHmedia mode.
 628   Form a 10-bit value by concatenating the major/minor opcodes i.e.
 629   opcode[31:26,20:16].  The 6 MSBs of this value index into the following
 630   array.  The 4 LSBs select the bit-pair in the entry (bits 1:0 correspond to
 631   LSBs==4'b0000 etc). */
 632static unsigned long shmedia_opcode_table[64] = {
 633        0x55554044,0x54445055,0x15141514,0x14541414,0x00000000,0x10001000,0x01110055,0x04050015,
 634        0x00000444,0xc0000000,0x44545515,0x40405555,0x55550015,0x10005555,0x55555505,0x04050000,
 635        0x00000555,0x00000404,0x00040445,0x15151414,0x00000000,0x00000000,0x00000000,0x00000000,
 636        0x00000055,0x40404444,0x00000404,0xc0009495,0x00000000,0x00000000,0x00000000,0x00000000,
 637        0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,
 638        0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,
 639        0x80005050,0x04005055,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,
 640        0x81055554,0x00000404,0x55555555,0x55555555,0x00000000,0x00000000,0x00000000,0x00000000
 641};
 642
 643/* Workaround SH5-101 cut2 silicon defect #2815 :
 644   in some situations, inter-mode branches from SHcompact -> SHmedia
 645   which should take ITLBMISS or EXECPROT exceptions at the target
 646   falsely take RESINST at the target instead. */
 647void do_reserved_inst(unsigned long error_code, struct pt_regs *regs)
 648{
 649        insn_size_t opcode = 0x6ff4fff0; /* guaranteed reserved opcode */
 650        unsigned long pc, aligned_pc;
 651        unsigned long index, shift;
 652        unsigned long major, minor, combined;
 653        unsigned long reserved_field;
 654        int opcode_state;
 655        int get_user_error;
 656        int signr = SIGILL;
 657        char *exception_name = "reserved_instruction";
 658
 659        pc = regs->pc;
 660
 661        /* SHcompact is not handled */
 662        if (unlikely((pc & 3) == 0))
 663                goto out;
 664
 665        /* SHmedia : check for defect.  This requires executable vmas
 666           to be readable too. */
 667        aligned_pc = pc & ~3;
 668        if (!access_ok(VERIFY_READ, aligned_pc, sizeof(insn_size_t)))
 669                get_user_error = -EFAULT;
 670        else
 671                get_user_error = __get_user(opcode, (insn_size_t *)aligned_pc);
 672
 673        if (get_user_error < 0) {
 674                /*
 675                 * Error trying to read opcode.  This typically means a
 676                 * real fault, not a RESINST any more.  So change the
 677                 * codes.
 678                 */
 679                exception_name = "address error (exec)";
 680                signr = SIGSEGV;
 681                goto out;
 682        }
 683
 684        /* These bits are currently reserved as zero in all valid opcodes */
 685        reserved_field = opcode & 0xf;
 686        if (unlikely(reserved_field))
 687                goto out;       /* invalid opcode */
 688
 689        major = (opcode >> 26) & 0x3f;
 690        minor = (opcode >> 16) & 0xf;
 691        combined = (major << 4) | minor;
 692        index = major;
 693        shift = minor << 1;
 694        opcode_state = (shmedia_opcode_table[index] >> shift) & 0x3;
 695        switch (opcode_state) {
 696        case OPCODE_INVALID:
 697                /* Trap. */
 698                break;
 699        case OPCODE_USER_VALID:
 700                /*
 701                 * Restart the instruction: the branch to the instruction
 702                 * will now be from an RTE not from SHcompact so the
 703                 * silicon defect won't be triggered.
 704                 */
 705                return;
 706        case OPCODE_PRIV_VALID:
 707                if (!user_mode(regs)) {
 708                        /*
 709                         * Should only ever get here if a module has
 710                         * SHcompact code inside it. If so, the same fix
 711                         * up is needed.
 712                         */
 713                        return; /* same reason */
 714                }
 715
 716                /*
 717                 * Otherwise, user mode trying to execute a privileged
 718                 * instruction - fall through to trap.
 719                 */
 720                break;
 721        case OPCODE_CTRL_REG:
 722                /* If in privileged mode, return as above. */
 723                if (!user_mode(regs))
 724                        return;
 725
 726                /* In user mode ... */
 727                if (combined == 0x9f) { /* GETCON */
 728                        unsigned long regno = (opcode >> 20) & 0x3f;
 729
 730                        if (regno >= 62)
 731                                return;
 732
 733                        /* reserved/privileged control register => trap */
 734                } else if (combined == 0x1bf) { /* PUTCON */
 735                        unsigned long regno = (opcode >> 4) & 0x3f;
 736
 737                        if (regno >= 62)
 738                                return;
 739
 740                        /* reserved/privileged control register => trap */
 741                }
 742
 743                break;
 744        default:
 745                /* Fall through to trap. */
 746                break;
 747        }
 748
 749out:
 750        do_unhandled_exception(signr, exception_name, error_code, regs);
 751}
 752
 753#else /* CONFIG_SH64_ID2815_WORKAROUND */
 754
 755/* If the workaround isn't needed, this is just a straightforward reserved
 756   instruction */
 757DO_ERROR(SIGILL, "reserved instruction", reserved_inst)
 758
 759#endif /* CONFIG_SH64_ID2815_WORKAROUND */
 760
 761/* Called with interrupts disabled */
 762asmlinkage void do_exception_error(unsigned long ex, struct pt_regs *regs)
 763{
 764        die_if_kernel("exception", regs, ex);
 765}
 766
 767asmlinkage int do_unknown_trapa(unsigned long scId, struct pt_regs *regs)
 768{
 769        /* Syscall debug */
 770        printk("System call ID error: [0x1#args:8 #syscall:16  0x%lx]\n", scId);
 771
 772        die_if_kernel("unknown trapa", regs, scId);
 773
 774        return -ENOSYS;
 775}
 776
 777/* Implement misaligned load/store handling for kernel (and optionally for user
 778   mode too).  Limitation : only SHmedia mode code is handled - there is no
 779   handling at all for misaligned accesses occurring in SHcompact code yet. */
 780
 781asmlinkage void do_address_error_load(unsigned long error_code, struct pt_regs *regs)
 782{
 783        if (misaligned_fixup(regs) < 0)
 784                do_unhandled_exception(SIGSEGV, "address error(load)",
 785                                       error_code, regs);
 786}
 787
 788asmlinkage void do_address_error_store(unsigned long error_code, struct pt_regs *regs)
 789{
 790        if (misaligned_fixup(regs) < 0)
 791                do_unhandled_exception(SIGSEGV, "address error(store)",
 792                                error_code, regs);
 793}
 794
 795asmlinkage void do_debug_interrupt(unsigned long code, struct pt_regs *regs)
 796{
 797        u64 peek_real_address_q(u64 addr);
 798        u64 poke_real_address_q(u64 addr, u64 val);
 799        unsigned long long DM_EXP_CAUSE_PHY = 0x0c100010;
 800        unsigned long long exp_cause;
 801        /* It's not worth ioremapping the debug module registers for the amount
 802           of access we make to them - just go direct to their physical
 803           addresses. */
 804        exp_cause = peek_real_address_q(DM_EXP_CAUSE_PHY);
 805        if (exp_cause & ~4)
 806                printk("DM.EXP_CAUSE had unexpected bits set (=%08lx)\n",
 807                        (unsigned long)(exp_cause & 0xffffffff));
 808        show_state();
 809        /* Clear all DEBUGINT causes */
 810        poke_real_address_q(DM_EXP_CAUSE_PHY, 0x0);
 811}
 812
 813void __cpuinit per_cpu_trap_init(void)
 814{
 815        /* Nothing to do for now, VBR initialization later. */
 816}
 817