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 EXC(1b,3b,%1,%0)
486 EXC(2b,3b,%2,%0)
487 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
488 : "r"(va), "0"(0));
489 if (error)
490 goto got_exception;
491 una_reg(reg) = tmp1|tmp2;
492 return;
493
494 case 0x28:
495 __asm__ __volatile__(
496 "1: ldq_u %1,0(%3)\n"
497 "2: ldq_u %2,3(%3)\n"
498 " extll %1,%3,%1\n"
499 " extlh %2,%3,%2\n"
500 "3:\n"
501 EXC(1b,3b,%1,%0)
502 EXC(2b,3b,%2,%0)
503 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
504 : "r"(va), "0"(0));
505 if (error)
506 goto got_exception;
507 una_reg(reg) = (int)(tmp1|tmp2);
508 return;
509
510 case 0x29:
511 __asm__ __volatile__(
512 "1: ldq_u %1,0(%3)\n"
513 "2: ldq_u %2,7(%3)\n"
514 " extql %1,%3,%1\n"
515 " extqh %2,%3,%2\n"
516 "3:\n"
517 EXC(1b,3b,%1,%0)
518 EXC(2b,3b,%2,%0)
519 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
520 : "r"(va), "0"(0));
521 if (error)
522 goto got_exception;
523 una_reg(reg) = tmp1|tmp2;
524 return;
525
526
527
528
529 case 0x0d:
530 __asm__ __volatile__(
531 "1: ldq_u %2,1(%5)\n"
532 "2: ldq_u %1,0(%5)\n"
533 " inswh %6,%5,%4\n"
534 " inswl %6,%5,%3\n"
535 " mskwh %2,%5,%2\n"
536 " mskwl %1,%5,%1\n"
537 " or %2,%4,%2\n"
538 " or %1,%3,%1\n"
539 "3: stq_u %2,1(%5)\n"
540 "4: stq_u %1,0(%5)\n"
541 "5:\n"
542 EXC(1b,5b,%2,%0)
543 EXC(2b,5b,%1,%0)
544 EXC(3b,5b,$31,%0)
545 EXC(4b,5b,$31,%0)
546 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
547 "=&r"(tmp3), "=&r"(tmp4)
548 : "r"(va), "r"(una_reg(reg)), "0"(0));
549 if (error)
550 goto got_exception;
551 return;
552
553 case 0x2c:
554 __asm__ __volatile__(
555 "1: ldq_u %2,3(%5)\n"
556 "2: ldq_u %1,0(%5)\n"
557 " inslh %6,%5,%4\n"
558 " insll %6,%5,%3\n"
559 " msklh %2,%5,%2\n"
560 " mskll %1,%5,%1\n"
561 " or %2,%4,%2\n"
562 " or %1,%3,%1\n"
563 "3: stq_u %2,3(%5)\n"
564 "4: stq_u %1,0(%5)\n"
565 "5:\n"
566 EXC(1b,5b,%2,%0)
567 EXC(2b,5b,%1,%0)
568 EXC(3b,5b,$31,%0)
569 EXC(4b,5b,$31,%0)
570 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
571 "=&r"(tmp3), "=&r"(tmp4)
572 : "r"(va), "r"(una_reg(reg)), "0"(0));
573 if (error)
574 goto got_exception;
575 return;
576
577 case 0x2d:
578 __asm__ __volatile__(
579 "1: ldq_u %2,7(%5)\n"
580 "2: ldq_u %1,0(%5)\n"
581 " insqh %6,%5,%4\n"
582 " insql %6,%5,%3\n"
583 " mskqh %2,%5,%2\n"
584 " mskql %1,%5,%1\n"
585 " or %2,%4,%2\n"
586 " or %1,%3,%1\n"
587 "3: stq_u %2,7(%5)\n"
588 "4: stq_u %1,0(%5)\n"
589 "5:\n"
590 EXC(1b,5b,%2,%0)
591 EXC(2b,5b,%1,%0)
592 EXC(3b,5b,$31,%0)
593 EXC(4b,5b,$31,%0)
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
602 printk("Bad unaligned kernel access at %016lx: %p %lx %lu\n",
603 pc, va, opcode, reg);
604 do_exit(SIGSEGV);
605
606got_exception:
607
608
609 if ((fixup = search_exception_tables(pc)) != 0) {
610 unsigned long newpc;
611 newpc = fixup_exception(una_reg, fixup, pc);
612
613 printk("Forwarding unaligned exception at %lx (%lx)\n",
614 pc, newpc);
615
616 regs->pc = newpc;
617 return;
618 }
619
620
621
622
623
624
625 printk("%s(%d): unhandled unaligned exception\n",
626 current->comm, task_pid_nr(current));
627
628 printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx\n",
629 pc, una_reg(26), regs->ps);
630 printk("r0 = %016lx r1 = %016lx r2 = %016lx\n",
631 una_reg(0), una_reg(1), una_reg(2));
632 printk("r3 = %016lx r4 = %016lx r5 = %016lx\n",
633 una_reg(3), una_reg(4), una_reg(5));
634 printk("r6 = %016lx r7 = %016lx r8 = %016lx\n",
635 una_reg(6), una_reg(7), una_reg(8));
636 printk("r9 = %016lx r10= %016lx r11= %016lx\n",
637 una_reg(9), una_reg(10), una_reg(11));
638 printk("r12= %016lx r13= %016lx r14= %016lx\n",
639 una_reg(12), una_reg(13), una_reg(14));
640 printk("r15= %016lx\n", una_reg(15));
641 printk("r16= %016lx r17= %016lx r18= %016lx\n",
642 una_reg(16), una_reg(17), una_reg(18));
643 printk("r19= %016lx r20= %016lx r21= %016lx\n",
644 una_reg(19), una_reg(20), una_reg(21));
645 printk("r22= %016lx r23= %016lx r24= %016lx\n",
646 una_reg(22), una_reg(23), una_reg(24));
647 printk("r25= %016lx r27= %016lx r28= %016lx\n",
648 una_reg(25), una_reg(27), una_reg(28));
649 printk("gp = %016lx sp = %p\n", regs->gp, regs+1);
650
651 dik_show_code((unsigned int *)pc);
652 dik_show_trace((unsigned long *)(regs+1));
653
654 if (test_and_set_thread_flag (TIF_DIE_IF_KERNEL)) {
655 printk("die_if_kernel recursion detected.\n");
656 local_irq_enable();
657 while (1);
658 }
659 do_exit(SIGSEGV);
660}
661
662
663
664
665
666
667
668static inline unsigned long
669s_mem_to_reg (unsigned long s_mem)
670{
671 unsigned long frac = (s_mem >> 0) & 0x7fffff;
672 unsigned long sign = (s_mem >> 31) & 0x1;
673 unsigned long exp_msb = (s_mem >> 30) & 0x1;
674 unsigned long exp_low = (s_mem >> 23) & 0x7f;
675 unsigned long exp;
676
677 exp = (exp_msb << 10) | exp_low;
678 if (exp_msb) {
679 if (exp_low == 0x7f) {
680 exp = 0x7ff;
681 }
682 } else {
683 if (exp_low == 0x00) {
684 exp = 0x000;
685 } else {
686 exp |= (0x7 << 7);
687 }
688 }
689 return (sign << 63) | (exp << 52) | (frac << 29);
690}
691
692
693
694
695
696static inline unsigned long
697s_reg_to_mem (unsigned long s_reg)
698{
699 return ((s_reg >> 62) << 30) | ((s_reg << 5) >> 34);
700}
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722#define OP_INT_MASK ( 1L << 0x28 | 1L << 0x2c \
723 | 1L << 0x29 | 1L << 0x2d \
724 | 1L << 0x0c | 1L << 0x0d \
725 | 1L << 0x0a | 1L << 0x0e )
726
727#define OP_WRITE_MASK ( 1L << 0x26 | 1L << 0x27 \
728 | 1L << 0x2c | 1L << 0x2d \
729 | 1L << 0x0d | 1L << 0x0e )
730
731#define R(x) ((size_t) &((struct pt_regs *)0)->x)
732
733static int unauser_reg_offsets[32] = {
734 R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), R(r8),
735
736 -56, -48, -40, -32, -24, -16, -8,
737 R(r16), R(r17), R(r18),
738 R(r19), R(r20), R(r21), R(r22), R(r23), R(r24), R(r25), R(r26),
739 R(r27), R(r28), R(gp),
740 0, 0
741};
742
743#undef R
744
745asmlinkage void
746do_entUnaUser(void __user * va, unsigned long opcode,
747 unsigned long reg, struct pt_regs *regs)
748{
749 static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 5);
750
751 unsigned long tmp1, tmp2, tmp3, tmp4;
752 unsigned long fake_reg, *reg_addr = &fake_reg;
753 siginfo_t info;
754 long error;
755
756
757
758
759 if (!(current_thread_info()->status & TS_UAC_NOPRINT)) {
760 if (__ratelimit(&ratelimit)) {
761 printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
762 current->comm, task_pid_nr(current),
763 regs->pc - 4, va, opcode, reg);
764 }
765 }
766 if ((current_thread_info()->status & TS_UAC_SIGBUS))
767 goto give_sigbus;
768
769 if ((current_thread_info()->status & TS_UAC_NOFIX))
770 return;
771
772
773
774
775 if ((unsigned long)va >= TASK_SIZE)
776 goto give_sigsegv;
777
778 ++unaligned[1].count;
779 unaligned[1].va = (unsigned long)va;
780 unaligned[1].pc = regs->pc - 4;
781
782 if ((1L << opcode) & OP_INT_MASK) {
783
784 if (reg < 30) {
785 reg_addr = (unsigned long *)
786 ((char *)regs + unauser_reg_offsets[reg]);
787 } else if (reg == 30) {
788
789 fake_reg = rdusp();
790 } else {
791
792 fake_reg = 0;
793 }
794 }
795
796
797
798
799
800 switch (opcode) {
801 case 0x0c:
802 __asm__ __volatile__(
803 "1: ldq_u %1,0(%3)\n"
804 "2: ldq_u %2,1(%3)\n"
805 " extwl %1,%3,%1\n"
806 " extwh %2,%3,%2\n"
807 "3:\n"
808 EXC(1b,3b,%1,%0)
809 EXC(2b,3b,%2,%0)
810 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
811 : "r"(va), "0"(0));
812 if (error)
813 goto give_sigsegv;
814 *reg_addr = tmp1|tmp2;
815 break;
816
817 case 0x22:
818 __asm__ __volatile__(
819 "1: ldq_u %1,0(%3)\n"
820 "2: ldq_u %2,3(%3)\n"
821 " extll %1,%3,%1\n"
822 " extlh %2,%3,%2\n"
823 "3:\n"
824 EXC(1b,3b,%1,%0)
825 EXC(2b,3b,%2,%0)
826 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
827 : "r"(va), "0"(0));
828 if (error)
829 goto give_sigsegv;
830 alpha_write_fp_reg(reg, s_mem_to_reg((int)(tmp1|tmp2)));
831 return;
832
833 case 0x23:
834 __asm__ __volatile__(
835 "1: ldq_u %1,0(%3)\n"
836 "2: ldq_u %2,7(%3)\n"
837 " extql %1,%3,%1\n"
838 " extqh %2,%3,%2\n"
839 "3:\n"
840 EXC(1b,3b,%1,%0)
841 EXC(2b,3b,%2,%0)
842 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
843 : "r"(va), "0"(0));
844 if (error)
845 goto give_sigsegv;
846 alpha_write_fp_reg(reg, tmp1|tmp2);
847 return;
848
849 case 0x28:
850 __asm__ __volatile__(
851 "1: ldq_u %1,0(%3)\n"
852 "2: ldq_u %2,3(%3)\n"
853 " extll %1,%3,%1\n"
854 " extlh %2,%3,%2\n"
855 "3:\n"
856 EXC(1b,3b,%1,%0)
857 EXC(2b,3b,%2,%0)
858 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
859 : "r"(va), "0"(0));
860 if (error)
861 goto give_sigsegv;
862 *reg_addr = (int)(tmp1|tmp2);
863 break;
864
865 case 0x29:
866 __asm__ __volatile__(
867 "1: ldq_u %1,0(%3)\n"
868 "2: ldq_u %2,7(%3)\n"
869 " extql %1,%3,%1\n"
870 " extqh %2,%3,%2\n"
871 "3:\n"
872 EXC(1b,3b,%1,%0)
873 EXC(2b,3b,%2,%0)
874 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
875 : "r"(va), "0"(0));
876 if (error)
877 goto give_sigsegv;
878 *reg_addr = tmp1|tmp2;
879 break;
880
881
882
883
884 case 0x0d:
885 __asm__ __volatile__(
886 "1: ldq_u %2,1(%5)\n"
887 "2: ldq_u %1,0(%5)\n"
888 " inswh %6,%5,%4\n"
889 " inswl %6,%5,%3\n"
890 " mskwh %2,%5,%2\n"
891 " mskwl %1,%5,%1\n"
892 " or %2,%4,%2\n"
893 " or %1,%3,%1\n"
894 "3: stq_u %2,1(%5)\n"
895 "4: stq_u %1,0(%5)\n"
896 "5:\n"
897 EXC(1b,5b,%2,%0)
898 EXC(2b,5b,%1,%0)
899 EXC(3b,5b,$31,%0)
900 EXC(4b,5b,$31,%0)
901 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
902 "=&r"(tmp3), "=&r"(tmp4)
903 : "r"(va), "r"(*reg_addr), "0"(0));
904 if (error)
905 goto give_sigsegv;
906 return;
907
908 case 0x26:
909 fake_reg = s_reg_to_mem(alpha_read_fp_reg(reg));
910
911
912 case 0x2c:
913 __asm__ __volatile__(
914 "1: ldq_u %2,3(%5)\n"
915 "2: ldq_u %1,0(%5)\n"
916 " inslh %6,%5,%4\n"
917 " insll %6,%5,%3\n"
918 " msklh %2,%5,%2\n"
919 " mskll %1,%5,%1\n"
920 " or %2,%4,%2\n"
921 " or %1,%3,%1\n"
922 "3: stq_u %2,3(%5)\n"
923 "4: stq_u %1,0(%5)\n"
924 "5:\n"
925 EXC(1b,5b,%2,%0)
926 EXC(2b,5b,%1,%0)
927 EXC(3b,5b,$31,%0)
928 EXC(4b,5b,$31,%0)
929 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
930 "=&r"(tmp3), "=&r"(tmp4)
931 : "r"(va), "r"(*reg_addr), "0"(0));
932 if (error)
933 goto give_sigsegv;
934 return;
935
936 case 0x27:
937 fake_reg = alpha_read_fp_reg(reg);
938
939
940 case 0x2d:
941 __asm__ __volatile__(
942 "1: ldq_u %2,7(%5)\n"
943 "2: ldq_u %1,0(%5)\n"
944 " insqh %6,%5,%4\n"
945 " insql %6,%5,%3\n"
946 " mskqh %2,%5,%2\n"
947 " mskql %1,%5,%1\n"
948 " or %2,%4,%2\n"
949 " or %1,%3,%1\n"
950 "3: stq_u %2,7(%5)\n"
951 "4: stq_u %1,0(%5)\n"
952 "5:\n"
953 EXC(1b,5b,%2,%0)
954 EXC(2b,5b,%1,%0)
955 EXC(3b,5b,$31,%0)
956 EXC(4b,5b,$31,%0)
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 default:
965
966 goto give_sigbus;
967 }
968
969
970 if (reg == 30)
971 wrusp(fake_reg);
972 return;
973
974give_sigsegv:
975 regs->pc -= 4;
976 info.si_signo = SIGSEGV;
977 info.si_errno = 0;
978
979
980
981
982 if ((unsigned long)va >= TASK_SIZE)
983 info.si_code = SEGV_ACCERR;
984 else {
985 struct mm_struct *mm = current->mm;
986 down_read(&mm->mmap_sem);
987 if (find_vma(mm, (unsigned long)va))
988 info.si_code = SEGV_ACCERR;
989 else
990 info.si_code = SEGV_MAPERR;
991 up_read(&mm->mmap_sem);
992 }
993 info.si_addr = va;
994 send_sig_info(SIGSEGV, &info, current);
995 return;
996
997give_sigbus:
998 regs->pc -= 4;
999 info.si_signo = SIGBUS;
1000 info.si_errno = 0;
1001 info.si_code = BUS_ADRALN;
1002 info.si_addr = va;
1003 send_sig_info(SIGBUS, &info, current);
1004 return;
1005}
1006
1007void
1008trap_init(void)
1009{
1010
1011 register unsigned long gptr __asm__("$29");
1012 wrkgp(gptr);
1013
1014
1015
1016 if (implver() == IMPLVER_EV4)
1017 opDEC_check();
1018
1019 wrent(entArith, 1);
1020 wrent(entMM, 2);
1021 wrent(entIF, 3);
1022 wrent(entUna, 4);
1023 wrent(entSys, 5);
1024 wrent(entDbg, 6);
1025}
1026