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