linux/arch/sh/kernel/traps_32.c
<<
>>
Prefs
   1/*
   2 * 'traps.c' handles hardware traps and faults after we have saved some
   3 * state in 'entry.S'.
   4 *
   5 *  SuperH version: Copyright (C) 1999 Niibe Yutaka
   6 *                  Copyright (C) 2000 Philipp Rumpf
   7 *                  Copyright (C) 2000 David Howells
   8 *                  Copyright (C) 2002 - 2007 Paul Mundt
   9 *
  10 * This file is subject to the terms and conditions of the GNU General Public
  11 * License.  See the file "COPYING" in the main directory of this archive
  12 * for more details.
  13 */
  14#include <linux/kernel.h>
  15#include <linux/ptrace.h>
  16#include <linux/hardirq.h>
  17#include <linux/init.h>
  18#include <linux/spinlock.h>
  19#include <linux/module.h>
  20#include <linux/kallsyms.h>
  21#include <linux/io.h>
  22#include <linux/bug.h>
  23#include <linux/debug_locks.h>
  24#include <linux/kdebug.h>
  25#include <linux/kexec.h>
  26#include <linux/limits.h>
  27#include <linux/proc_fs.h>
  28#include <linux/sysfs.h>
  29#include <asm/system.h>
  30#include <asm/uaccess.h>
  31#include <asm/fpu.h>
  32#include <asm/kprobes.h>
  33
  34#ifdef CONFIG_CPU_SH2
  35# define TRAP_RESERVED_INST     4
  36# define TRAP_ILLEGAL_SLOT_INST 6
  37# define TRAP_ADDRESS_ERROR     9
  38# ifdef CONFIG_CPU_SH2A
  39#  define TRAP_UBC              12
  40#  define TRAP_FPU_ERROR        13
  41#  define TRAP_DIVZERO_ERROR    17
  42#  define TRAP_DIVOVF_ERROR     18
  43# endif
  44#else
  45#define TRAP_RESERVED_INST      12
  46#define TRAP_ILLEGAL_SLOT_INST  13
  47#endif
  48
  49static unsigned long se_user;
  50static unsigned long se_sys;
  51static unsigned long se_half;
  52static unsigned long se_word;
  53static unsigned long se_dword;
  54static unsigned long se_multi;
  55/* bitfield: 1: warn 2: fixup 4: signal -> combinations 2|4 && 1|2|4 are not
  56   valid! */
  57static int se_usermode = 3;
  58/* 0: no warning 1: print a warning message, disabled by default */
  59static int se_kernmode_warn;
  60
  61#ifdef CONFIG_PROC_FS
  62static const char *se_usermode_action[] = {
  63        "ignored",
  64        "warn",
  65        "fixup",
  66        "fixup+warn",
  67        "signal",
  68        "signal+warn"
  69};
  70
  71static int
  72proc_alignment_read(char *page, char **start, off_t off, int count, int *eof,
  73                    void *data)
  74{
  75        char *p = page;
  76        int len;
  77
  78        p += sprintf(p, "User:\t\t%lu\n", se_user);
  79        p += sprintf(p, "System:\t\t%lu\n", se_sys);
  80        p += sprintf(p, "Half:\t\t%lu\n", se_half);
  81        p += sprintf(p, "Word:\t\t%lu\n", se_word);
  82        p += sprintf(p, "DWord:\t\t%lu\n", se_dword);
  83        p += sprintf(p, "Multi:\t\t%lu\n", se_multi);
  84        p += sprintf(p, "User faults:\t%i (%s)\n", se_usermode,
  85                        se_usermode_action[se_usermode]);
  86        p += sprintf(p, "Kernel faults:\t%i (fixup%s)\n", se_kernmode_warn,
  87                        se_kernmode_warn ? "+warn" : "");
  88
  89        len = (p - page) - off;
  90        if (len < 0)
  91                len = 0;
  92
  93        *eof = (len <= count) ? 1 : 0;
  94        *start = page + off;
  95
  96        return len;
  97}
  98
  99static int proc_alignment_write(struct file *file, const char __user *buffer,
 100                                unsigned long count, void *data)
 101{
 102        char mode;
 103
 104        if (count > 0) {
 105                if (get_user(mode, buffer))
 106                        return -EFAULT;
 107                if (mode >= '0' && mode <= '5')
 108                        se_usermode = mode - '0';
 109        }
 110        return count;
 111}
 112
 113static int proc_alignment_kern_write(struct file *file, const char __user *buffer,
 114                                     unsigned long count, void *data)
 115{
 116        char mode;
 117
 118        if (count > 0) {
 119                if (get_user(mode, buffer))
 120                        return -EFAULT;
 121                if (mode >= '0' && mode <= '1')
 122                        se_kernmode_warn = mode - '0';
 123        }
 124        return count;
 125}
 126#endif
 127
 128static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
 129{
 130        unsigned long p;
 131        int i;
 132
 133        printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
 134
 135        for (p = bottom & ~31; p < top; ) {
 136                printk("%04lx: ", p & 0xffff);
 137
 138                for (i = 0; i < 8; i++, p += 4) {
 139                        unsigned int val;
 140
 141                        if (p < bottom || p >= top)
 142                                printk("         ");
 143                        else {
 144                                if (__get_user(val, (unsigned int __user *)p)) {
 145                                        printk("\n");
 146                                        return;
 147                                }
 148                                printk("%08x ", val);
 149                        }
 150                }
 151                printk("\n");
 152        }
 153}
 154
 155static DEFINE_SPINLOCK(die_lock);
 156
 157void die(const char * str, struct pt_regs * regs, long err)
 158{
 159        static int die_counter;
 160
 161        oops_enter();
 162
 163        spin_lock_irq(&die_lock);
 164        console_verbose();
 165        bust_spinlocks(1);
 166
 167        printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
 168        sysfs_printk_last_file();
 169        print_modules();
 170        show_regs(regs);
 171
 172        printk("Process: %s (pid: %d, stack limit = %p)\n", current->comm,
 173                        task_pid_nr(current), task_stack_page(current) + 1);
 174
 175        if (!user_mode(regs) || in_interrupt())
 176                dump_mem("Stack: ", regs->regs[15], THREAD_SIZE +
 177                         (unsigned long)task_stack_page(current));
 178
 179        notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV);
 180
 181        bust_spinlocks(0);
 182        add_taint(TAINT_DIE);
 183        spin_unlock_irq(&die_lock);
 184        oops_exit();
 185
 186        if (kexec_should_crash(current))
 187                crash_kexec(regs);
 188
 189        if (in_interrupt())
 190                panic("Fatal exception in interrupt");
 191
 192        if (panic_on_oops)
 193                panic("Fatal exception");
 194
 195        do_exit(SIGSEGV);
 196}
 197
 198static inline void die_if_kernel(const char *str, struct pt_regs *regs,
 199                                 long err)
 200{
 201        if (!user_mode(regs))
 202                die(str, regs, err);
 203}
 204
 205/*
 206 * try and fix up kernelspace address errors
 207 * - userspace errors just cause EFAULT to be returned, resulting in SEGV
 208 * - kernel/userspace interfaces cause a jump to an appropriate handler
 209 * - other kernel errors are bad
 210 */
 211static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
 212{
 213        if (!user_mode(regs)) {
 214                const struct exception_table_entry *fixup;
 215                fixup = search_exception_tables(regs->pc);
 216                if (fixup) {
 217                        regs->pc = fixup->fixup;
 218                        return;
 219                }
 220
 221                die(str, regs, err);
 222        }
 223}
 224
 225static inline void sign_extend(unsigned int count, unsigned char *dst)
 226{
 227#ifdef __LITTLE_ENDIAN__
 228        if ((count == 1) && dst[0] & 0x80) {
 229                dst[1] = 0xff;
 230                dst[2] = 0xff;
 231                dst[3] = 0xff;
 232        }
 233        if ((count == 2) && dst[1] & 0x80) {
 234                dst[2] = 0xff;
 235                dst[3] = 0xff;
 236        }
 237#else
 238        if ((count == 1) && dst[3] & 0x80) {
 239                dst[2] = 0xff;
 240                dst[1] = 0xff;
 241                dst[0] = 0xff;
 242        }
 243        if ((count == 2) && dst[2] & 0x80) {
 244                dst[1] = 0xff;
 245                dst[0] = 0xff;
 246        }
 247#endif
 248}
 249
 250static struct mem_access user_mem_access = {
 251        copy_from_user,
 252        copy_to_user,
 253};
 254
 255/*
 256 * handle an instruction that does an unaligned memory access by emulating the
 257 * desired behaviour
 258 * - note that PC _may not_ point to the faulting instruction
 259 *   (if that instruction is in a branch delay slot)
 260 * - return 0 if emulation okay, -EFAULT on existential error
 261 */
 262static int handle_unaligned_ins(insn_size_t instruction, struct pt_regs *regs,
 263                                struct mem_access *ma)
 264{
 265        int ret, index, count;
 266        unsigned long *rm, *rn;
 267        unsigned char *src, *dst;
 268        unsigned char __user *srcu, *dstu;
 269
 270        index = (instruction>>8)&15;    /* 0x0F00 */
 271        rn = &regs->regs[index];
 272
 273        index = (instruction>>4)&15;    /* 0x00F0 */
 274        rm = &regs->regs[index];
 275
 276        count = 1<<(instruction&3);
 277
 278        switch (count) {
 279        case 1: se_half  += 1; break;
 280        case 2: se_word  += 1; break;
 281        case 4: se_dword += 1; break;
 282        case 8: se_multi += 1; break; /* ??? */
 283        }
 284
 285        ret = -EFAULT;
 286        switch (instruction>>12) {
 287        case 0: /* mov.[bwl] to/from memory via r0+rn */
 288                if (instruction & 8) {
 289                        /* from memory */
 290                        srcu = (unsigned char __user *)*rm;
 291                        srcu += regs->regs[0];
 292                        dst = (unsigned char *)rn;
 293                        *(unsigned long *)dst = 0;
 294
 295#if !defined(__LITTLE_ENDIAN__)
 296                        dst += 4-count;
 297#endif
 298                        if (ma->from(dst, srcu, count))
 299                                goto fetch_fault;
 300
 301                        sign_extend(count, dst);
 302                } else {
 303                        /* to memory */
 304                        src = (unsigned char *)rm;
 305#if !defined(__LITTLE_ENDIAN__)
 306                        src += 4-count;
 307#endif
 308                        dstu = (unsigned char __user *)*rn;
 309                        dstu += regs->regs[0];
 310
 311                        if (ma->to(dstu, src, count))
 312                                goto fetch_fault;
 313                }
 314                ret = 0;
 315                break;
 316
 317        case 1: /* mov.l Rm,@(disp,Rn) */
 318                src = (unsigned char*) rm;
 319                dstu = (unsigned char __user *)*rn;
 320                dstu += (instruction&0x000F)<<2;
 321
 322                if (ma->to(dstu, src, 4))
 323                        goto fetch_fault;
 324                ret = 0;
 325                break;
 326
 327        case 2: /* mov.[bwl] to memory, possibly with pre-decrement */
 328                if (instruction & 4)
 329                        *rn -= count;
 330                src = (unsigned char*) rm;
 331                dstu = (unsigned char __user *)*rn;
 332#if !defined(__LITTLE_ENDIAN__)
 333                src += 4-count;
 334#endif
 335                if (ma->to(dstu, src, count))
 336                        goto fetch_fault;
 337                ret = 0;
 338                break;
 339
 340        case 5: /* mov.l @(disp,Rm),Rn */
 341                srcu = (unsigned char __user *)*rm;
 342                srcu += (instruction & 0x000F) << 2;
 343                dst = (unsigned char *)rn;
 344                *(unsigned long *)dst = 0;
 345
 346                if (ma->from(dst, srcu, 4))
 347                        goto fetch_fault;
 348                ret = 0;
 349                break;
 350
 351        case 6: /* mov.[bwl] from memory, possibly with post-increment */
 352                srcu = (unsigned char __user *)*rm;
 353                if (instruction & 4)
 354                        *rm += count;
 355                dst = (unsigned char*) rn;
 356                *(unsigned long*)dst = 0;
 357
 358#if !defined(__LITTLE_ENDIAN__)
 359                dst += 4-count;
 360#endif
 361                if (ma->from(dst, srcu, count))
 362                        goto fetch_fault;
 363                sign_extend(count, dst);
 364                ret = 0;
 365                break;
 366
 367        case 8:
 368                switch ((instruction&0xFF00)>>8) {
 369                case 0x81: /* mov.w R0,@(disp,Rn) */
 370                        src = (unsigned char *) &regs->regs[0];
 371#if !defined(__LITTLE_ENDIAN__)
 372                        src += 2;
 373#endif
 374                        dstu = (unsigned char __user *)*rm; /* called Rn in the spec */
 375                        dstu += (instruction & 0x000F) << 1;
 376
 377                        if (ma->to(dstu, src, 2))
 378                                goto fetch_fault;
 379                        ret = 0;
 380                        break;
 381
 382                case 0x85: /* mov.w @(disp,Rm),R0 */
 383                        srcu = (unsigned char __user *)*rm;
 384                        srcu += (instruction & 0x000F) << 1;
 385                        dst = (unsigned char *) &regs->regs[0];
 386                        *(unsigned long *)dst = 0;
 387
 388#if !defined(__LITTLE_ENDIAN__)
 389                        dst += 2;
 390#endif
 391                        if (ma->from(dst, srcu, 2))
 392                                goto fetch_fault;
 393                        sign_extend(2, dst);
 394                        ret = 0;
 395                        break;
 396                }
 397                break;
 398        }
 399        return ret;
 400
 401 fetch_fault:
 402        /* Argh. Address not only misaligned but also non-existent.
 403         * Raise an EFAULT and see if it's trapped
 404         */
 405        die_if_no_fixup("Fault in unaligned fixup", regs, 0);
 406        return -EFAULT;
 407}
 408
 409/*
 410 * emulate the instruction in the delay slot
 411 * - fetches the instruction from PC+2
 412 */
 413static inline int handle_delayslot(struct pt_regs *regs,
 414                                   insn_size_t old_instruction,
 415                                   struct mem_access *ma)
 416{
 417        insn_size_t instruction;
 418        void __user *addr = (void __user *)(regs->pc +
 419                instruction_size(old_instruction));
 420
 421        if (copy_from_user(&instruction, addr, sizeof(instruction))) {
 422                /* the instruction-fetch faulted */
 423                if (user_mode(regs))
 424                        return -EFAULT;
 425
 426                /* kernel */
 427                die("delay-slot-insn faulting in handle_unaligned_delayslot",
 428                    regs, 0);
 429        }
 430
 431        return handle_unaligned_ins(instruction, regs, ma);
 432}
 433
 434/*
 435 * handle an instruction that does an unaligned memory access
 436 * - have to be careful of branch delay-slot instructions that fault
 437 *  SH3:
 438 *   - if the branch would be taken PC points to the branch
 439 *   - if the branch would not be taken, PC points to delay-slot
 440 *  SH4:
 441 *   - PC always points to delayed branch
 442 * - return 0 if handled, -EFAULT if failed (may not return if in kernel)
 443 */
 444
 445/* Macros to determine offset from current PC for branch instructions */
 446/* Explicit type coercion is used to force sign extension where needed */
 447#define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4)
 448#define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4)
 449
 450int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
 451                            struct mem_access *ma, int expected)
 452{
 453        u_int rm;
 454        int ret, index;
 455
 456        /*
 457         * XXX: We can't handle mixed 16/32-bit instructions yet
 458         */
 459        if (instruction_size(instruction) != 2)
 460                return -EINVAL;
 461
 462        index = (instruction>>8)&15;    /* 0x0F00 */
 463        rm = regs->regs[index];
 464
 465        /* shout about fixups */
 466        if (!expected && printk_ratelimit())
 467                printk(KERN_NOTICE "Fixing up unaligned %s access "
 468                       "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
 469                       user_mode(regs) ? "userspace" : "kernel",
 470                       current->comm, task_pid_nr(current),
 471                       (void *)regs->pc, instruction);
 472
 473        ret = -EFAULT;
 474        switch (instruction&0xF000) {
 475        case 0x0000:
 476                if (instruction==0x000B) {
 477                        /* rts */
 478                        ret = handle_delayslot(regs, instruction, ma);
 479                        if (ret==0)
 480                                regs->pc = regs->pr;
 481                }
 482                else if ((instruction&0x00FF)==0x0023) {
 483                        /* braf @Rm */
 484                        ret = handle_delayslot(regs, instruction, ma);
 485                        if (ret==0)
 486                                regs->pc += rm + 4;
 487                }
 488                else if ((instruction&0x00FF)==0x0003) {
 489                        /* bsrf @Rm */
 490                        ret = handle_delayslot(regs, instruction, ma);
 491                        if (ret==0) {
 492                                regs->pr = regs->pc + 4;
 493                                regs->pc += rm + 4;
 494                        }
 495                }
 496                else {
 497                        /* mov.[bwl] to/from memory via r0+rn */
 498                        goto simple;
 499                }
 500                break;
 501
 502        case 0x1000: /* mov.l Rm,@(disp,Rn) */
 503                goto simple;
 504
 505        case 0x2000: /* mov.[bwl] to memory, possibly with pre-decrement */
 506                goto simple;
 507
 508        case 0x4000:
 509                if ((instruction&0x00FF)==0x002B) {
 510                        /* jmp @Rm */
 511                        ret = handle_delayslot(regs, instruction, ma);
 512                        if (ret==0)
 513                                regs->pc = rm;
 514                }
 515                else if ((instruction&0x00FF)==0x000B) {
 516                        /* jsr @Rm */
 517                        ret = handle_delayslot(regs, instruction, ma);
 518                        if (ret==0) {
 519                                regs->pr = regs->pc + 4;
 520                                regs->pc = rm;
 521                        }
 522                }
 523                else {
 524                        /* mov.[bwl] to/from memory via r0+rn */
 525                        goto simple;
 526                }
 527                break;
 528
 529        case 0x5000: /* mov.l @(disp,Rm),Rn */
 530                goto simple;
 531
 532        case 0x6000: /* mov.[bwl] from memory, possibly with post-increment */
 533                goto simple;
 534
 535        case 0x8000: /* bf lab, bf/s lab, bt lab, bt/s lab */
 536                switch (instruction&0x0F00) {
 537                case 0x0100: /* mov.w R0,@(disp,Rm) */
 538                        goto simple;
 539                case 0x0500: /* mov.w @(disp,Rm),R0 */
 540                        goto simple;
 541                case 0x0B00: /* bf   lab - no delayslot*/
 542                        break;
 543                case 0x0F00: /* bf/s lab */
 544                        ret = handle_delayslot(regs, instruction, ma);
 545                        if (ret==0) {
 546#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
 547                                if ((regs->sr & 0x00000001) != 0)
 548                                        regs->pc += 4; /* next after slot */
 549                                else
 550#endif
 551                                        regs->pc += SH_PC_8BIT_OFFSET(instruction);
 552                        }
 553                        break;
 554                case 0x0900: /* bt   lab - no delayslot */
 555                        break;
 556                case 0x0D00: /* bt/s lab */
 557                        ret = handle_delayslot(regs, instruction, ma);
 558                        if (ret==0) {
 559#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
 560                                if ((regs->sr & 0x00000001) == 0)
 561                                        regs->pc += 4; /* next after slot */
 562                                else
 563#endif
 564                                        regs->pc += SH_PC_8BIT_OFFSET(instruction);
 565                        }
 566                        break;
 567                }
 568                break;
 569
 570        case 0xA000: /* bra label */
 571                ret = handle_delayslot(regs, instruction, ma);
 572                if (ret==0)
 573                        regs->pc += SH_PC_12BIT_OFFSET(instruction);
 574                break;
 575
 576        case 0xB000: /* bsr label */
 577                ret = handle_delayslot(regs, instruction, ma);
 578                if (ret==0) {
 579                        regs->pr = regs->pc + 4;
 580                        regs->pc += SH_PC_12BIT_OFFSET(instruction);
 581                }
 582                break;
 583        }
 584        return ret;
 585
 586        /* handle non-delay-slot instruction */
 587 simple:
 588        ret = handle_unaligned_ins(instruction, regs, ma);
 589        if (ret==0)
 590                regs->pc += instruction_size(instruction);
 591        return ret;
 592}
 593
 594/*
 595 * Handle various address error exceptions:
 596 *  - instruction address error:
 597 *       misaligned PC
 598 *       PC >= 0x80000000 in user mode
 599 *  - data address error (read and write)
 600 *       misaligned data access
 601 *       access to >= 0x80000000 is user mode
 602 * Unfortuntaly we can't distinguish between instruction address error
 603 * and data address errors caused by read accesses.
 604 */
 605asmlinkage void do_address_error(struct pt_regs *regs,
 606                                 unsigned long writeaccess,
 607                                 unsigned long address)
 608{
 609        unsigned long error_code = 0;
 610        mm_segment_t oldfs;
 611        siginfo_t info;
 612        insn_size_t instruction;
 613        int tmp;
 614
 615        /* Intentional ifdef */
 616#ifdef CONFIG_CPU_HAS_SR_RB
 617        error_code = lookup_exception_vector();
 618#endif
 619
 620        oldfs = get_fs();
 621
 622        if (user_mode(regs)) {
 623                int si_code = BUS_ADRERR;
 624
 625                local_irq_enable();
 626
 627                se_user += 1;
 628
 629                set_fs(USER_DS);
 630                if (copy_from_user(&instruction, (insn_size_t *)(regs->pc & ~1),
 631                                   sizeof(instruction))) {
 632                        set_fs(oldfs);
 633                        goto uspace_segv;
 634                }
 635                set_fs(oldfs);
 636
 637                /* shout about userspace fixups */
 638                if (se_usermode & 1)
 639                        printk(KERN_NOTICE "Unaligned userspace access "
 640                               "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
 641                               current->comm, current->pid, (void *)regs->pc,
 642                               instruction);
 643
 644                if (se_usermode & 2)
 645                        goto fixup;
 646
 647                if (se_usermode & 4)
 648                        goto uspace_segv;
 649                else {
 650                        /* ignore */
 651                        regs->pc += instruction_size(instruction);
 652                        return;
 653                }
 654
 655fixup:
 656                /* bad PC is not something we can fix */
 657                if (regs->pc & 1) {
 658                        si_code = BUS_ADRALN;
 659                        goto uspace_segv;
 660                }
 661
 662                set_fs(USER_DS);
 663                tmp = handle_unaligned_access(instruction, regs,
 664                                              &user_mem_access, 0);
 665                set_fs(oldfs);
 666
 667                if (tmp==0)
 668                        return; /* sorted */
 669uspace_segv:
 670                printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned "
 671                       "access (PC %lx PR %lx)\n", current->comm, regs->pc,
 672                       regs->pr);
 673
 674                info.si_signo = SIGBUS;
 675                info.si_errno = 0;
 676                info.si_code = si_code;
 677                info.si_addr = (void __user *)address;
 678                force_sig_info(SIGBUS, &info, current);
 679        } else {
 680                se_sys += 1;
 681
 682                if (regs->pc & 1)
 683                        die("unaligned program counter", regs, error_code);
 684
 685                set_fs(KERNEL_DS);
 686                if (copy_from_user(&instruction, (void __user *)(regs->pc),
 687                                   sizeof(instruction))) {
 688                        /* Argh. Fault on the instruction itself.
 689                           This should never happen non-SMP
 690                        */
 691                        set_fs(oldfs);
 692                        die("insn faulting in do_address_error", regs, 0);
 693                }
 694
 695                if (se_kernmode_warn)
 696                        printk(KERN_NOTICE "Unaligned kernel access "
 697                               "on behalf of \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
 698                               current->comm, current->pid, (void *)regs->pc,
 699                               instruction);
 700
 701                handle_unaligned_access(instruction, regs,
 702                                        &user_mem_access, 0);
 703                set_fs(oldfs);
 704        }
 705}
 706
 707#ifdef CONFIG_SH_DSP
 708/*
 709 *      SH-DSP support gerg@snapgear.com.
 710 */
 711int is_dsp_inst(struct pt_regs *regs)
 712{
 713        unsigned short inst = 0;
 714
 715        /*
 716         * Safe guard if DSP mode is already enabled or we're lacking
 717         * the DSP altogether.
 718         */
 719        if (!(current_cpu_data.flags & CPU_HAS_DSP) || (regs->sr & SR_DSP))
 720                return 0;
 721
 722        get_user(inst, ((unsigned short *) regs->pc));
 723
 724        inst &= 0xf000;
 725
 726        /* Check for any type of DSP or support instruction */
 727        if ((inst == 0xf000) || (inst == 0x4000))
 728                return 1;
 729
 730        return 0;
 731}
 732#else
 733#define is_dsp_inst(regs)       (0)
 734#endif /* CONFIG_SH_DSP */
 735
 736#ifdef CONFIG_CPU_SH2A
 737asmlinkage void do_divide_error(unsigned long r4, unsigned long r5,
 738                                unsigned long r6, unsigned long r7,
 739                                struct pt_regs __regs)
 740{
 741        siginfo_t info;
 742
 743        switch (r4) {
 744        case TRAP_DIVZERO_ERROR:
 745                info.si_code = FPE_INTDIV;
 746                break;
 747        case TRAP_DIVOVF_ERROR:
 748                info.si_code = FPE_INTOVF;
 749                break;
 750        }
 751
 752        force_sig_info(SIGFPE, &info, current);
 753}
 754#endif
 755
 756asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
 757                                unsigned long r6, unsigned long r7,
 758                                struct pt_regs __regs)
 759{
 760        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 761        unsigned long error_code;
 762        struct task_struct *tsk = current;
 763
 764#ifdef CONFIG_SH_FPU_EMU
 765        unsigned short inst = 0;
 766        int err;
 767
 768        get_user(inst, (unsigned short*)regs->pc);
 769
 770        err = do_fpu_inst(inst, regs);
 771        if (!err) {
 772                regs->pc += instruction_size(inst);
 773                return;
 774        }
 775        /* not a FPU inst. */
 776#endif
 777
 778#ifdef CONFIG_SH_DSP
 779        /* Check if it's a DSP instruction */
 780        if (is_dsp_inst(regs)) {
 781                /* Enable DSP mode, and restart instruction. */
 782                regs->sr |= SR_DSP;
 783                /* Save DSP mode */
 784                tsk->thread.dsp_status.status |= SR_DSP;
 785                return;
 786        }
 787#endif
 788
 789        error_code = lookup_exception_vector();
 790
 791        local_irq_enable();
 792        force_sig(SIGILL, tsk);
 793        die_if_no_fixup("reserved instruction", regs, error_code);
 794}
 795
 796#ifdef CONFIG_SH_FPU_EMU
 797static int emulate_branch(unsigned short inst, struct pt_regs *regs)
 798{
 799        /*
 800         * bfs: 8fxx: PC+=d*2+4;
 801         * bts: 8dxx: PC+=d*2+4;
 802         * bra: axxx: PC+=D*2+4;
 803         * bsr: bxxx: PC+=D*2+4  after PR=PC+4;
 804         * braf:0x23: PC+=Rn*2+4;
 805         * bsrf:0x03: PC+=Rn*2+4 after PR=PC+4;
 806         * jmp: 4x2b: PC=Rn;
 807         * jsr: 4x0b: PC=Rn      after PR=PC+4;
 808         * rts: 000b: PC=PR;
 809         */
 810        if (((inst & 0xf000) == 0xb000)  ||     /* bsr */
 811            ((inst & 0xf0ff) == 0x0003)  ||     /* bsrf */
 812            ((inst & 0xf0ff) == 0x400b))        /* jsr */
 813                regs->pr = regs->pc + 4;
 814
 815        if ((inst & 0xfd00) == 0x8d00) {        /* bfs, bts */
 816                regs->pc += SH_PC_8BIT_OFFSET(inst);
 817                return 0;
 818        }
 819
 820        if ((inst & 0xe000) == 0xa000) {        /* bra, bsr */
 821                regs->pc += SH_PC_12BIT_OFFSET(inst);
 822                return 0;
 823        }
 824
 825        if ((inst & 0xf0df) == 0x0003) {        /* braf, bsrf */
 826                regs->pc += regs->regs[(inst & 0x0f00) >> 8] + 4;
 827                return 0;
 828        }
 829
 830        if ((inst & 0xf0df) == 0x400b) {        /* jmp, jsr */
 831                regs->pc = regs->regs[(inst & 0x0f00) >> 8];
 832                return 0;
 833        }
 834
 835        if ((inst & 0xffff) == 0x000b) {        /* rts */
 836                regs->pc = regs->pr;
 837                return 0;
 838        }
 839
 840        return 1;
 841}
 842#endif
 843
 844asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
 845                                unsigned long r6, unsigned long r7,
 846                                struct pt_regs __regs)
 847{
 848        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 849        unsigned long inst;
 850        struct task_struct *tsk = current;
 851
 852        if (kprobe_handle_illslot(regs->pc) == 0)
 853                return;
 854
 855#ifdef CONFIG_SH_FPU_EMU
 856        get_user(inst, (unsigned short *)regs->pc + 1);
 857        if (!do_fpu_inst(inst, regs)) {
 858                get_user(inst, (unsigned short *)regs->pc);
 859                if (!emulate_branch(inst, regs))
 860                        return;
 861                /* fault in branch.*/
 862        }
 863        /* not a FPU inst. */
 864#endif
 865
 866        inst = lookup_exception_vector();
 867
 868        local_irq_enable();
 869        force_sig(SIGILL, tsk);
 870        die_if_no_fixup("illegal slot instruction", regs, inst);
 871}
 872
 873asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
 874                                   unsigned long r6, unsigned long r7,
 875                                   struct pt_regs __regs)
 876{
 877        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 878        long ex;
 879
 880        ex = lookup_exception_vector();
 881        die_if_kernel("exception", regs, ex);
 882}
 883
 884#if defined(CONFIG_SH_STANDARD_BIOS)
 885void *gdb_vbr_vector;
 886
 887static inline void __init gdb_vbr_init(void)
 888{
 889        register unsigned long vbr;
 890
 891        /*
 892         * Read the old value of the VBR register to initialise
 893         * the vector through which debug and BIOS traps are
 894         * delegated by the Linux trap handler.
 895         */
 896        asm volatile("stc vbr, %0" : "=r" (vbr));
 897
 898        gdb_vbr_vector = (void *)(vbr + 0x100);
 899        printk("Setting GDB trap vector to 0x%08lx\n",
 900               (unsigned long)gdb_vbr_vector);
 901}
 902#endif
 903
 904void __cpuinit per_cpu_trap_init(void)
 905{
 906        extern void *vbr_base;
 907
 908#ifdef CONFIG_SH_STANDARD_BIOS
 909        if (raw_smp_processor_id() == 0)
 910                gdb_vbr_init();
 911#endif
 912
 913        /* NOTE: The VBR value should be at P1
 914           (or P2, virtural "fixed" address space).
 915           It's definitely should not in physical address.  */
 916
 917        asm volatile("ldc       %0, vbr"
 918                     : /* no output */
 919                     : "r" (&vbr_base)
 920                     : "memory");
 921}
 922
 923void *set_exception_table_vec(unsigned int vec, void *handler)
 924{
 925        extern void *exception_handling_table[];
 926        void *old_handler;
 927
 928        old_handler = exception_handling_table[vec];
 929        exception_handling_table[vec] = handler;
 930        return old_handler;
 931}
 932
 933void __init trap_init(void)
 934{
 935        set_exception_table_vec(TRAP_RESERVED_INST, do_reserved_inst);
 936        set_exception_table_vec(TRAP_ILLEGAL_SLOT_INST, do_illegal_slot_inst);
 937
 938#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_FPU) || \
 939    defined(CONFIG_SH_FPU_EMU)
 940        /*
 941         * For SH-4 lacking an FPU, treat floating point instructions as
 942         * reserved. They'll be handled in the math-emu case, or faulted on
 943         * otherwise.
 944         */
 945        set_exception_table_evt(0x800, do_reserved_inst);
 946        set_exception_table_evt(0x820, do_illegal_slot_inst);
 947#elif defined(CONFIG_SH_FPU)
 948#ifdef CONFIG_CPU_SUBTYPE_SHX3
 949        set_exception_table_evt(0xd80, fpu_state_restore_trap_handler);
 950        set_exception_table_evt(0xda0, fpu_state_restore_trap_handler);
 951#else
 952        set_exception_table_evt(0x800, fpu_state_restore_trap_handler);
 953        set_exception_table_evt(0x820, fpu_state_restore_trap_handler);
 954#endif
 955#endif
 956
 957#ifdef CONFIG_CPU_SH2
 958        set_exception_table_vec(TRAP_ADDRESS_ERROR, address_error_trap_handler);
 959#endif
 960#ifdef CONFIG_CPU_SH2A
 961        set_exception_table_vec(TRAP_DIVZERO_ERROR, do_divide_error);
 962        set_exception_table_vec(TRAP_DIVOVF_ERROR, do_divide_error);
 963#ifdef CONFIG_SH_FPU
 964        set_exception_table_vec(TRAP_FPU_ERROR, fpu_error_trap_handler);
 965#endif
 966#endif
 967
 968#ifdef TRAP_UBC
 969        set_exception_table_vec(TRAP_UBC, break_point_trap);
 970#endif
 971
 972        /* Setup VBR for boot cpu */
 973        per_cpu_trap_init();
 974}
 975
 976void show_stack(struct task_struct *tsk, unsigned long *sp)
 977{
 978        unsigned long stack;
 979
 980        if (!tsk)
 981                tsk = current;
 982        if (tsk == current)
 983                sp = (unsigned long *)current_stack_pointer;
 984        else
 985                sp = (unsigned long *)tsk->thread.sp;
 986
 987        stack = (unsigned long)sp;
 988        dump_mem("Stack: ", stack, THREAD_SIZE +
 989                 (unsigned long)task_stack_page(tsk));
 990        show_trace(tsk, sp, NULL);
 991}
 992
 993void dump_stack(void)
 994{
 995        show_stack(NULL, NULL);
 996}
 997EXPORT_SYMBOL(dump_stack);
 998
 999#ifdef CONFIG_PROC_FS
1000/*
1001 * This needs to be done after sysctl_init, otherwise sys/ will be
1002 * overwritten.  Actually, this shouldn't be in sys/ at all since
1003 * it isn't a sysctl, and it doesn't contain sysctl information.
1004 * We now locate it in /proc/cpu/alignment instead.
1005 */
1006static int __init alignment_init(void)
1007{
1008        struct proc_dir_entry *dir, *res;
1009
1010        dir = proc_mkdir("cpu", NULL);
1011        if (!dir)
1012                return -ENOMEM;
1013
1014        res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, dir);
1015        if (!res)
1016                return -ENOMEM;
1017
1018        res->read_proc = proc_alignment_read;
1019        res->write_proc = proc_alignment_write;
1020
1021        res = create_proc_entry("kernel_alignment", S_IWUSR | S_IRUGO, dir);
1022        if (!res)
1023                return -ENOMEM;
1024
1025        res->read_proc = proc_alignment_read;
1026        res->write_proc = proc_alignment_kern_write;
1027
1028        return 0;
1029}
1030
1031fs_initcall(alignment_init);
1032#endif
1033