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