1
2
3
4
5
6
7
8
9
10
11#include <linux/config.h>
12#include <linux/mm.h>
13#include <linux/sched.h>
14#include <linux/tty.h>
15#include <linux/delay.h>
16#include <linux/smp_lock.h>
17#include <linux/module.h>
18#include <linux/init.h>
19#include <linux/kallsyms.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 __init
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, current->pid, str, err);
187 dik_show_regs(regs, r9_15);
188 dik_show_trace((unsigned long *)(regs+1));
189 dik_show_code((unsigned int *)regs->pc);
190
191 if (test_and_set_thread_flag (TIF_DIE_IF_KERNEL)) {
192 printk("die_if_kernel recursion detected.\n");
193 local_irq_enable();
194 while (1);
195 }
196 do_exit(SIGSEGV);
197}
198
199#ifndef CONFIG_MATHEMU
200static long dummy_emul(void) { return 0; }
201long (*alpha_fp_emul_imprecise)(struct pt_regs *regs, unsigned long writemask)
202 = (void *)dummy_emul;
203long (*alpha_fp_emul) (unsigned long pc)
204 = (void *)dummy_emul;
205#else
206long alpha_fp_emul_imprecise(struct pt_regs *regs, unsigned long writemask);
207long alpha_fp_emul (unsigned long pc);
208#endif
209
210asmlinkage void
211do_entArith(unsigned long summary, unsigned long write_mask,
212 struct pt_regs *regs)
213{
214 long si_code = FPE_FLTINV;
215 siginfo_t info;
216
217 if (summary & 1) {
218
219
220
221 if (!amask(AMASK_PRECISE_TRAP))
222 si_code = alpha_fp_emul(regs->pc - 4);
223 else
224 si_code = alpha_fp_emul_imprecise(regs, write_mask);
225 if (si_code == 0)
226 return;
227 }
228 die_if_kernel("Arithmetic fault", regs, 0, NULL);
229
230 info.si_signo = SIGFPE;
231 info.si_errno = 0;
232 info.si_code = si_code;
233 info.si_addr = (void __user *) regs->pc;
234 send_sig_info(SIGFPE, &info, current);
235}
236
237asmlinkage void
238do_entIF(unsigned long type, struct pt_regs *regs)
239{
240 siginfo_t info;
241 int signo, code;
242
243 if (regs->ps == 0) {
244 if (type == 1) {
245 const unsigned int *data
246 = (const unsigned int *) regs->pc;
247 printk("Kernel bug at %s:%d\n",
248 (const char *)(data[1] | (long)data[2] << 32),
249 data[0]);
250 }
251 die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"),
252 regs, type, NULL);
253 }
254
255 switch (type) {
256 case 0:
257 info.si_signo = SIGTRAP;
258 info.si_errno = 0;
259 info.si_code = TRAP_BRKPT;
260 info.si_trapno = 0;
261 info.si_addr = (void __user *) regs->pc;
262
263 if (ptrace_cancel_bpt(current)) {
264 regs->pc -= 4;
265 }
266
267 send_sig_info(SIGTRAP, &info, current);
268 return;
269
270 case 1:
271 info.si_signo = SIGTRAP;
272 info.si_errno = 0;
273 info.si_code = __SI_FAULT;
274 info.si_addr = (void __user *) regs->pc;
275 info.si_trapno = 0;
276 send_sig_info(SIGTRAP, &info, current);
277 return;
278
279 case 2:
280 info.si_addr = (void __user *) regs->pc;
281 info.si_trapno = regs->r16;
282 switch ((long) regs->r16) {
283 case GEN_INTOVF:
284 signo = SIGFPE;
285 code = FPE_INTOVF;
286 break;
287 case GEN_INTDIV:
288 signo = SIGFPE;
289 code = FPE_INTDIV;
290 break;
291 case GEN_FLTOVF:
292 signo = SIGFPE;
293 code = FPE_FLTOVF;
294 break;
295 case GEN_FLTDIV:
296 signo = SIGFPE;
297 code = FPE_FLTDIV;
298 break;
299 case GEN_FLTUND:
300 signo = SIGFPE;
301 code = FPE_FLTUND;
302 break;
303 case GEN_FLTINV:
304 signo = SIGFPE;
305 code = FPE_FLTINV;
306 break;
307 case GEN_FLTINE:
308 signo = SIGFPE;
309 code = FPE_FLTRES;
310 break;
311 case GEN_ROPRAND:
312 signo = SIGFPE;
313 code = __SI_FAULT;
314 break;
315
316 case GEN_DECOVF:
317 case GEN_DECDIV:
318 case GEN_DECINV:
319 case GEN_ASSERTERR:
320 case GEN_NULPTRERR:
321 case GEN_STKOVF:
322 case GEN_STRLENERR:
323 case GEN_SUBSTRERR:
324 case GEN_RANGERR:
325 case GEN_SUBRNG:
326 case GEN_SUBRNG1:
327 case GEN_SUBRNG2:
328 case GEN_SUBRNG3:
329 case GEN_SUBRNG4:
330 case GEN_SUBRNG5:
331 case GEN_SUBRNG6:
332 case GEN_SUBRNG7:
333 default:
334 signo = SIGTRAP;
335 code = __SI_FAULT;
336 break;
337 }
338
339 info.si_signo = signo;
340 info.si_errno = 0;
341 info.si_code = code;
342 info.si_addr = (void __user *) regs->pc;
343 send_sig_info(signo, &info, current);
344 return;
345
346 case 4:
347 if (implver() == IMPLVER_EV4) {
348 long si_code;
349
350
351
352
353
354
355
356
357
358 regs->pc += opDEC_fix;
359
360
361
362
363 si_code = alpha_fp_emul(regs->pc - 4);
364 if (si_code == 0)
365 return;
366 if (si_code > 0) {
367 info.si_signo = SIGFPE;
368 info.si_errno = 0;
369 info.si_code = si_code;
370 info.si_addr = (void __user *) regs->pc;
371 send_sig_info(SIGFPE, &info, current);
372 return;
373 }
374 }
375 break;
376
377 case 3:
378
379
380
381
382
383
384
385
386
387 current_thread_info()->pcb.flags |= 1;
388 __reload_thread(¤t_thread_info()->pcb);
389 return;
390
391 case 5:
392 default:
393 ;
394 }
395
396 info.si_signo = SIGILL;
397 info.si_errno = 0;
398 info.si_code = ILL_ILLOPC;
399 info.si_addr = (void __user *) regs->pc;
400 send_sig_info(SIGILL, &info, current);
401}
402
403
404
405
406
407
408
409
410asmlinkage void
411do_entDbg(struct pt_regs *regs)
412{
413 siginfo_t info;
414
415 die_if_kernel("Instruction fault", regs, 0, NULL);
416
417 info.si_signo = SIGILL;
418 info.si_errno = 0;
419 info.si_code = ILL_ILLOPC;
420 info.si_addr = (void __user *) regs->pc;
421 force_sig_info(SIGILL, &info, current);
422}
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438struct allregs {
439 unsigned long regs[32];
440 unsigned long ps, pc, gp, a0, a1, a2;
441};
442
443struct unaligned_stat {
444 unsigned long count, va, pc;
445} unaligned[2];
446
447
448
449#define una_reg(r) (regs.regs[(r) >= 16 && (r) <= 18 ? (r)+19 : (r)])
450
451
452asmlinkage void
453do_entUna(void * va, unsigned long opcode, unsigned long reg,
454 unsigned long a3, unsigned long a4, unsigned long a5,
455 struct allregs regs)
456{
457 long error, tmp1, tmp2, tmp3, tmp4;
458 unsigned long pc = regs.pc - 4;
459 const struct exception_table_entry *fixup;
460
461 unaligned[0].count++;
462 unaligned[0].va = (unsigned long) va;
463 unaligned[0].pc = pc;
464
465
466
467
468
469 switch (opcode) {
470 case 0x0c:
471 __asm__ __volatile__(
472 "1: ldq_u %1,0(%3)\n"
473 "2: ldq_u %2,1(%3)\n"
474 " extwl %1,%3,%1\n"
475 " extwh %2,%3,%2\n"
476 "3:\n"
477 ".section __ex_table,\"a\"\n"
478 " .long 1b - .\n"
479 " lda %1,3b-1b(%0)\n"
480 " .long 2b - .\n"
481 " lda %2,3b-2b(%0)\n"
482 ".previous"
483 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
484 : "r"(va), "0"(0));
485 if (error)
486 goto got_exception;
487 una_reg(reg) = tmp1|tmp2;
488 return;
489
490 case 0x28:
491 __asm__ __volatile__(
492 "1: ldq_u %1,0(%3)\n"
493 "2: ldq_u %2,3(%3)\n"
494 " extll %1,%3,%1\n"
495 " extlh %2,%3,%2\n"
496 "3:\n"
497 ".section __ex_table,\"a\"\n"
498 " .long 1b - .\n"
499 " lda %1,3b-1b(%0)\n"
500 " .long 2b - .\n"
501 " lda %2,3b-2b(%0)\n"
502 ".previous"
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 ".section __ex_table,\"a\"\n"
518 " .long 1b - .\n"
519 " lda %1,3b-1b(%0)\n"
520 " .long 2b - .\n"
521 " lda %2,3b-2b(%0)\n"
522 ".previous"
523 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
524 : "r"(va), "0"(0));
525 if (error)
526 goto got_exception;
527 una_reg(reg) = tmp1|tmp2;
528 return;
529
530
531
532
533 case 0x0d:
534 __asm__ __volatile__(
535 "1: ldq_u %2,1(%5)\n"
536 "2: ldq_u %1,0(%5)\n"
537 " inswh %6,%5,%4\n"
538 " inswl %6,%5,%3\n"
539 " mskwh %2,%5,%2\n"
540 " mskwl %1,%5,%1\n"
541 " or %2,%4,%2\n"
542 " or %1,%3,%1\n"
543 "3: stq_u %2,1(%5)\n"
544 "4: stq_u %1,0(%5)\n"
545 "5:\n"
546 ".section __ex_table,\"a\"\n"
547 " .long 1b - .\n"
548 " lda %2,5b-1b(%0)\n"
549 " .long 2b - .\n"
550 " lda %1,5b-2b(%0)\n"
551 " .long 3b - .\n"
552 " lda $31,5b-3b(%0)\n"
553 " .long 4b - .\n"
554 " lda $31,5b-4b(%0)\n"
555 ".previous"
556 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
557 "=&r"(tmp3), "=&r"(tmp4)
558 : "r"(va), "r"(una_reg(reg)), "0"(0));
559 if (error)
560 goto got_exception;
561 return;
562
563 case 0x2c:
564 __asm__ __volatile__(
565 "1: ldq_u %2,3(%5)\n"
566 "2: ldq_u %1,0(%5)\n"
567 " inslh %6,%5,%4\n"
568 " insll %6,%5,%3\n"
569 " msklh %2,%5,%2\n"
570 " mskll %1,%5,%1\n"
571 " or %2,%4,%2\n"
572 " or %1,%3,%1\n"
573 "3: stq_u %2,3(%5)\n"
574 "4: stq_u %1,0(%5)\n"
575 "5:\n"
576 ".section __ex_table,\"a\"\n"
577 " .long 1b - .\n"
578 " lda %2,5b-1b(%0)\n"
579 " .long 2b - .\n"
580 " lda %1,5b-2b(%0)\n"
581 " .long 3b - .\n"
582 " lda $31,5b-3b(%0)\n"
583 " .long 4b - .\n"
584 " lda $31,5b-4b(%0)\n"
585 ".previous"
586 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
587 "=&r"(tmp3), "=&r"(tmp4)
588 : "r"(va), "r"(una_reg(reg)), "0"(0));
589 if (error)
590 goto got_exception;
591 return;
592
593 case 0x2d:
594 __asm__ __volatile__(
595 "1: ldq_u %2,7(%5)\n"
596 "2: ldq_u %1,0(%5)\n"
597 " insqh %6,%5,%4\n"
598 " insql %6,%5,%3\n"
599 " mskqh %2,%5,%2\n"
600 " mskql %1,%5,%1\n"
601 " or %2,%4,%2\n"
602 " or %1,%3,%1\n"
603 "3: stq_u %2,7(%5)\n"
604 "4: stq_u %1,0(%5)\n"
605 "5:\n"
606 ".section __ex_table,\"a\"\n\t"
607 " .long 1b - .\n"
608 " lda %2,5b-1b(%0)\n"
609 " .long 2b - .\n"
610 " lda %1,5b-2b(%0)\n"
611 " .long 3b - .\n"
612 " lda $31,5b-3b(%0)\n"
613 " .long 4b - .\n"
614 " lda $31,5b-4b(%0)\n"
615 ".previous"
616 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
617 "=&r"(tmp3), "=&r"(tmp4)
618 : "r"(va), "r"(una_reg(reg)), "0"(0));
619 if (error)
620 goto got_exception;
621 return;
622 }
623
624 lock_kernel();
625 printk("Bad unaligned kernel access at %016lx: %p %lx %ld\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 (®s)->pc = newpc;
640 return;
641 }
642
643
644
645
646
647 lock_kernel();
648
649 printk("%s(%d): unhandled unaligned exception\n",
650 current->comm, current->pid);
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, ®s+1);
674
675 dik_show_code((unsigned int *)pc);
676 dik_show_trace((unsigned long *)(®s+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 int cnt = 0;
774 static long last_time = 0;
775
776 unsigned long tmp1, tmp2, tmp3, tmp4;
777 unsigned long fake_reg, *reg_addr = &fake_reg;
778 siginfo_t info;
779 long error;
780
781
782
783
784 if (!test_thread_flag (TIF_UAC_NOPRINT)) {
785 if (cnt >= 5 && jiffies - last_time > 5*HZ) {
786 cnt = 0;
787 }
788 if (++cnt < 5) {
789 printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
790 current->comm, current->pid,
791 regs->pc - 4, va, opcode, reg);
792 }
793 last_time = jiffies;
794 }
795 if (test_thread_flag (TIF_UAC_SIGBUS))
796 goto give_sigbus;
797
798 if (test_thread_flag (TIF_UAC_NOFIX))
799 return;
800
801
802
803
804 if (!__access_ok((unsigned long)va, 0, USER_DS))
805 goto give_sigsegv;
806
807 ++unaligned[1].count;
808 unaligned[1].va = (unsigned long)va;
809 unaligned[1].pc = regs->pc - 4;
810
811 if ((1L << opcode) & OP_INT_MASK) {
812
813 if (reg < 30) {
814 reg_addr = (unsigned long *)
815 ((char *)regs + unauser_reg_offsets[reg]);
816 } else if (reg == 30) {
817
818 fake_reg = rdusp();
819 } else {
820
821 fake_reg = 0;
822 }
823 }
824
825
826
827
828
829 switch (opcode) {
830 case 0x0c:
831 __asm__ __volatile__(
832 "1: ldq_u %1,0(%3)\n"
833 "2: ldq_u %2,1(%3)\n"
834 " extwl %1,%3,%1\n"
835 " extwh %2,%3,%2\n"
836 "3:\n"
837 ".section __ex_table,\"a\"\n"
838 " .long 1b - .\n"
839 " lda %1,3b-1b(%0)\n"
840 " .long 2b - .\n"
841 " lda %2,3b-2b(%0)\n"
842 ".previous"
843 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
844 : "r"(va), "0"(0));
845 if (error)
846 goto give_sigsegv;
847 *reg_addr = tmp1|tmp2;
848 break;
849
850 case 0x22:
851 __asm__ __volatile__(
852 "1: ldq_u %1,0(%3)\n"
853 "2: ldq_u %2,3(%3)\n"
854 " extll %1,%3,%1\n"
855 " extlh %2,%3,%2\n"
856 "3:\n"
857 ".section __ex_table,\"a\"\n"
858 " .long 1b - .\n"
859 " lda %1,3b-1b(%0)\n"
860 " .long 2b - .\n"
861 " lda %2,3b-2b(%0)\n"
862 ".previous"
863 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
864 : "r"(va), "0"(0));
865 if (error)
866 goto give_sigsegv;
867 alpha_write_fp_reg(reg, s_mem_to_reg((int)(tmp1|tmp2)));
868 return;
869
870 case 0x23:
871 __asm__ __volatile__(
872 "1: ldq_u %1,0(%3)\n"
873 "2: ldq_u %2,7(%3)\n"
874 " extql %1,%3,%1\n"
875 " extqh %2,%3,%2\n"
876 "3:\n"
877 ".section __ex_table,\"a\"\n"
878 " .long 1b - .\n"
879 " lda %1,3b-1b(%0)\n"
880 " .long 2b - .\n"
881 " lda %2,3b-2b(%0)\n"
882 ".previous"
883 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
884 : "r"(va), "0"(0));
885 if (error)
886 goto give_sigsegv;
887 alpha_write_fp_reg(reg, tmp1|tmp2);
888 return;
889
890 case 0x28:
891 __asm__ __volatile__(
892 "1: ldq_u %1,0(%3)\n"
893 "2: ldq_u %2,3(%3)\n"
894 " extll %1,%3,%1\n"
895 " extlh %2,%3,%2\n"
896 "3:\n"
897 ".section __ex_table,\"a\"\n"
898 " .long 1b - .\n"
899 " lda %1,3b-1b(%0)\n"
900 " .long 2b - .\n"
901 " lda %2,3b-2b(%0)\n"
902 ".previous"
903 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
904 : "r"(va), "0"(0));
905 if (error)
906 goto give_sigsegv;
907 *reg_addr = (int)(tmp1|tmp2);
908 break;
909
910 case 0x29:
911 __asm__ __volatile__(
912 "1: ldq_u %1,0(%3)\n"
913 "2: ldq_u %2,7(%3)\n"
914 " extql %1,%3,%1\n"
915 " extqh %2,%3,%2\n"
916 "3:\n"
917 ".section __ex_table,\"a\"\n"
918 " .long 1b - .\n"
919 " lda %1,3b-1b(%0)\n"
920 " .long 2b - .\n"
921 " lda %2,3b-2b(%0)\n"
922 ".previous"
923 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
924 : "r"(va), "0"(0));
925 if (error)
926 goto give_sigsegv;
927 *reg_addr = tmp1|tmp2;
928 break;
929
930
931
932
933 case 0x0d:
934 __asm__ __volatile__(
935 "1: ldq_u %2,1(%5)\n"
936 "2: ldq_u %1,0(%5)\n"
937 " inswh %6,%5,%4\n"
938 " inswl %6,%5,%3\n"
939 " mskwh %2,%5,%2\n"
940 " mskwl %1,%5,%1\n"
941 " or %2,%4,%2\n"
942 " or %1,%3,%1\n"
943 "3: stq_u %2,1(%5)\n"
944 "4: stq_u %1,0(%5)\n"
945 "5:\n"
946 ".section __ex_table,\"a\"\n"
947 " .long 1b - .\n"
948 " lda %2,5b-1b(%0)\n"
949 " .long 2b - .\n"
950 " lda %1,5b-2b(%0)\n"
951 " .long 3b - .\n"
952 " lda $31,5b-3b(%0)\n"
953 " .long 4b - .\n"
954 " lda $31,5b-4b(%0)\n"
955 ".previous"
956 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
957 "=&r"(tmp3), "=&r"(tmp4)
958 : "r"(va), "r"(*reg_addr), "0"(0));
959 if (error)
960 goto give_sigsegv;
961 return;
962
963 case 0x26:
964 fake_reg = s_reg_to_mem(alpha_read_fp_reg(reg));
965
966
967 case 0x2c:
968 __asm__ __volatile__(
969 "1: ldq_u %2,3(%5)\n"
970 "2: ldq_u %1,0(%5)\n"
971 " inslh %6,%5,%4\n"
972 " insll %6,%5,%3\n"
973 " msklh %2,%5,%2\n"
974 " mskll %1,%5,%1\n"
975 " or %2,%4,%2\n"
976 " or %1,%3,%1\n"
977 "3: stq_u %2,3(%5)\n"
978 "4: stq_u %1,0(%5)\n"
979 "5:\n"
980 ".section __ex_table,\"a\"\n"
981 " .long 1b - .\n"
982 " lda %2,5b-1b(%0)\n"
983 " .long 2b - .\n"
984 " lda %1,5b-2b(%0)\n"
985 " .long 3b - .\n"
986 " lda $31,5b-3b(%0)\n"
987 " .long 4b - .\n"
988 " lda $31,5b-4b(%0)\n"
989 ".previous"
990 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
991 "=&r"(tmp3), "=&r"(tmp4)
992 : "r"(va), "r"(*reg_addr), "0"(0));
993 if (error)
994 goto give_sigsegv;
995 return;
996
997 case 0x27:
998 fake_reg = alpha_read_fp_reg(reg);
999
1000
1001 case 0x2d:
1002 __asm__ __volatile__(
1003 "1: ldq_u %2,7(%5)\n"
1004 "2: ldq_u %1,0(%5)\n"
1005 " insqh %6,%5,%4\n"
1006 " insql %6,%5,%3\n"
1007 " mskqh %2,%5,%2\n"
1008 " mskql %1,%5,%1\n"
1009 " or %2,%4,%2\n"
1010 " or %1,%3,%1\n"
1011 "3: stq_u %2,7(%5)\n"
1012 "4: stq_u %1,0(%5)\n"
1013 "5:\n"
1014 ".section __ex_table,\"a\"\n\t"
1015 " .long 1b - .\n"
1016 " lda %2,5b-1b(%0)\n"
1017 " .long 2b - .\n"
1018 " lda %1,5b-2b(%0)\n"
1019 " .long 3b - .\n"
1020 " lda $31,5b-3b(%0)\n"
1021 " .long 4b - .\n"
1022 " lda $31,5b-4b(%0)\n"
1023 ".previous"
1024 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
1025 "=&r"(tmp3), "=&r"(tmp4)
1026 : "r"(va), "r"(*reg_addr), "0"(0));
1027 if (error)
1028 goto give_sigsegv;
1029 return;
1030
1031 default:
1032
1033 goto give_sigbus;
1034 }
1035
1036
1037 if (reg == 30)
1038 wrusp(fake_reg);
1039 return;
1040
1041give_sigsegv:
1042 regs->pc -= 4;
1043 info.si_signo = SIGSEGV;
1044 info.si_errno = 0;
1045
1046
1047
1048
1049 if (!__access_ok((unsigned long)va, 0, USER_DS))
1050 info.si_code = SEGV_ACCERR;
1051 else {
1052 struct mm_struct *mm = current->mm;
1053 down_read(&mm->mmap_sem);
1054 if (find_vma(mm, (unsigned long)va))
1055 info.si_code = SEGV_ACCERR;
1056 else
1057 info.si_code = SEGV_MAPERR;
1058 up_read(&mm->mmap_sem);
1059 }
1060 info.si_addr = va;
1061 send_sig_info(SIGSEGV, &info, current);
1062 return;
1063
1064give_sigbus:
1065 regs->pc -= 4;
1066 info.si_signo = SIGBUS;
1067 info.si_errno = 0;
1068 info.si_code = BUS_ADRALN;
1069 info.si_addr = va;
1070 send_sig_info(SIGBUS, &info, current);
1071 return;
1072}
1073
1074void __init
1075trap_init(void)
1076{
1077
1078 register unsigned long gptr __asm__("$29");
1079 wrkgp(gptr);
1080
1081
1082
1083 if (implver() == IMPLVER_EV4)
1084 opDEC_check();
1085
1086 wrent(entArith, 1);
1087 wrent(entMM, 2);
1088 wrent(entIF, 3);
1089 wrent(entUna, 4);
1090 wrent(entSys, 5);
1091 wrent(entDbg, 6);
1092}
1093