~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/alpha/kernel/traps.c

Version: ~ [ linux-5.13-rc5 ] ~ [ linux-5.12.9 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.42 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.124 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.193 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.235 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.271 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.271 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * arch/alpha/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/config.h>
 12 #include <linux/mm.h>
 13 #include <linux/sched.h>
 14 #include <linux/tty.h>
 15 #include <linux/delay.h>
 16 #include <linux/smp_lock.h>
 17 #include <linux/module.h>
 18 
 19 #include <asm/gentrap.h>
 20 #include <asm/uaccess.h>
 21 #include <asm/unaligned.h>
 22 #include <asm/sysinfo.h>
 23 #include <asm/hwrpb.h>
 24 #include <asm/mmu_context.h>
 25 
 26 #include "proto.h"
 27 
 28 /* data/code implementing a work-around for some SRMs which
 29    mishandle opDEC faults
 30 */
 31 static int opDEC_testing = 0;
 32 static int opDEC_fix = 0;
 33 static int opDEC_checked = 0;
 34 static unsigned long opDEC_test_pc = 0;
 35 
 36 static void
 37 opDEC_check(void)
 38 {
 39         unsigned long test_pc;
 40 
 41         if (opDEC_checked) return;
 42 
 43         lock_kernel();
 44         opDEC_testing = 1;
 45 
 46         __asm__ __volatile__(
 47                 "       br      %0,1f\n"
 48                 "1:     addq    %0,8,%0\n"
 49                 "       stq     %0,%1\n"
 50                 "       cvttq/svm $f31,$f31\n"
 51                 : "=&r"(test_pc), "=m"(opDEC_test_pc)
 52                 : );
 53 
 54         opDEC_testing = 0;
 55         opDEC_checked = 1;
 56         unlock_kernel();
 57 }
 58 
 59 void
 60 dik_show_regs(struct pt_regs *regs, unsigned long *r9_15)
 61 {
 62         printk("pc = [<%016lx>]  ra = [<%016lx>]  ps = %04lx    %s\n",
 63                regs->pc, regs->r26, regs->ps, print_tainted());
 64         printk("v0 = %016lx  t0 = %016lx  t1 = %016lx\n",
 65                regs->r0, regs->r1, regs->r2);
 66         printk("t2 = %016lx  t3 = %016lx  t4 = %016lx\n",
 67                regs->r3, regs->r4, regs->r5);
 68         printk("t5 = %016lx  t6 = %016lx  t7 = %016lx\n",
 69                regs->r6, regs->r7, regs->r8);
 70 
 71         if (r9_15) {
 72                 printk("s0 = %016lx  s1 = %016lx  s2 = %016lx\n",
 73                        r9_15[9], r9_15[10], r9_15[11]);
 74                 printk("s3 = %016lx  s4 = %016lx  s5 = %016lx\n",
 75                        r9_15[12], r9_15[13], r9_15[14]);
 76                 printk("s6 = %016lx\n", r9_15[15]);
 77         }
 78 
 79         printk("a0 = %016lx  a1 = %016lx  a2 = %016lx\n",
 80                regs->r16, regs->r17, regs->r18);
 81         printk("a3 = %016lx  a4 = %016lx  a5 = %016lx\n",
 82                regs->r19, regs->r20, regs->r21);
 83         printk("t8 = %016lx  t9 = %016lx  t10= %016lx\n",
 84                regs->r22, regs->r23, regs->r24);
 85         printk("t11= %016lx  pv = %016lx  at = %016lx\n",
 86                regs->r25, regs->r27, regs->r28);
 87         printk("gp = %016lx  sp = %p\n", regs->gp, regs+1);
 88 #if 0
 89 __halt();
 90 #endif
 91 }
 92 
 93 #if 0
 94 static char * ireg_name[] = {"v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
 95                            "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6",
 96                            "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
 97                            "t10", "t11", "ra", "pv", "at", "gp", "sp", "zero"};
 98 #endif
 99 
100 static void
101 dik_show_code(unsigned int *pc)
102 {
103         long i;
104 
105         printk("Code:");
106         for (i = -6; i < 2; i++) {
107                 unsigned int insn;
108                 if (__get_user(insn, pc+i))
109                         break;
110                 printk("%c%08x%c", i ? ' ' : '<', insn, i ? ' ' : '>');
111         }
112         printk("\n");
113 }
114 
115 static void
116 dik_show_trace(unsigned long *sp)
117 {
118         long i = 0;
119         printk("Trace:");
120         while (0x1ff8 & (unsigned long) sp) {
121                 extern char _stext[], _etext[];
122                 unsigned long tmp = *sp;
123                 sp++;
124                 if (tmp < (unsigned long) &_stext)
125                         continue;
126                 if (tmp >= (unsigned long) &_etext)
127                         continue;
128                 printk("%lx%c", tmp, ' ');
129                 if (i > 40) {
130                         printk(" ...");
131                         break;
132                 }
133         }
134         printk("\n");
135 }
136 
137 void show_trace_task(struct task_struct * tsk)
138 {
139         struct thread_info *ti = tsk->thread_info;
140         unsigned long fp, sp = ti->pcb.ksp, base = (unsigned long) ti;
141  
142         if (sp > base && sp+6*8 < base + 16*1024) {
143                 fp = ((unsigned long*)sp)[6];
144                 if (fp > sp && fp < base + 16*1024)
145                         dik_show_trace((unsigned long *)fp);
146         }
147 }
148 
149 static int kstack_depth_to_print = 24;
150 
151 void show_stack(struct task_struct *task, unsigned long *sp)
152 {
153         unsigned long *stack;
154         int i;
155 
156         /*
157          * debugging aid: "show_stack(NULL);" prints the
158          * back trace for this cpu.
159          */
160         if(sp==NULL)
161                 sp=(unsigned long*)&sp;
162 
163         stack = sp;
164         for(i=0; i < kstack_depth_to_print; i++) {
165                 if (((long) stack & (THREAD_SIZE-1)) == 0)
166                         break;
167                 if (i && ((i % 4) == 0))
168                         printk("\n       ");
169                 printk("%016lx ", *stack++);
170         }
171         printk("\n");
172         dik_show_trace(sp);
173 }
174 
175 void dump_stack(void)
176 {
177         show_stack(NULL, NULL);
178 }
179 
180 EXPORT_SYMBOL(dump_stack);
181 
182 void
183 die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15)
184 {
185         if (regs->ps & 8)
186                 return;
187 #ifdef CONFIG_SMP
188         printk("CPU %d ", hard_smp_processor_id());
189 #endif
190         printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err);
191         dik_show_regs(regs, r9_15);
192         dik_show_trace((unsigned long *)(regs+1));
193         dik_show_code((unsigned int *)regs->pc);
194 
195         if (test_and_set_thread_flag (TIF_DIE_IF_KERNEL)) {
196                 printk("die_if_kernel recursion detected.\n");
197                 local_irq_enable();
198                 while (1);
199         }
200         do_exit(SIGSEGV);
201 }
202 
203 #ifndef CONFIG_MATHEMU
204 static long dummy_emul(void) { return 0; }
205 long (*alpha_fp_emul_imprecise)(struct pt_regs *regs, unsigned long writemask)
206   = (void *)dummy_emul;
207 long (*alpha_fp_emul) (unsigned long pc)
208   = (void *)dummy_emul;
209 #else
210 long alpha_fp_emul_imprecise(struct pt_regs *regs, unsigned long writemask);
211 long alpha_fp_emul (unsigned long pc);
212 #endif
213 
214 asmlinkage void
215 do_entArith(unsigned long summary, unsigned long write_mask,
216             struct pt_regs *regs)
217 {
218         long si_code = FPE_FLTINV;
219         siginfo_t info;
220 
221         if (summary & 1) {
222                 /* Software-completion summary bit is set, so try to
223                    emulate the instruction.  If the processor supports
224                    precise exceptions, we don't have to search.  */
225                 if (!amask(AMASK_PRECISE_TRAP))
226                         si_code = alpha_fp_emul(regs->pc - 4);
227                 else
228                         si_code = alpha_fp_emul_imprecise(regs, write_mask);
229                 if (si_code == 0)
230                         return;
231         }
232         die_if_kernel("Arithmetic fault", regs, 0, 0);
233 
234         info.si_signo = SIGFPE;
235         info.si_errno = 0;
236         info.si_code = si_code;
237         info.si_addr = (void *) regs->pc;
238         send_sig_info(SIGFPE, &info, current);
239 }
240 
241 asmlinkage void
242 do_entIF(unsigned long type, struct pt_regs *regs)
243 {
244         siginfo_t info;
245         int signo, code;
246 
247         if (!opDEC_testing || type != 4) {
248                 if (type == 1) {
249                         const unsigned int *data
250                           = (const unsigned int *) regs->pc;
251                         printk("Kernel bug at %s:%d\n",
252                                (const char *)(data[1] | (long)data[2] << 32), 
253                                data[0]);
254                 }
255                 die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"),
256                               regs, type, 0);
257         }
258 
259         switch (type) {
260               case 0: /* breakpoint */
261                 info.si_signo = SIGTRAP;
262                 info.si_errno = 0;
263                 info.si_code = TRAP_BRKPT;
264                 info.si_trapno = 0;
265                 info.si_addr = (void *) regs->pc;
266 
267                 if (ptrace_cancel_bpt(current)) {
268                         regs->pc -= 4;  /* make pc point to former bpt */
269                 }
270 
271                 send_sig_info(SIGTRAP, &info, current);
272                 return;
273 
274               case 1: /* bugcheck */
275                 info.si_signo = SIGTRAP;
276                 info.si_errno = 0;
277                 info.si_code = __SI_FAULT;
278                 info.si_addr = (void *) regs->pc;
279                 info.si_trapno = 0;
280                 send_sig_info(SIGTRAP, &info, current);
281                 return;
282                 
283               case 2: /* gentrap */
284                 info.si_addr = (void *) regs->pc;
285                 info.si_trapno = regs->r16;
286                 switch ((long) regs->r16) {
287                 case GEN_INTOVF:
288                         signo = SIGFPE;
289                         code = FPE_INTOVF;
290                         break;
291                 case GEN_INTDIV:
292                         signo = SIGFPE;
293                         code = FPE_INTDIV;
294                         break;
295                 case GEN_FLTOVF:
296                         signo = SIGFPE;
297                         code = FPE_FLTOVF;
298                         break;
299                 case GEN_FLTDIV:
300                         signo = SIGFPE;
301                         code = FPE_FLTDIV;
302                         break;
303                 case GEN_FLTUND:
304                         signo = SIGFPE;
305                         code = FPE_FLTUND;
306                         break;
307                 case GEN_FLTINV:
308                         signo = SIGFPE;
309                         code = FPE_FLTINV;
310                         break;
311                 case GEN_FLTINE:
312                         signo = SIGFPE;
313                         code = FPE_FLTRES;
314                         break;
315                 case GEN_ROPRAND:
316                         signo = SIGFPE;
317                         code = __SI_FAULT;
318                         break;
319 
320                 case GEN_DECOVF:
321                 case GEN_DECDIV:
322                 case GEN_DECINV:
323                 case GEN_ASSERTERR:
324                 case GEN_NULPTRERR:
325                 case GEN_STKOVF:
326                 case GEN_STRLENERR:
327                 case GEN_SUBSTRERR:
328                 case GEN_RANGERR:
329                 case GEN_SUBRNG:
330                 case GEN_SUBRNG1:
331                 case GEN_SUBRNG2:
332                 case GEN_SUBRNG3:
333                 case GEN_SUBRNG4:
334                 case GEN_SUBRNG5:
335                 case GEN_SUBRNG6:
336                 case GEN_SUBRNG7:
337                 default:
338                         signo = SIGTRAP;
339                         code = __SI_FAULT;
340                         break;
341                 }
342 
343                 info.si_signo = signo;
344                 info.si_errno = 0;
345                 info.si_code = code;
346                 info.si_addr = (void *) regs->pc;
347                 send_sig_info(signo, &info, current);
348                 return;
349 
350               case 4: /* opDEC */
351                 if (implver() == IMPLVER_EV4) {
352                         long si_code;
353 
354                         /* The some versions of SRM do not handle
355                            the opDEC properly - they return the PC of the
356                            opDEC fault, not the instruction after as the
357                            Alpha architecture requires.  Here we fix it up.
358                            We do this by intentionally causing an opDEC
359                            fault during the boot sequence and testing if
360                            we get the correct PC.  If not, we set a flag
361                            to correct it every time through.  */
362                         if (opDEC_testing) {
363                                 if (regs->pc == opDEC_test_pc) {
364                                         opDEC_fix = 4;
365                                         regs->pc += 4;
366                                         printk("opDEC fixup enabled.\n");
367                                 }
368                                 return;
369                         }
370                         regs->pc += opDEC_fix; 
371                         
372                         /* EV4 does not implement anything except normal
373                            rounding.  Everything else will come here as
374                            an illegal instruction.  Emulate them.  */
375                         si_code = alpha_fp_emul(regs->pc - 4);
376                         if (si_code == 0)
377                                 return;
378                         if (si_code > 0) {
379                                 info.si_signo = SIGFPE;
380                                 info.si_errno = 0;
381                                 info.si_code = si_code;
382                                 info.si_addr = (void *) regs->pc;
383                                 send_sig_info(SIGFPE, &info, current);
384                                 return;
385                         }
386                 }
387                 break;
388 
389               case 3: /* FEN fault */
390                 /* Irritating users can call PAL_clrfen to disable the
391                    FPU for the process.  The kernel will then trap in
392                    do_switch_stack and undo_switch_stack when we try
393                    to save and restore the FP registers.
394 
395                    Given that GCC by default generates code that uses the
396                    FP registers, PAL_clrfen is not useful except for DoS
397                    attacks.  So turn the bleeding FPU back on and be done
398                    with it.  */
399                 current_thread_info()->pcb.flags |= 1;
400                 __reload_thread(&current_thread_info()->pcb);
401                 return;
402 
403               case 5: /* illoc */
404               default: /* unexpected instruction-fault type */
405                       ;
406         }
407 
408         info.si_signo = SIGILL;
409         info.si_errno = 0;
410         info.si_code = ILL_ILLOPC;
411         info.si_addr = (void *) regs->pc;
412         send_sig_info(SIGILL, &info, current);
413 }
414 
415 /* There is an ifdef in the PALcode in MILO that enables a 
416    "kernel debugging entry point" as an unprivileged call_pal.
417 
418    We don't want to have anything to do with it, but unfortunately
419    several versions of MILO included in distributions have it enabled,
420    and if we don't put something on the entry point we'll oops.  */
421 
422 asmlinkage void
423 do_entDbg(struct pt_regs *regs)
424 {
425         siginfo_t info;
426 
427         die_if_kernel("Instruction fault", regs, 0, 0);
428 
429         info.si_signo = SIGILL;
430         info.si_errno = 0;
431         info.si_code = ILL_ILLOPC;
432         info.si_addr = (void *) regs->pc;
433         force_sig_info(SIGILL, &info, current);
434 }
435 
436 
437 /*
438  * entUna has a different register layout to be reasonably simple. It
439  * needs access to all the integer registers (the kernel doesn't use
440  * fp-regs), and it needs to have them in order for simpler access.
441  *
442  * Due to the non-standard register layout (and because we don't want
443  * to handle floating-point regs), user-mode unaligned accesses are
444  * handled separately by do_entUnaUser below.
445  *
446  * Oh, btw, we don't handle the "gp" register correctly, but if we fault
447  * on a gp-register unaligned load/store, something is _very_ wrong
448  * in the kernel anyway..
449  */
450 struct allregs {
451         unsigned long regs[32];
452         unsigned long ps, pc, gp, a0, a1, a2;
453 };
454 
455 struct unaligned_stat {
456         unsigned long count, va, pc;
457 } unaligned[2];
458 
459 
460 /* Macro for exception fixup code to access integer registers.  */
461 #define una_reg(r)  (regs.regs[(r) >= 16 && (r) <= 18 ? (r)+19 : (r)])
462 
463 
464 asmlinkage void
465 do_entUna(void * va, unsigned long opcode, unsigned long reg,
466           unsigned long a3, unsigned long a4, unsigned long a5,
467           struct allregs regs)
468 {
469         long error, tmp1, tmp2, tmp3, tmp4;
470         unsigned long pc = regs.pc - 4;
471         const struct exception_table_entry *fixup;
472 
473         unaligned[0].count++;
474         unaligned[0].va = (unsigned long) va;
475         unaligned[0].pc = pc;
476 
477         /* We don't want to use the generic get/put unaligned macros as
478            we want to trap exceptions.  Only if we actually get an
479            exception will we decide whether we should have caught it.  */
480 
481         switch (opcode) {
482         case 0x0c: /* ldwu */
483                 __asm__ __volatile__(
484                 "1:     ldq_u %1,0(%3)\n"
485                 "2:     ldq_u %2,1(%3)\n"
486                 "       extwl %1,%3,%1\n"
487                 "       extwh %2,%3,%2\n"
488                 "3:\n"
489                 ".section __ex_table,\"a\"\n"
490                 "       .long 1b - .\n"
491                 "       lda %1,3b-1b(%0)\n"
492                 "       .long 2b - .\n"
493                 "       lda %2,3b-2b(%0)\n"
494                 ".previous"
495                         : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
496                         : "r"(va), ""(0));
497                 if (error)
498                         goto got_exception;
499                 una_reg(reg) = tmp1|tmp2;
500                 return;
501 
502         case 0x28: /* ldl */
503                 __asm__ __volatile__(
504                 "1:     ldq_u %1,0(%3)\n"
505                 "2:     ldq_u %2,3(%3)\n"
506                 "       extll %1,%3,%1\n"
507                 "       extlh %2,%3,%2\n"
508                 "3:\n"
509                 ".section __ex_table,\"a\"\n"
510                 "       .long 1b - .\n"
511                 "       lda %1,3b-1b(%0)\n"
512                 "       .long 2b - .\n"
513                 "       lda %2,3b-2b(%0)\n"
514                 ".previous"
515                         : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
516                         : "r"(va), ""(0));
517                 if (error)
518                         goto got_exception;
519                 una_reg(reg) = (int)(tmp1|tmp2);
520                 return;
521 
522         case 0x29: /* ldq */
523                 __asm__ __volatile__(
524                 "1:     ldq_u %1,0(%3)\n"
525                 "2:     ldq_u %2,7(%3)\n"
526                 "       extql %1,%3,%1\n"
527                 "       extqh %2,%3,%2\n"
528                 "3:\n"
529                 ".section __ex_table,\"a\"\n"
530                 "       .long 1b - .\n"
531                 "       lda %1,3b-1b(%0)\n"
532                 "       .long 2b - .\n"
533                 "       lda %2,3b-2b(%0)\n"
534                 ".previous"
535                         : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
536                         : "r"(va), ""(0));
537                 if (error)
538                         goto got_exception;
539                 una_reg(reg) = tmp1|tmp2;
540                 return;
541 
542         /* Note that the store sequences do not indicate that they change
543            memory because it _should_ be affecting nothing in this context.
544            (Otherwise we have other, much larger, problems.)  */
545         case 0x0d: /* stw */
546                 __asm__ __volatile__(
547                 "1:     ldq_u %2,1(%5)\n"
548                 "2:     ldq_u %1,0(%5)\n"
549                 "       inswh %6,%5,%4\n"
550                 "       inswl %6,%5,%3\n"
551                 "       mskwh %2,%5,%2\n"
552                 "       mskwl %1,%5,%1\n"
553                 "       or %2,%4,%2\n"
554                 "       or %1,%3,%1\n"
555                 "3:     stq_u %2,1(%5)\n"
556                 "4:     stq_u %1,0(%5)\n"
557                 "5:\n"
558                 ".section __ex_table,\"a\"\n"
559                 "       .long 1b - .\n"
560                 "       lda %2,5b-1b(%0)\n"
561                 "       .long 2b - .\n"
562                 "       lda %1,5b-2b(%0)\n"
563                 "       .long 3b - .\n"
564                 "       lda $31,5b-3b(%0)\n"
565                 "       .long 4b - .\n"
566                 "       lda $31,5b-4b(%0)\n"
567                 ".previous"
568                         : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
569                           "=&r"(tmp3), "=&r"(tmp4)
570                         : "r"(va), "r"(una_reg(reg)), ""(0));
571                 if (error)
572                         goto got_exception;
573                 return;
574 
575         case 0x2c: /* stl */
576                 __asm__ __volatile__(
577                 "1:     ldq_u %2,3(%5)\n"
578                 "2:     ldq_u %1,0(%5)\n"
579                 "       inslh %6,%5,%4\n"
580                 "       insll %6,%5,%3\n"
581                 "       msklh %2,%5,%2\n"
582                 "       mskll %1,%5,%1\n"
583                 "       or %2,%4,%2\n"
584                 "       or %1,%3,%1\n"
585                 "3:     stq_u %2,3(%5)\n"
586                 "4:     stq_u %1,0(%5)\n"
587                 "5:\n"
588                 ".section __ex_table,\"a\"\n"
589                 "       .long 1b - .\n"
590                 "       lda %2,5b-1b(%0)\n"
591                 "       .long 2b - .\n"
592                 "       lda %1,5b-2b(%0)\n"
593                 "       .long 3b - .\n"
594                 "       lda $31,5b-3b(%0)\n"
595                 "       .long 4b - .\n"
596                 "       lda $31,5b-4b(%0)\n"
597                 ".previous"
598                         : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
599                           "=&r"(tmp3), "=&r"(tmp4)
600                         : "r"(va), "r"(una_reg(reg)), ""(0));
601                 if (error)
602                         goto got_exception;
603                 return;
604 
605         case 0x2d: /* stq */
606                 __asm__ __volatile__(
607                 "1:     ldq_u %2,7(%5)\n"
608                 "2:     ldq_u %1,0(%5)\n"
609                 "       insqh %6,%5,%4\n"
610                 "       insql %6,%5,%3\n"
611                 "       mskqh %2,%5,%2\n"
612                 "       mskql %1,%5,%1\n"
613                 "       or %2,%4,%2\n"
614                 "       or %1,%3,%1\n"
615                 "3:     stq_u %2,7(%5)\n"
616                 "4:     stq_u %1,0(%5)\n"
617                 "5:\n"
618                 ".section __ex_table,\"a\"\n\t"
619                 "       .long 1b - .\n"
620                 "       lda %2,5b-1b(%0)\n"
621                 "       .long 2b - .\n"
622                 "       lda %1,5b-2b(%0)\n"
623                 "       .long 3b - .\n"
624                 "       lda $31,5b-3b(%0)\n"
625                 "       .long 4b - .\n"
626                 "       lda $31,5b-4b(%0)\n"
627                 ".previous"
628                         : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
629                           "=&r"(tmp3), "=&r"(tmp4)
630                         : "r"(va), "r"(una_reg(reg)), ""(0));
631                 if (error)
632                         goto got_exception;
633                 return;
634         }
635 
636         lock_kernel();
637         printk("Bad unaligned kernel access at %016lx: %p %lx %ld\n",
638                 pc, va, opcode, reg);
639         do_exit(SIGSEGV);
640 
641 got_exception:
642         /* Ok, we caught the exception, but we don't want it.  Is there
643            someone to pass it along to?  */
644         if ((fixup = search_exception_tables(pc)) != 0) {
645                 unsigned long newpc;
646                 newpc = fixup_exception(una_reg, fixup, pc);
647 
648                 printk("Forwarding unaligned exception at %lx (%lx)\n",
649                        pc, newpc);
650 
651                 (&regs)->pc = newpc;
652                 return;
653         }
654 
655         /*
656          * Yikes!  No one to forward the exception to.
657          * Since the registers are in a weird format, dump them ourselves.
658          */
659         lock_kernel();
660 
661         printk("%s(%d): unhandled unaligned exception\n",
662                current->comm, current->pid);
663 
664         printk("pc = [<%016lx>]  ra = [<%016lx>]  ps = %04lx\n",
665                pc, una_reg(26), regs.ps);
666         printk("r0 = %016lx  r1 = %016lx  r2 = %016lx\n",
667                una_reg(0), una_reg(1), una_reg(2));
668         printk("r3 = %016lx  r4 = %016lx  r5 = %016lx\n",
669                una_reg(3), una_reg(4), una_reg(5));
670         printk("r6 = %016lx  r7 = %016lx  r8 = %016lx\n",
671                una_reg(6), una_reg(7), una_reg(8));
672         printk("r9 = %016lx  r10= %016lx  r11= %016lx\n",
673                una_reg(9), una_reg(10), una_reg(11));
674         printk("r12= %016lx  r13= %016lx  r14= %016lx\n",
675                una_reg(12), una_reg(13), una_reg(14));
676         printk("r15= %016lx\n", una_reg(15));
677         printk("r16= %016lx  r17= %016lx  r18= %016lx\n",
678                una_reg(16), una_reg(17), una_reg(18));
679         printk("r19= %016lx  r20= %016lx  r21= %016lx\n",
680                una_reg(19), una_reg(20), una_reg(21));
681         printk("r22= %016lx  r23= %016lx  r24= %016lx\n",
682                una_reg(22), una_reg(23), una_reg(24));
683         printk("r25= %016lx  r27= %016lx  r28= %016lx\n",
684                una_reg(25), una_reg(27), una_reg(28));
685         printk("gp = %016lx  sp = %p\n", regs.gp, &regs+1);
686 
687         dik_show_code((unsigned int *)pc);
688         dik_show_trace((unsigned long *)(&regs+1));
689 
690         if (test_and_set_thread_flag (TIF_DIE_IF_KERNEL)) {
691                 printk("die_if_kernel recursion detected.\n");
692                 local_irq_enable();
693                 while (1);
694         }
695         do_exit(SIGSEGV);
696 }
697 
698 /*
699  * Convert an s-floating point value in memory format to the
700  * corresponding value in register format.  The exponent
701  * needs to be remapped to preserve non-finite values
702  * (infinities, not-a-numbers, denormals).
703  */
704 static inline unsigned long
705 s_mem_to_reg (unsigned long s_mem)
706 {
707         unsigned long frac    = (s_mem >>  0) & 0x7fffff;
708         unsigned long sign    = (s_mem >> 31) & 0x1;
709         unsigned long exp_msb = (s_mem >> 30) & 0x1;
710         unsigned long exp_low = (s_mem >> 23) & 0x7f;
711         unsigned long exp;
712 
713         exp = (exp_msb << 10) | exp_low;        /* common case */
714         if (exp_msb) {
715                 if (exp_low == 0x7f) {
716                         exp = 0x7ff;
717                 }
718         } else {
719                 if (exp_low == 0x00) {
720                         exp = 0x000;
721                 } else {
722                         exp |= (0x7 << 7);
723                 }
724         }
725         return (sign << 63) | (exp << 52) | (frac << 29);
726 }
727 
728 /*
729  * Convert an s-floating point value in register format to the
730  * corresponding value in memory format.
731  */
732 static inline unsigned long
733 s_reg_to_mem (unsigned long s_reg)
734 {
735         return ((s_reg >> 62) << 30) | ((s_reg << 5) >> 34);
736 }
737 
738 /*
739  * Handle user-level unaligned fault.  Handling user-level unaligned
740  * faults is *extremely* slow and produces nasty messages.  A user
741  * program *should* fix unaligned faults ASAP.
742  *
743  * Notice that we have (almost) the regular kernel stack layout here,
744  * so finding the appropriate registers is a little more difficult
745  * than in the kernel case.
746  *
747  * Finally, we handle regular integer load/stores only.  In
748  * particular, load-linked/store-conditionally and floating point
749  * load/stores are not supported.  The former make no sense with
750  * unaligned faults (they are guaranteed to fail) and I don't think
751  * the latter will occur in any decent program.
752  *
753  * Sigh. We *do* have to handle some FP operations, because GCC will
754  * uses them as temporary storage for integer memory to memory copies.
755  * However, we need to deal with stt/ldt and sts/lds only.
756  */
757 
758 #define OP_INT_MASK     ( 1L << 0x28 | 1L << 0x2c   /* ldl stl */       \
759                         | 1L << 0x29 | 1L << 0x2d   /* ldq stq */       \
760                         | 1L << 0x0c | 1L << 0x0d   /* ldwu stw */      \
761                         | 1L << 0x0a | 1L << 0x0e ) /* ldbu stb */
762 
763 #define OP_WRITE_MASK   ( 1L << 0x26 | 1L << 0x27   /* sts stt */       \
764                         | 1L << 0x2c | 1L << 0x2d   /* stl stq */       \
765                         | 1L << 0x0d | 1L << 0x0e ) /* stw stb */
766 
767 #define R(x)    ((size_t) &((struct pt_regs *)0)->x)
768 
769 static int unauser_reg_offsets[32] = {
770         R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), R(r8),
771         /* r9 ... r15 are stored in front of regs.  */
772         -56, -48, -40, -32, -24, -16, -8,
773         R(r16), R(r17), R(r18),
774         R(r19), R(r20), R(r21), R(r22), R(r23), R(r24), R(r25), R(r26),
775         R(r27), R(r28), R(gp),
776         0, 0
777 };
778 
779 #undef R
780 
781 asmlinkage void
782 do_entUnaUser(void * va, unsigned long opcode,
783               unsigned long reg, struct pt_regs *regs)
784 {
785         static int cnt = 0;
786         static long last_time = 0;
787 
788         unsigned long tmp1, tmp2, tmp3, tmp4;
789         unsigned long fake_reg, *reg_addr = &fake_reg;
790         siginfo_t info;
791         long error;
792 
793         /* Check the UAC bits to decide what the user wants us to do
794            with the unaliged access.  */
795 
796         if (!test_thread_flag (TIF_UAC_NOPRINT)) {
797                 if (cnt >= 5 && jiffies - last_time > 5*HZ) {
798                         cnt = 0;
799                 }
800                 if (++cnt < 5) {
801                         printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
802                                current->comm, current->pid,
803                                regs->pc - 4, va, opcode, reg);
804                 }
805                 last_time = jiffies;
806         }
807         if (test_thread_flag (TIF_UAC_SIGBUS))
808                 goto give_sigbus;
809         /* Not sure why you'd want to use this, but... */
810         if (test_thread_flag (TIF_UAC_NOFIX))
811                 return;
812 
813         /* Don't bother reading ds in the access check since we already
814            know that this came from the user.  Also rely on the fact that
815            the page at TASK_SIZE is unmapped and so can't be touched anyway. */
816         if (!__access_ok((unsigned long)va, 0, USER_DS))
817                 goto give_sigsegv;
818 
819         ++unaligned[1].count;
820         unaligned[1].va = (unsigned long)va;
821         unaligned[1].pc = regs->pc - 4;
822 
823         if ((1L << opcode) & OP_INT_MASK) {
824                 /* it's an integer load/store */
825                 if (reg < 30) {
826                         reg_addr = (unsigned long *)
827                           ((char *)regs + unauser_reg_offsets[reg]);
828                 } else if (reg == 30) {
829                         /* usp in PAL regs */
830                         fake_reg = rdusp();
831                 } else {
832                         /* zero "register" */
833                         fake_reg = 0;
834                 }
835         }
836 
837         /* We don't want to use the generic get/put unaligned macros as
838            we want to trap exceptions.  Only if we actually get an
839            exception will we decide whether we should have caught it.  */
840 
841         switch (opcode) {
842         case 0x0c: /* ldwu */
843                 __asm__ __volatile__(
844                 "1:     ldq_u %1,0(%3)\n"
845                 "2:     ldq_u %2,1(%3)\n"
846                 "       extwl %1,%3,%1\n"
847                 "       extwh %2,%3,%2\n"
848                 "3:\n"
849                 ".section __ex_table,\"a\"\n"
850                 "       .long 1b - .\n"
851                 "       lda %1,3b-1b(%0)\n"
852                 "       .long 2b - .\n"
853                 "       lda %2,3b-2b(%0)\n"
854                 ".previous"
855                         : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
856                         : "r"(va), ""(0));
857                 if (error)
858                         goto give_sigsegv;
859                 *reg_addr = tmp1|tmp2;
860                 break;
861 
862         case 0x22: /* lds */
863                 __asm__ __volatile__(
864                 "1:     ldq_u %1,0(%3)\n"
865                 "2:     ldq_u %2,3(%3)\n"
866                 "       extll %1,%3,%1\n"
867                 "       extlh %2,%3,%2\n"
868                 "3:\n"
869                 ".section __ex_table,\"a\"\n"
870                 "       .long 1b - .\n"
871                 "       lda %1,3b-1b(%0)\n"
872                 "       .long 2b - .\n"
873                 "       lda %2,3b-2b(%0)\n"
874                 ".previous"
875                         : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
876                         : "r"(va), ""(0));
877                 if (error)
878                         goto give_sigsegv;
879                 alpha_write_fp_reg(reg, s_mem_to_reg((int)(tmp1|tmp2)));
880                 return;
881 
882         case 0x23: /* ldt */
883                 __asm__ __volatile__(
884                 "1:     ldq_u %1,0(%3)\n"
885                 "2:     ldq_u %2,7(%3)\n"
886                 "       extql %1,%3,%1\n"
887                 "       extqh %2,%3,%2\n"
888                 "3:\n"
889                 ".section __ex_table,\"a\"\n"
890                 "       .long 1b - .\n"
891                 "       lda %1,3b-1b(%0)\n"
892                 "       .long 2b - .\n"
893                 "       lda %2,3b-2b(%0)\n"
894                 ".previous"
895                         : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
896                         : "r"(va), ""(0));
897                 if (error)
898                         goto give_sigsegv;
899                 alpha_write_fp_reg(reg, tmp1|tmp2);
900                 return;
901 
902         case 0x28: /* ldl */
903                 __asm__ __volatile__(
904                 "1:     ldq_u %1,0(%3)\n"
905                 "2:     ldq_u %2,3(%3)\n"
906                 "       extll %1,%3,%1\n"
907                 "       extlh %2,%3,%2\n"
908                 "3:\n"
909                 ".section __ex_table,\"a\"\n"
910                 "       .long 1b - .\n"
911                 "       lda %1,3b-1b(%0)\n"
912                 "       .long 2b - .\n"
913                 "       lda %2,3b-2b(%0)\n"
914                 ".previous"
915                         : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
916                         : "r"(va), ""(0));
917                 if (error)
918                         goto give_sigsegv;
919                 *reg_addr = (int)(tmp1|tmp2);
920                 break;
921 
922         case 0x29: /* ldq */
923                 __asm__ __volatile__(
924                 "1:     ldq_u %1,0(%3)\n"
925                 "2:     ldq_u %2,7(%3)\n"
926                 "       extql %1,%3,%1\n"
927                 "       extqh %2,%3,%2\n"
928                 "3:\n"
929                 ".section __ex_table,\"a\"\n"
930                 "       .long 1b - .\n"
931                 "       lda %1,3b-1b(%0)\n"
932                 "       .long 2b - .\n"
933                 "       lda %2,3b-2b(%0)\n"
934                 ".previous"
935                         : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
936                         : "r"(va), ""(0));
937                 if (error)
938                         goto give_sigsegv;
939                 *reg_addr = tmp1|tmp2;
940                 break;
941 
942         /* Note that the store sequences do not indicate that they change
943            memory because it _should_ be affecting nothing in this context.
944            (Otherwise we have other, much larger, problems.)  */
945         case 0x0d: /* stw */
946                 __asm__ __volatile__(
947                 "1:     ldq_u %2,1(%5)\n"
948                 "2:     ldq_u %1,0(%5)\n"
949                 "       inswh %6,%5,%4\n"
950                 "       inswl %6,%5,%3\n"
951                 "       mskwh %2,%5,%2\n"
952                 "       mskwl %1,%5,%1\n"
953                 "       or %2,%4,%2\n"
954                 "       or %1,%3,%1\n"
955                 "3:     stq_u %2,1(%5)\n"
956                 "4:     stq_u %1,0(%5)\n"
957                 "5:\n"
958                 ".section __ex_table,\"a\"\n"
959                 "       .long 1b - .\n"
960                 "       lda %2,5b-1b(%0)\n"
961                 "       .long 2b - .\n"
962                 "       lda %1,5b-2b(%0)\n"
963                 "       .long 3b - .\n"
964                 "       lda $31,5b-3b(%0)\n"
965                 "       .long 4b - .\n"
966                 "       lda $31,5b-4b(%0)\n"
967                 ".previous"
968                         : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
969                           "=&r"(tmp3), "=&r"(tmp4)
970                         : "r"(va), "r"(*reg_addr), ""(0));
971                 if (error)
972                         goto give_sigsegv;
973                 return;
974 
975         case 0x26: /* sts */
976                 fake_reg = s_reg_to_mem(alpha_read_fp_reg(reg));
977                 /* FALLTHRU */
978 
979         case 0x2c: /* stl */
980                 __asm__ __volatile__(
981                 "1:     ldq_u %2,3(%5)\n"
982                 "2:     ldq_u %1,0(%5)\n"
983                 "       inslh %6,%5,%4\n"
984                 "       insll %6,%5,%3\n"
985                 "       msklh %2,%5,%2\n"
986                 "       mskll %1,%5,%1\n"
987                 "       or %2,%4,%2\n"
988                 "       or %1,%3,%1\n"
989                 "3:     stq_u %2,3(%5)\n"
990                 "4:     stq_u %1,0(%5)\n"
991                 "5:\n"
992                 ".section __ex_table,\"a\"\n"
993                 "       .long 1b - .\n"
994                 "       lda %2,5b-1b(%0)\n"
995                 "       .long 2b - .\n"
996                 "       lda %1,5b-2b(%0)\n"
997                 "       .long 3b - .\n"
998                 "       lda $31,5b-3b(%0)\n"
999                 "       .long 4b - .\n"
1000                 "       lda $31,5b-4b(%0)\n"
1001                 ".previous"
1002                         : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
1003                           "=&r"(tmp3), "=&r"(tmp4)
1004                         : "r"(va), "r"(*reg_addr), ""(0));
1005                 if (error)
1006                         goto give_sigsegv;
1007                 return;
1008 
1009         case 0x27: /* stt */
1010                 fake_reg = alpha_read_fp_reg(reg);
1011                 /* FALLTHRU */
1012 
1013         case 0x2d: /* stq */
1014                 __asm__ __volatile__(
1015                 "1:     ldq_u %2,7(%5)\n"
1016                 "2:     ldq_u %1,0(%5)\n"
1017                 "       insqh %6,%5,%4\n"
1018                 "       insql %6,%5,%3\n"
1019                 "       mskqh %2,%5,%2\n"
1020                 "       mskql %1,%5,%1\n"
1021                 "       or %2,%4,%2\n"
1022                 "       or %1,%3,%1\n"
1023                 "3:     stq_u %2,7(%5)\n"
1024                 "4:     stq_u %1,0(%5)\n"
1025                 "5:\n"
1026                 ".section __ex_table,\"a\"\n\t"
1027                 "       .long 1b - .\n"
1028                 "       lda %2,5b-1b(%0)\n"
1029                 "       .long 2b - .\n"
1030                 "       lda %1,5b-2b(%0)\n"
1031                 "       .long 3b - .\n"
1032                 "       lda $31,5b-3b(%0)\n"
1033                 "       .long 4b - .\n"
1034                 "       lda $31,5b-4b(%0)\n"
1035                 ".previous"
1036                         : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
1037                           "=&r"(tmp3), "=&r"(tmp4)
1038                         : "r"(va), "r"(*reg_addr), ""(0));
1039                 if (error)
1040                         goto give_sigsegv;
1041                 return;
1042 
1043         default:
1044                 /* What instruction were you trying to use, exactly?  */
1045                 goto give_sigbus;
1046         }
1047 
1048         /* Only integer loads should get here; everyone else returns early. */
1049         if (reg == 30)
1050                 wrusp(fake_reg);
1051         return;
1052 
1053 give_sigsegv:
1054         regs->pc -= 4;  /* make pc point to faulting insn */
1055         info.si_signo = SIGSEGV;
1056         info.si_errno = 0;
1057 
1058         /* We need to replicate some of the logic in mm/fault.c,
1059            since we don't have access to the fault code in the
1060            exception handling return path.  */
1061         if (!__access_ok((unsigned long)va, 0, USER_DS))
1062                 info.si_code = SEGV_ACCERR;
1063         else {
1064                 struct mm_struct *mm = current->mm;
1065                 down_read(&mm->mmap_sem);
1066                 if (find_vma(mm, (unsigned long)va))
1067                         info.si_code = SEGV_ACCERR;
1068                 else
1069                         info.si_code = SEGV_MAPERR;
1070                 up_read(&mm->mmap_sem);
1071         }
1072         info.si_addr = va;
1073         send_sig_info(SIGSEGV, &info, current);
1074         return;
1075 
1076 give_sigbus:
1077         regs->pc -= 4;
1078         info.si_signo = SIGBUS;
1079         info.si_errno = 0;
1080         info.si_code = BUS_ADRALN;
1081         info.si_addr = va;
1082         send_sig_info(SIGBUS, &info, current);
1083         return;
1084 }
1085 
1086 void
1087 trap_init(void)
1088 {
1089         /* Tell PAL-code what global pointer we want in the kernel.  */
1090         register unsigned long gptr __asm__("$29");
1091         wrkgp(gptr);
1092 
1093         wrent(entArith, 1);
1094         wrent(entMM, 2);
1095         wrent(entIF, 3);
1096         wrent(entUna, 4);
1097         wrent(entSys, 5);
1098         wrent(entDbg, 6);
1099 
1100         /* Hack for Multia (UDB) and JENSEN: some of their SRMs have
1101            a bug in the handling of the opDEC fault.  Fix it up if so.  */
1102         if (implver() == IMPLVER_EV4)
1103                 opDEC_check();
1104 }
1105 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp