root/arch/alpha/kernel/traps.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. die_if_kernel
  2. do_entArith
  3. do_entIF
  4. do_entUna
  5. do_entUnaUser
  6. do_entSys
  7. trap_init

   1 /*
   2  * kernel/traps.c
   3  *
   4  * (C) Copyright 1994 Linus Torvalds
   5  */
   6 
   7 /*
   8  * This file initializes the trap entry points
   9  */
  10 
  11 #include <linux/mm.h>
  12 #include <linux/sched.h>
  13 #include <linux/tty.h>
  14 
  15 #include <asm/unaligned.h>
  16 #include <asm/gentrap.h>
  17 
  18 void die_if_kernel(char * str, struct pt_regs * regs, long err)
     /* [previous][next][first][last][top][bottom][index][help] */
  19 {
  20         long i;
  21         unsigned long sp;
  22         unsigned int * pc;
  23 
  24         if (regs->ps & 8)
  25                 return;
  26         printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err);
  27         sp = (unsigned long) (regs+1);
  28         printk("pc = %lx ps = %04lx\n", regs->pc, regs->ps);
  29         printk("rp = %lx sp = %lx\n", regs->r26, sp);
  30         printk("r0=%lx r1=%lx r2=%lx r3=%lx\n",
  31                 regs->r0, regs->r1, regs->r2, regs->r3);
  32         printk("r8=%lx\n", regs->r8);
  33         printk("r16=%lx r17=%lx r18=%lx r19=%lx\n",
  34                 regs->r16, regs->r17, regs->r18, regs->r19);
  35         printk("r20=%lx r21=%lx r22=%lx r23=%lx\n",
  36                 regs->r20, regs->r21, regs->r22, regs->r23);
  37         printk("r24=%lx r25=%lx r26=%lx r27=%lx\n",
  38                 regs->r24, regs->r25, regs->r26, regs->r27);
  39         printk("r28=%lx r29=%lx r30=%lx\n",
  40                 regs->r28, regs->gp, sp);
  41         printk("Code:");
  42         pc = (unsigned int *) regs->pc;
  43         for (i = -3; i < 6; i++)
  44                 printk("%c%08x%c",i?' ':'<',pc[i],i?' ':'>');
  45         printk("\n");
  46         do_exit(SIGSEGV);
  47 }
  48 
  49 asmlinkage void do_entArith(unsigned long summary, unsigned long write_mask,
     /* [previous][next][first][last][top][bottom][index][help] */
  50         unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5,
  51         struct pt_regs regs)
  52 {
  53         printk("Arithmetic trap: %02lx %016lx\n", summary, write_mask);
  54         die_if_kernel("Arithmetic fault", &regs, 0);
  55         send_sig(SIGFPE, current, 1);
  56 }
  57 
  58 asmlinkage void do_entIF(unsigned long type, unsigned long a1, unsigned long a2,
     /* [previous][next][first][last][top][bottom][index][help] */
  59         unsigned long a3, unsigned long a4, unsigned long a5,
  60         struct pt_regs regs)
  61 {
  62         extern int ptrace_cancel_bpt (struct task_struct *who);
  63 
  64         die_if_kernel("Instruction fault", &regs, type);
  65         switch (type) {
  66               case 0: /* breakpoint */
  67                 if (ptrace_cancel_bpt(current)) {
  68                         regs.pc -= 4;   /* make pc point to former bpt */
  69                 }
  70                 send_sig(SIGTRAP, current, 1);
  71                 break;
  72 
  73               case 2: /* gentrap */
  74                 /*
  75                  * The translation from the gentrap error code into a
  76                  * siginfo structure (see /usr/include/sys/siginfo.h)
  77                  * is missing as Linux does not presently support the
  78                  * siginfo argument that is normally passed to a
  79                  * signal handler.
  80                  */
  81                 switch ((long) regs.r16) {
  82                       case GEN_INTOVF: case GEN_INTDIV: case GEN_FLTOVF:
  83                       case GEN_FLTDIV: case GEN_FLTUND: case GEN_FLTINV:
  84                       case GEN_FLTINE:
  85                         send_sig(SIGFPE, current, 1);
  86                         break;
  87 
  88                       case GEN_DECOVF:
  89                       case GEN_DECDIV:
  90                       case GEN_DECINV:
  91                       case GEN_ROPRAND:
  92                       case GEN_ASSERTERR:
  93                       case GEN_NULPTRERR:
  94                       case GEN_STKOVF:
  95                       case GEN_STRLENERR:
  96                       case GEN_SUBSTRERR:
  97                       case GEN_RANGERR:
  98                       case GEN_SUBRNG:
  99                       case GEN_SUBRNG1:
 100                       case GEN_SUBRNG2:
 101                       case GEN_SUBRNG3:
 102                       case GEN_SUBRNG4:
 103                       case GEN_SUBRNG5:
 104                       case GEN_SUBRNG6:
 105                       case GEN_SUBRNG7:
 106                         send_sig(SIGILL, current, 1);
 107                         break;
 108                 }
 109                 break;
 110 
 111               case 1: /* bugcheck */
 112               case 3: /* FEN fault */
 113               case 4: /* opDEC */
 114                 send_sig(SIGILL, current, 1);
 115                 break;
 116 
 117               default:
 118                 panic("do_entIF: unexpected instruction-fault type");
 119         }
 120 }
 121 
 122 /*
 123  * entUna has a different register layout to be reasonably simple. It
 124  * needs access to all the integer registers (the kernel doesn't use
 125  * fp-regs), and it needs to have them in order for simpler access.
 126  *
 127  * Due to the non-standard register layout (and because we don't want
 128  * to handle floating-point regs), user-mode unaligned accesses are
 129  * handled separately by do_entUnaUser below.
 130  *
 131  * Oh, btw, we don't handle the "gp" register correctly, but if we fault
 132  * on a gp-register unaligned load/store, something is _very_ wrong
 133  * in the kernel anyway..
 134  */
 135 struct allregs {
 136         unsigned long regs[32];
 137         unsigned long ps, pc, gp, a0, a1, a2;
 138 };
 139 
 140 struct unaligned_stat {
 141         unsigned long count, va, pc;
 142 } unaligned[2];
 143 
 144 asmlinkage void do_entUna(void * va, unsigned long opcode, unsigned long reg,
     /* [previous][next][first][last][top][bottom][index][help] */
 145         unsigned long a3, unsigned long a4, unsigned long a5,
 146         struct allregs regs)
 147 {
 148         static int cnt = 0;
 149         static long last_time = 0;
 150 
 151         if (cnt >= 5 && jiffies - last_time > 5*HZ) {
 152                 cnt = 0;
 153         }
 154         if (++cnt < 5) {
 155                 printk("kernel: unaligned trap at %016lx: %p %lx %ld\n",
 156                        regs.pc - 4, va, opcode, reg);
 157         }
 158         last_time = jiffies;
 159 
 160         ++unaligned[0].count;
 161         unaligned[0].va = (unsigned long) va - 4;
 162         unaligned[0].pc = regs.pc;
 163 
 164         /* $16-$18 are PAL-saved, and are offset by 19 entries */
 165         if (reg >= 16 && reg <= 18)
 166                 reg += 19;
 167         switch (opcode) {
 168                 case 0x28: /* ldl */
 169                         *(reg+regs.regs) = (int) ldl_u(va);
 170                         return;
 171                 case 0x29: /* ldq */
 172                         *(reg+regs.regs) = ldq_u(va);
 173                         return;
 174                 case 0x2c: /* stl */
 175                         stl_u(*(reg+regs.regs), va);
 176                         return;
 177                 case 0x2d: /* stq */
 178                         stq_u(*(reg+regs.regs), va);
 179                         return;
 180         }
 181         printk("Bad unaligned kernel access at %016lx: %p %lx %ld\n",
 182                 regs.pc, va, opcode, reg);
 183         do_exit(SIGSEGV);
 184 }
 185 
 186 /*
 187  * Handle user-level unaligned fault.  Handling user-level unaligned
 188  * faults is *extremely* slow and produces nasty messages.  A user
 189  * program *should* fix unaligned faults ASAP.
 190  *
 191  * Notice that we have (almost) the regular kernel stack layout here,
 192  * so finding the appropriate registers is a little more difficult
 193  * than in the kernel case.
 194  *
 195  * Finally, we handle regular integer load/stores only.  In
 196  * particular, load-linked/store-conditionally and floating point
 197  * load/stores are not supported.  The former make no sense with
 198  * unaligned faults (they are guaranteed to fail) and I don't think
 199  * the latter will occur in any decent program.
 200  */
 201 asmlinkage void do_entUnaUser(void * va, unsigned long opcode, unsigned long reg,
     /* [previous][next][first][last][top][bottom][index][help] */
 202                               unsigned long * frame)
 203 {
 204         long dir, size;
 205         unsigned long *reg_addr, *pc_addr, usp, zero = 0;
 206         static int cnt = 0;
 207         static long last_time = 0;
 208 
 209         pc_addr = frame + 7 + 20 + 1;                   /* pc in PAL frame */
 210 
 211         if (cnt >= 5 && jiffies - last_time > 5*HZ) {
 212                 cnt = 0;
 213         }
 214         if (++cnt < 5) {
 215                 printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
 216                        current->comm, current->pid,
 217                        *pc_addr - 4, va, opcode, reg);
 218         }
 219         last_time = jiffies;
 220 
 221         ++unaligned[1].count;
 222         unaligned[1].va = (unsigned long) va - 4;
 223         unaligned[1].pc = *pc_addr;
 224 
 225         dir = VERIFY_READ;
 226         if (opcode > 0x29) {
 227                 /* it's a stl or stq */
 228                 dir = VERIFY_WRITE;
 229         }
 230         size = 4;
 231         if (opcode & 1) {
 232                 /* it's a quadword op */
 233                 size = 8;
 234         }
 235         if (verify_area(dir, va, size)) {
 236                 *pc_addr -= 4;  /* make pc point to faulting insn */
 237                 send_sig(SIGSEGV, current, 1);
 238                 return;
 239         }
 240 
 241         reg_addr = frame;
 242         if (reg < 9) {
 243                 reg_addr += 7 + reg;                    /* v0-t7 in SAVE_ALL frame */
 244         } else if (reg < 16) {
 245                 reg_addr += (reg - 9);                  /* s0-s6 in entUna frame */
 246         } else if (reg < 19) {
 247                 reg_addr += 7 + 20 + 3 + (reg - 16);    /* a0-a2 in PAL frame */
 248         } else if (reg < 29) {
 249                 reg_addr += 7 + 9 + (reg - 19);         /* a3-at in SAVE_ALL frame */
 250         } else {
 251                 switch (reg) {
 252                         case 29:                        /* gp in PAL frame */
 253                                 reg_addr += 7 + 20 + 2;
 254                                 break;
 255                         case 30:                        /* usp in PAL regs */
 256                                 usp = rdusp();
 257                                 reg_addr = &usp;
 258                                 break;
 259                         case 31:                        /* zero "register" */
 260                                 reg_addr = &zero;
 261                                 break;
 262                 }
 263         }
 264 
 265         switch (opcode) {
 266                 case 0x28: *reg_addr = (int) ldl_u(va); break;  /* ldl */
 267                 case 0x29: *reg_addr = ldq_u(va);       break;  /* ldq */
 268                 case 0x2c: stl_u(*reg_addr, va);        break;  /* stl */
 269                 case 0x2d: stq_u(*reg_addr, va);        break;  /* stq */
 270                 default:
 271                         *pc_addr -= 4;  /* make pc point to faulting insn */
 272                         send_sig(SIGBUS, current, 1);
 273                         return;
 274         }
 275 
 276         if (reg == 30 && dir == VERIFY_WRITE) {
 277                 wrusp(usp);
 278         } 
 279 }
 280 
 281 /*
 282  * DEC means people to use the "retsys" instruction for return from
 283  * a system call, but they are clearly misguided about this. We use
 284  * "rti" in all cases, and fill in the stack with the return values.
 285  * That should make signal handling etc much cleaner.
 286  *
 287  * Even more horribly, DEC doesn't allow system calls from kernel mode.
 288  * "Security" features letting the user do something the kernel can't
 289  * are a thinko. DEC palcode is strange. The PAL-code designers probably
 290  * got terminally tainted by VMS at some point.
 291  */
 292 asmlinkage long do_entSys(unsigned long a0, unsigned long a1, unsigned long a2,
     /* [previous][next][first][last][top][bottom][index][help] */
 293         unsigned long a3, unsigned long a4, unsigned long a5, struct pt_regs regs)
 294 {
 295         if (regs.r0 != 112)
 296           printk("<sc %ld(%lx,%lx,%lx)>", regs.r0, a0, a1, a2);
 297         return -1;
 298 }
 299 
 300 extern asmlinkage void entMM(void);
 301 extern asmlinkage void entIF(void);
 302 extern asmlinkage void entArith(void);
 303 extern asmlinkage void entUna(void);
 304 extern asmlinkage void entSys(void);
 305 
 306 void trap_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 307 {
 308         unsigned long gptr;
 309 
 310         /*
 311          * Tell PAL-code what global pointer we want in the kernel..
 312          */
 313         __asm__("br %0,___tmp\n"
 314                 "___tmp:\tldgp %0,0(%0)"
 315                 : "=r" (gptr));
 316         wrkgp(gptr);
 317 
 318         wrent(entArith, 1);
 319         wrent(entMM, 2);
 320         wrent(entIF, 3);
 321         wrent(entUna, 4);
 322         wrent(entSys, 5);
 323 }

/* [previous][next][first][last][top][bottom][index][help] */