1
2
3
4
5
6
7
8
9
10
11#include <linux/jiffies.h>
12#include <linux/mm.h>
13#include <linux/sched/signal.h>
14#include <linux/sched/debug.h>
15#include <linux/tty.h>
16#include <linux/delay.h>
17#include <linux/extable.h>
18#include <linux/kallsyms.h>
19#include <linux/ratelimit.h>
20
21#include <asm/gentrap.h>
22#include <linux/uaccess.h>
23#include <asm/unaligned.h>
24#include <asm/sysinfo.h>
25#include <asm/hwrpb.h>
26#include <asm/mmu_context.h>
27#include <asm/special_insns.h>
28
29#include "proto.h"
30
31
32
33static int opDEC_fix;
34
35static void
36opDEC_check(void)
37{
38 __asm__ __volatile__ (
39
40 " br $16, 1f\n"
41
42
43 " ldq $16, 8($sp)\n"
44 " addq $16, 4, $16\n"
45 " stq $16, 8($sp)\n"
46 " call_pal %[rti]\n"
47
48 "1: lda $17, 3\n"
49 " call_pal %[wrent]\n"
50
51
52
53 " lda %[fix], 0\n"
54 " cvttq/svm $f31,$f31\n"
55 " lda %[fix], 4"
56 : [fix] "=r" (opDEC_fix)
57 : [rti] "n" (PAL_rti), [wrent] "n" (PAL_wrent)
58 : "$0", "$1", "$16", "$17", "$22", "$23", "$24", "$25");
59
60 if (opDEC_fix)
61 printk("opDEC fixup enabled.\n");
62}
63
64void
65dik_show_regs(struct pt_regs *regs, unsigned long *r9_15)
66{
67 printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx %s\n",
68 regs->pc, regs->r26, regs->ps, print_tainted());
69 printk("pc is at %pSR\n", (void *)regs->pc);
70 printk("ra is at %pSR\n", (void *)regs->r26);
71 printk("v0 = %016lx t0 = %016lx t1 = %016lx\n",
72 regs->r0, regs->r1, regs->r2);
73 printk("t2 = %016lx t3 = %016lx t4 = %016lx\n",
74 regs->r3, regs->r4, regs->r5);
75 printk("t5 = %016lx t6 = %016lx t7 = %016lx\n",
76 regs->r6, regs->r7, regs->r8);
77
78 if (r9_15) {
79 printk("s0 = %016lx s1 = %016lx s2 = %016lx\n",
80 r9_15[9], r9_15[10], r9_15[11]);
81 printk("s3 = %016lx s4 = %016lx s5 = %016lx\n",
82 r9_15[12], r9_15[13], r9_15[14]);
83 printk("s6 = %016lx\n", r9_15[15]);
84 }
85
86 printk("a0 = %016lx a1 = %016lx a2 = %016lx\n",
87 regs->r16, regs->r17, regs->r18);
88 printk("a3 = %016lx a4 = %016lx a5 = %016lx\n",
89 regs->r19, regs->r20, regs->r21);
90 printk("t8 = %016lx t9 = %016lx t10= %016lx\n",
91 regs->r22, regs->r23, regs->r24);
92 printk("t11= %016lx pv = %016lx at = %016lx\n",
93 regs->r25, regs->r27, regs->r28);
94 printk("gp = %016lx sp = %p\n", regs->gp, regs+1);
95#if 0
96__halt();
97#endif
98}
99
100#if 0
101static char * ireg_name[] = {"v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
102 "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6",
103 "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
104 "t10", "t11", "ra", "pv", "at", "gp", "sp", "zero"};
105#endif
106
107static void
108dik_show_code(unsigned int *pc)
109{
110 long i;
111
112 printk("Code:");
113 for (i = -6; i < 2; i++) {
114 unsigned int insn;
115 if (__get_user(insn, (unsigned int __user *)pc + i))
116 break;
117 printk("%c%08x%c", i ? ' ' : '<', insn, i ? ' ' : '>');
118 }
119 printk("\n");
120}
121
122static void
123dik_show_trace(unsigned long *sp)
124{
125 long i = 0;
126 printk("Trace:\n");
127 while (0x1ff8 & (unsigned long) sp) {
128 extern char _stext[], _etext[];
129 unsigned long tmp = *sp;
130 sp++;
131 if (tmp < (unsigned long) &_stext)
132 continue;
133 if (tmp >= (unsigned long) &_etext)
134 continue;
135 printk("[<%lx>] %pSR\n", tmp, (void *)tmp);
136 if (i > 40) {
137 printk(" ...");
138 break;
139 }
140 }
141 printk("\n");
142}
143
144static int kstack_depth_to_print = 24;
145
146void show_stack(struct task_struct *task, unsigned long *sp)
147{
148 unsigned long *stack;
149 int i;
150
151
152
153
154
155 if(sp==NULL)
156 sp=(unsigned long*)&sp;
157
158 stack = sp;
159 for(i=0; i < kstack_depth_to_print; i++) {
160 if (((long) stack & (THREAD_SIZE-1)) == 0)
161 break;
162 if (i && ((i % 4) == 0))
163 printk("\n ");
164 printk("%016lx ", *stack++);
165 }
166 printk("\n");
167 dik_show_trace(sp);
168}
169
170void
171die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15)
172{
173 if (regs->ps & 8)
174 return;
175#ifdef CONFIG_SMP
176 printk("CPU %d ", hard_smp_processor_id());
177#endif
178 printk("%s(%d): %s %ld\n", current->comm, task_pid_nr(current), str, err);
179 dik_show_regs(regs, r9_15);
180 add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
181 dik_show_trace((unsigned long *)(regs+1));
182 dik_show_code((unsigned int *)regs->pc);
183
184 if (test_and_set_thread_flag (TIF_DIE_IF_KERNEL)) {
185 printk("die_if_kernel recursion detected.\n");
186 local_irq_enable();
187 while (1);
188 }
189 do_exit(SIGSEGV);
190}
191
192#ifndef CONFIG_MATHEMU
193static long dummy_emul(void) { return 0; }
194long (*alpha_fp_emul_imprecise)(struct pt_regs *regs, unsigned long writemask)
195 = (void *)dummy_emul;
196long (*alpha_fp_emul) (unsigned long pc)
197 = (void *)dummy_emul;
198#else
199long alpha_fp_emul_imprecise(struct pt_regs *regs, unsigned long writemask);
200long alpha_fp_emul (unsigned long pc);
201#endif
202
203asmlinkage void
204do_entArith(unsigned long summary, unsigned long write_mask,
205 struct pt_regs *regs)
206{
207 long si_code = FPE_FLTINV;
208 siginfo_t info;
209
210 if (summary & 1) {
211
212
213
214 if (!amask(AMASK_PRECISE_TRAP))
215 si_code = alpha_fp_emul(regs->pc - 4);
216 else
217 si_code = alpha_fp_emul_imprecise(regs, write_mask);
218 if (si_code == 0)
219 return;
220 }
221 die_if_kernel("Arithmetic fault", regs, 0, NULL);
222
223 info.si_signo = SIGFPE;
224 info.si_errno = 0;
225 info.si_code = si_code;
226 info.si_addr = (void __user *) regs->pc;
227 send_sig_info(SIGFPE, &info, current);
228}
229
230asmlinkage void
231do_entIF(unsigned long type, struct pt_regs *regs)
232{
233 siginfo_t info;
234 int signo, code;
235
236 if ((regs->ps & ~IPL_MAX) == 0) {
237 if (type == 1) {
238 const unsigned int *data
239 = (const unsigned int *) regs->pc;
240 printk("Kernel bug at %s:%d\n",
241 (const char *)(data[1] | (long)data[2] << 32),
242 data[0]);
243 }
244#ifdef CONFIG_ALPHA_WTINT
245 if (type == 4) {
246
247
248
249 unsigned int *pinsn
250 = (unsigned int *) regs->pc - 1;
251 if (*pinsn == PAL_wtint) {
252 *pinsn = 0x47e01400;
253 imb();
254 regs->r0 = 0;
255 return;
256 }
257 }
258#endif
259 die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"),
260 regs, type, NULL);
261 }
262
263 switch (type) {
264 case 0:
265 info.si_signo = SIGTRAP;
266 info.si_errno = 0;
267 info.si_code = TRAP_BRKPT;
268 info.si_trapno = 0;
269 info.si_addr = (void __user *) regs->pc;
270
271 if (ptrace_cancel_bpt(current)) {
272 regs->pc -= 4;
273 }
274
275 send_sig_info(SIGTRAP, &info, current);
276 return;
277
278 case 1:
279 info.si_signo = SIGTRAP;
280 info.si_errno = 0;
281 info.si_code = __SI_FAULT;
282 info.si_addr = (void __user *) regs->pc;
283 info.si_trapno = 0;
284 send_sig_info(SIGTRAP, &info, current);
285 return;
286
287 case 2:
288 info.si_addr = (void __user *) regs->pc;
289 info.si_trapno = regs->r16;
290 switch ((long) regs->r16) {
291 case GEN_INTOVF:
292 signo = SIGFPE;
293 code = FPE_INTOVF;
294 break;
295 case GEN_INTDIV:
296 signo = SIGFPE;
297 code = FPE_INTDIV;
298 break;
299 case GEN_FLTOVF:
300 signo = SIGFPE;
301 code = FPE_FLTOVF;
302 break;
303 case GEN_FLTDIV:
304 signo = SIGFPE;
305 code = FPE_FLTDIV;
306 break;
307 case GEN_FLTUND:
308 signo = SIGFPE;
309 code = FPE_FLTUND;
310 break;
311 case GEN_FLTINV:
312 signo = SIGFPE;
313 code = FPE_FLTINV;
314 break;
315 case GEN_FLTINE:
316 signo = SIGFPE;
317 code = FPE_FLTRES;
318 break;
319 case GEN_ROPRAND:
320 signo = SIGFPE;
321 code = __SI_FAULT;
322 break;
323
324 case GEN_DECOVF:
325 case GEN_DECDIV:
326 case GEN_DECINV:
327 case GEN_ASSERTERR:
328 case GEN_NULPTRERR:
329 case GEN_STKOVF:
330 case GEN_STRLENERR:
331 case GEN_SUBSTRERR:
332 case GEN_RANGERR:
333 case GEN_SUBRNG:
334 case GEN_SUBRNG1:
335 case GEN_SUBRNG2:
336 case GEN_SUBRNG3:
337 case GEN_SUBRNG4:
338 case GEN_SUBRNG5:
339 case GEN_SUBRNG6:
340 case GEN_SUBRNG7:
341 default:
342 signo = SIGTRAP;
343 code = __SI_FAULT;
344 break;
345 }
346
347 info.si_signo = signo;
348 info.si_errno = 0;
349 info.si_code = code;
350 info.si_addr = (void __user *) regs->pc;
351 send_sig_info(signo, &info, current);
352 return;
353
354 case 4:
355 if (implver() == IMPLVER_EV4) {
356 long si_code;
357
358
359
360
361
362
363
364
365
366 regs->pc += opDEC_fix;
367
368
369
370
371 si_code = alpha_fp_emul(regs->pc - 4);
372 if (si_code == 0)
373 return;
374 if (si_code > 0) {
375 info.si_signo = SIGFPE;
376 info.si_errno = 0;
377 info.si_code = si_code;
378 info.si_addr = (void __user *) regs->pc;
379 send_sig_info(SIGFPE, &info, current);
380 return;
381 }
382 }
383 break;
384
385 case 3:
386
387
388
389
390
391
392
393
394
395 current_thread_info()->pcb.flags |= 1;
396 __reload_thread(¤t_thread_info()->pcb);
397 return;
398
399 case 5:
400 default:
401 ;
402 }
403
404 info.si_signo = SIGILL;
405 info.si_errno = 0;
406 info.si_code = ILL_ILLOPC;
407 info.si_addr = (void __user *) regs->pc;
408 send_sig_info(SIGILL, &info, current);
409}
410
411
412
413
414
415
416
417
418asmlinkage void
419do_entDbg(struct pt_regs *regs)
420{
421 siginfo_t info;
422
423 die_if_kernel("Instruction fault", regs, 0, NULL);
424
425 info.si_signo = SIGILL;
426 info.si_errno = 0;
427 info.si_code = ILL_ILLOPC;
428 info.si_addr = (void __user *) regs->pc;
429 force_sig_info(SIGILL, &info, current);
430}
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446struct allregs {
447 unsigned long regs[32];
448 unsigned long ps, pc, gp, a0, a1, a2;
449};
450
451struct unaligned_stat {
452 unsigned long count, va, pc;
453} unaligned[2];
454
455
456
457#define una_reg(r) (_regs[(r) >= 16 && (r) <= 18 ? (r)+19 : (r)])
458
459
460asmlinkage void
461do_entUna(void * va, unsigned long opcode, unsigned long reg,
462 struct allregs *regs)
463{
464 long error, tmp1, tmp2, tmp3, tmp4;
465 unsigned long pc = regs->pc - 4;
466 unsigned long *_regs = regs->regs;
467 const struct exception_table_entry *fixup;
468
469 unaligned[0].count++;
470 unaligned[0].va = (unsigned long) va;
471 unaligned[0].pc = pc;
472
473
474
475
476
477 switch (opcode) {
478 case 0x0c:
479 __asm__ __volatile__(
480 "1: ldq_u %1,0(%3)\n"
481 "2: ldq_u %2,1(%3)\n"
482 " extwl %1,%3,%1\n"
483 " extwh %2,%3,%2\n"
484 "3:\n"
485 ".section __ex_table,\"a\"\n"
486 " .long 1b - .\n"
487 " lda %1,3b-1b(%0)\n"
488 " .long 2b - .\n"
489 " lda %2,3b-2b(%0)\n"
490 ".previous"
491 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
492 : "r"(va), "0"(0));
493 if (error)
494 goto got_exception;
495 una_reg(reg) = tmp1|tmp2;
496 return;
497
498 case 0x28:
499 __asm__ __volatile__(
500 "1: ldq_u %1,0(%3)\n"
501 "2: ldq_u %2,3(%3)\n"
502 " extll %1,%3,%1\n"
503 " extlh %2,%3,%2\n"
504 "3:\n"
505 ".section __ex_table,\"a\"\n"
506 " .long 1b - .\n"
507 " lda %1,3b-1b(%0)\n"
508 " .long 2b - .\n"
509 " lda %2,3b-2b(%0)\n"
510 ".previous"
511 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
512 : "r"(va), "0"(0));
513 if (error)
514 goto got_exception;
515 una_reg(reg) = (int)(tmp1|tmp2);
516 return;
517
518 case 0x29:
519 __asm__ __volatile__(
520 "1: ldq_u %1,0(%3)\n"
521 "2: ldq_u %2,7(%3)\n"
522 " extql %1,%3,%1\n"
523 " extqh %2,%3,%2\n"
524 "3:\n"
525 ".section __ex_table,\"a\"\n"
526 " .long 1b - .\n"
527 " lda %1,3b-1b(%0)\n"
528 " .long 2b - .\n"
529 " lda %2,3b-2b(%0)\n"
530 ".previous"
531 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
532 : "r"(va), "0"(0));
533 if (error)
534 goto got_exception;
535 una_reg(reg) = tmp1|tmp2;
536 return;
537
538
539
540
541 case 0x0d:
542 __asm__ __volatile__(
543 "1: ldq_u %2,1(%5)\n"
544 "2: ldq_u %1,0(%5)\n"
545 " inswh %6,%5,%4\n"
546 " inswl %6,%5,%3\n"
547 " mskwh %2,%5,%2\n"
548 " mskwl %1,%5,%1\n"
549 " or %2,%4,%2\n"
550 " or %1,%3,%1\n"
551 "3: stq_u %2,1(%5)\n"
552 "4: stq_u %1,0(%5)\n"
553 "5:\n"
554 ".section __ex_table,\"a\"\n"
555 " .long 1b - .\n"
556 " lda %2,5b-1b(%0)\n"
557 " .long 2b - .\n"
558 " lda %1,5b-2b(%0)\n"
559 " .long 3b - .\n"
560 " lda $31,5b-3b(%0)\n"
561 " .long 4b - .\n"
562 " lda $31,5b-4b(%0)\n"
563 ".previous"
564 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
565 "=&r"(tmp3), "=&r"(tmp4)
566 : "r"(va), "r"(una_reg(reg)), "0"(0));
567 if (error)
568 goto got_exception;
569 return;
570
571 case 0x2c:
572 __asm__ __volatile__(
573 "1: ldq_u %2,3(%5)\n"
574 "2: ldq_u %1,0(%5)\n"
575 " inslh %6,%5,%4\n"
576 " insll %6,%5,%3\n"
577 " msklh %2,%5,%2\n"
578 " mskll %1,%5,%1\n"
579 " or %2,%4,%2\n"
580 " or %1,%3,%1\n"
581 "3: stq_u %2,3(%5)\n"
582 "4: stq_u %1,0(%5)\n"
583 "5:\n"
584 ".section __ex_table,\"a\"\n"
585 " .long 1b - .\n"
586 " lda %2,5b-1b(%0)\n"
587 " .long 2b - .\n"
588 " lda %1,5b-2b(%0)\n"
589 " .long 3b - .\n"
590 " lda $31,5b-3b(%0)\n"
591 " .long 4b - .\n"
592 " lda $31,5b-4b(%0)\n"
593 ".previous"
594 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
595 "=&r"(tmp3), "=&r"(tmp4)
596 : "r"(va), "r"(una_reg(reg)), "0"(0));
597 if (error)
598 goto got_exception;
599 return;
600
601 case 0x2d:
602 __asm__ __volatile__(
603 "1: ldq_u %2,7(%5)\n"
604 "2: ldq_u %1,0(%5)\n"
605 " insqh %6,%5,%4\n"
606 " insql %6,%5,%3\n"
607 " mskqh %2,%5,%2\n"
608 " mskql %1,%5,%1\n"
609 " or %2,%4,%2\n"
610 " or %1,%3,%1\n"
611 "3: stq_u %2,7(%5)\n"
612 "4: stq_u %1,0(%5)\n"
613 "5:\n"
614 ".section __ex_table,\"a\"\n\t"
615 " .long 1b - .\n"
616 " lda %2,5b-1b(%0)\n"
617 " .long 2b - .\n"
618 " lda %1,5b-2b(%0)\n"
619 " .long 3b - .\n"
620 " lda $31,5b-3b(%0)\n"
621 " .long 4b - .\n"
622 " lda $31,5b-4b(%0)\n"
623 ".previous"
624 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
625 "=&r"(tmp3), "=&r"(tmp4)
626 : "r"(va), "r"(una_reg(reg)), "0"(0));
627 if (error)
628 goto got_exception;
629 return;
630 }
631
632 printk("Bad unaligned kernel access at %016lx: %p %lx %lu\n",
633 pc, va, opcode, reg);
634 do_exit(SIGSEGV);
635
636got_exception:
637
638
639 if ((fixup = search_exception_tables(pc)) != 0) {
640 unsigned long newpc;
641 newpc = fixup_exception(una_reg, fixup, pc);
642
643 printk("Forwarding unaligned exception at %lx (%lx)\n",
644 pc, newpc);
645
646 regs->pc = newpc;
647 return;
648 }
649
650
651
652
653
654
655 printk("%s(%d): unhandled unaligned exception\n",
656 current->comm, task_pid_nr(current));
657
658 printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx\n",
659 pc, una_reg(26), regs->ps);
660 printk("r0 = %016lx r1 = %016lx r2 = %016lx\n",
661 una_reg(0), una_reg(1), una_reg(2));
662 printk("r3 = %016lx r4 = %016lx r5 = %016lx\n",
663 una_reg(3), una_reg(4), una_reg(5));
664 printk("r6 = %016lx r7 = %016lx r8 = %016lx\n",
665 una_reg(6), una_reg(7), una_reg(8));
666 printk("r9 = %016lx r10= %016lx r11= %016lx\n",
667 una_reg(9), una_reg(10), una_reg(11));
668 printk("r12= %016lx r13= %016lx r14= %016lx\n",
669 una_reg(12), una_reg(13), una_reg(14));
670 printk("r15= %016lx\n", una_reg(15));
671 printk("r16= %016lx r17= %016lx r18= %016lx\n",
672 una_reg(16), una_reg(17), una_reg(18));
673 printk("r19= %016lx r20= %016lx r21= %016lx\n",
674 una_reg(19), una_reg(20), una_reg(21));
675 printk("r22= %016lx r23= %016lx r24= %016lx\n",
676 una_reg(22), una_reg(23), una_reg(24));
677 printk("r25= %016lx r27= %016lx r28= %016lx\n",
678 una_reg(25), una_reg(27), una_reg(28));
679 printk("gp = %016lx sp = %p\n", regs->gp, regs+1);
680
681 dik_show_code((unsigned int *)pc);
682 dik_show_trace((unsigned long *)(regs+1));
683
684 if (test_and_set_thread_flag (TIF_DIE_IF_KERNEL)) {
685 printk("die_if_kernel recursion detected.\n");
686 local_irq_enable();
687 while (1);
688 }
689 do_exit(SIGSEGV);
690}
691
692
693
694
695
696
697
698static inline unsigned long
699s_mem_to_reg (unsigned long s_mem)
700{
701 unsigned long frac = (s_mem >> 0) & 0x7fffff;
702 unsigned long sign = (s_mem >> 31) & 0x1;
703 unsigned long exp_msb = (s_mem >> 30) & 0x1;
704 unsigned long exp_low = (s_mem >> 23) & 0x7f;
705 unsigned long exp;
706
707 exp = (exp_msb << 10) | exp_low;
708 if (exp_msb) {
709 if (exp_low == 0x7f) {
710 exp = 0x7ff;
711 }
712 } else {
713 if (exp_low == 0x00) {
714 exp = 0x000;
715 } else {
716 exp |= (0x7 << 7);
717 }
718 }
719 return (sign << 63) | (exp << 52) | (frac << 29);
720}
721
722
723
724
725
726static inline unsigned long
727s_reg_to_mem (unsigned long s_reg)
728{
729 return ((s_reg >> 62) << 30) | ((s_reg << 5) >> 34);
730}
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752#define OP_INT_MASK ( 1L << 0x28 | 1L << 0x2c \
753 | 1L << 0x29 | 1L << 0x2d \
754 | 1L << 0x0c | 1L << 0x0d \
755 | 1L << 0x0a | 1L << 0x0e )
756
757#define OP_WRITE_MASK ( 1L << 0x26 | 1L << 0x27 \
758 | 1L << 0x2c | 1L << 0x2d \
759 | 1L << 0x0d | 1L << 0x0e )
760
761#define R(x) ((size_t) &((struct pt_regs *)0)->x)
762
763static int unauser_reg_offsets[32] = {
764 R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), R(r8),
765
766 -56, -48, -40, -32, -24, -16, -8,
767 R(r16), R(r17), R(r18),
768 R(r19), R(r20), R(r21), R(r22), R(r23), R(r24), R(r25), R(r26),
769 R(r27), R(r28), R(gp),
770 0, 0
771};
772
773#undef R
774
775asmlinkage void
776do_entUnaUser(void __user * va, unsigned long opcode,
777 unsigned long reg, struct pt_regs *regs)
778{
779 static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 5);
780
781 unsigned long tmp1, tmp2, tmp3, tmp4;
782 unsigned long fake_reg, *reg_addr = &fake_reg;
783 siginfo_t info;
784 long error;
785
786
787
788
789 if (!(current_thread_info()->status & TS_UAC_NOPRINT)) {
790 if (__ratelimit(&ratelimit)) {
791 printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
792 current->comm, task_pid_nr(current),
793 regs->pc - 4, va, opcode, reg);
794 }
795 }
796 if ((current_thread_info()->status & TS_UAC_SIGBUS))
797 goto give_sigbus;
798
799 if ((current_thread_info()->status & TS_UAC_NOFIX))
800 return;
801
802
803
804
805 if (!__access_ok((unsigned long)va, 0, USER_DS))
806 goto give_sigsegv;
807
808 ++unaligned[1].count;
809 unaligned[1].va = (unsigned long)va;
810 unaligned[1].pc = regs->pc - 4;
811
812 if ((1L << opcode) & OP_INT_MASK) {
813
814 if (reg < 30) {
815 reg_addr = (unsigned long *)
816 ((char *)regs + unauser_reg_offsets[reg]);
817 } else if (reg == 30) {
818
819 fake_reg = rdusp();
820 } else {
821
822 fake_reg = 0;
823 }
824 }
825
826
827
828
829
830 switch (opcode) {
831 case 0x0c:
832 __asm__ __volatile__(
833 "1: ldq_u %1,0(%3)\n"
834 "2: ldq_u %2,1(%3)\n"
835 " extwl %1,%3,%1\n"
836 " extwh %2,%3,%2\n"
837 "3:\n"
838 ".section __ex_table,\"a\"\n"
839 " .long 1b - .\n"
840 " lda %1,3b-1b(%0)\n"
841 " .long 2b - .\n"
842 " lda %2,3b-2b(%0)\n"
843 ".previous"
844 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
845 : "r"(va), "0"(0));
846 if (error)
847 goto give_sigsegv;
848 *reg_addr = tmp1|tmp2;
849 break;
850
851 case 0x22:
852 __asm__ __volatile__(
853 "1: ldq_u %1,0(%3)\n"
854 "2: ldq_u %2,3(%3)\n"
855 " extll %1,%3,%1\n"
856 " extlh %2,%3,%2\n"
857 "3:\n"
858 ".section __ex_table,\"a\"\n"
859 " .long 1b - .\n"
860 " lda %1,3b-1b(%0)\n"
861 " .long 2b - .\n"
862 " lda %2,3b-2b(%0)\n"
863 ".previous"
864 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
865 : "r"(va), "0"(0));
866 if (error)
867 goto give_sigsegv;
868 alpha_write_fp_reg(reg, s_mem_to_reg((int)(tmp1|tmp2)));
869 return;
870
871 case 0x23:
872 __asm__ __volatile__(
873 "1: ldq_u %1,0(%3)\n"
874 "2: ldq_u %2,7(%3)\n"
875 " extql %1,%3,%1\n"
876 " extqh %2,%3,%2\n"
877 "3:\n"
878 ".section __ex_table,\"a\"\n"
879 " .long 1b - .\n"
880 " lda %1,3b-1b(%0)\n"
881 " .long 2b - .\n"
882 " lda %2,3b-2b(%0)\n"
883 ".previous"
884 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
885 : "r"(va), "0"(0));
886 if (error)
887 goto give_sigsegv;
888 alpha_write_fp_reg(reg, tmp1|tmp2);
889 return;
890
891 case 0x28:
892 __asm__ __volatile__(
893 "1: ldq_u %1,0(%3)\n"
894 "2: ldq_u %2,3(%3)\n"
895 " extll %1,%3,%1\n"
896 " extlh %2,%3,%2\n"
897 "3:\n"
898 ".section __ex_table,\"a\"\n"
899 " .long 1b - .\n"
900 " lda %1,3b-1b(%0)\n"
901 " .long 2b - .\n"
902 " lda %2,3b-2b(%0)\n"
903 ".previous"
904 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
905 : "r"(va), "0"(0));
906 if (error)
907 goto give_sigsegv;
908 *reg_addr = (int)(tmp1|tmp2);
909 break;
910
911 case 0x29:
912 __asm__ __volatile__(
913 "1: ldq_u %1,0(%3)\n"
914 "2: ldq_u %2,7(%3)\n"
915 " extql %1,%3,%1\n"
916 " extqh %2,%3,%2\n"
917 "3:\n"
918 ".section __ex_table,\"a\"\n"
919 " .long 1b - .\n"
920 " lda %1,3b-1b(%0)\n"
921 " .long 2b - .\n"
922 " lda %2,3b-2b(%0)\n"
923 ".previous"
924 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
925 : "r"(va), "0"(0));
926 if (error)
927 goto give_sigsegv;
928 *reg_addr = tmp1|tmp2;
929 break;
930
931
932
933
934 case 0x0d:
935 __asm__ __volatile__(
936 "1: ldq_u %2,1(%5)\n"
937 "2: ldq_u %1,0(%5)\n"
938 " inswh %6,%5,%4\n"
939 " inswl %6,%5,%3\n"
940 " mskwh %2,%5,%2\n"
941 " mskwl %1,%5,%1\n"
942 " or %2,%4,%2\n"
943 " or %1,%3,%1\n"
944 "3: stq_u %2,1(%5)\n"
945 "4: stq_u %1,0(%5)\n"
946 "5:\n"
947 ".section __ex_table,\"a\"\n"
948 " .long 1b - .\n"
949 " lda %2,5b-1b(%0)\n"
950 " .long 2b - .\n"
951 " lda %1,5b-2b(%0)\n"
952 " .long 3b - .\n"
953 " lda $31,5b-3b(%0)\n"
954 " .long 4b - .\n"
955 " lda $31,5b-4b(%0)\n"
956 ".previous"
957 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
958 "=&r"(tmp3), "=&r"(tmp4)
959 : "r"(va), "r"(*reg_addr), "0"(0));
960 if (error)
961 goto give_sigsegv;
962 return;
963
964 case 0x26:
965 fake_reg = s_reg_to_mem(alpha_read_fp_reg(reg));
966
967
968 case 0x2c:
969 __asm__ __volatile__(
970 "1: ldq_u %2,3(%5)\n"
971 "2: ldq_u %1,0(%5)\n"
972 " inslh %6,%5,%4\n"
973 " insll %6,%5,%3\n"
974 " msklh %2,%5,%2\n"
975 " mskll %1,%5,%1\n"
976 " or %2,%4,%2\n"
977 " or %1,%3,%1\n"
978 "3: stq_u %2,3(%5)\n"
979 "4: stq_u %1,0(%5)\n"
980 "5:\n"
981 ".section __ex_table,\"a\"\n"
982 " .long 1b - .\n"
983 " lda %2,5b-1b(%0)\n"
984 " .long 2b - .\n"
985 " lda %1,5b-2b(%0)\n"
986 " .long 3b - .\n"
987 " lda $31,5b-3b(%0)\n"
988 " .long 4b - .\n"
989 " lda $31,5b-4b(%0)\n"
990 ".previous"
991 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
992 "=&r"(tmp3), "=&r"(tmp4)
993 : "r"(va), "r"(*reg_addr), "0"(0));
994 if (error)
995 goto give_sigsegv;
996 return;
997
998 case 0x27:
999 fake_reg = alpha_read_fp_reg(reg);
1000
1001
1002 case 0x2d:
1003 __asm__ __volatile__(
1004 "1: ldq_u %2,7(%5)\n"
1005 "2: ldq_u %1,0(%5)\n"
1006 " insqh %6,%5,%4\n"
1007 " insql %6,%5,%3\n"
1008 " mskqh %2,%5,%2\n"
1009 " mskql %1,%5,%1\n"
1010 " or %2,%4,%2\n"
1011 " or %1,%3,%1\n"
1012 "3: stq_u %2,7(%5)\n"
1013 "4: stq_u %1,0(%5)\n"
1014 "5:\n"
1015 ".section __ex_table,\"a\"\n\t"
1016 " .long 1b - .\n"
1017 " lda %2,5b-1b(%0)\n"
1018 " .long 2b - .\n"
1019 " lda %1,5b-2b(%0)\n"
1020 " .long 3b - .\n"
1021 " lda $31,5b-3b(%0)\n"
1022 " .long 4b - .\n"
1023 " lda $31,5b-4b(%0)\n"
1024 ".previous"
1025 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
1026 "=&r"(tmp3), "=&r"(tmp4)
1027 : "r"(va), "r"(*reg_addr), "0"(0));
1028 if (error)
1029 goto give_sigsegv;
1030 return;
1031
1032 default:
1033
1034 goto give_sigbus;
1035 }
1036
1037
1038 if (reg == 30)
1039 wrusp(fake_reg);
1040 return;
1041
1042give_sigsegv:
1043 regs->pc -= 4;
1044 info.si_signo = SIGSEGV;
1045 info.si_errno = 0;
1046
1047
1048
1049
1050 if (!__access_ok((unsigned long)va, 0, USER_DS))
1051 info.si_code = SEGV_ACCERR;
1052 else {
1053 struct mm_struct *mm = current->mm;
1054 down_read(&mm->mmap_sem);
1055 if (find_vma(mm, (unsigned long)va))
1056 info.si_code = SEGV_ACCERR;
1057 else
1058 info.si_code = SEGV_MAPERR;
1059 up_read(&mm->mmap_sem);
1060 }
1061 info.si_addr = va;
1062 send_sig_info(SIGSEGV, &info, current);
1063 return;
1064
1065give_sigbus:
1066 regs->pc -= 4;
1067 info.si_signo = SIGBUS;
1068 info.si_errno = 0;
1069 info.si_code = BUS_ADRALN;
1070 info.si_addr = va;
1071 send_sig_info(SIGBUS, &info, current);
1072 return;
1073}
1074
1075void
1076trap_init(void)
1077{
1078
1079 register unsigned long gptr __asm__("$29");
1080 wrkgp(gptr);
1081
1082
1083
1084 if (implver() == IMPLVER_EV4)
1085 opDEC_check();
1086
1087 wrent(entArith, 1);
1088 wrent(entMM, 2);
1089 wrent(entIF, 3);
1090 wrent(entUna, 4);
1091 wrent(entSys, 5);
1092 wrent(entDbg, 6);
1093}
1094