VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / arch / parisc / kernel / traps.c
1 /*
2  *  linux/arch/parisc/traps.c
3  *
4  *  Copyright (C) 1991, 1992  Linus Torvalds
5  *  Copyright (C) 1999, 2000  Philipp Rumpf <prumpf@tux.org>
6  */
7
8 /*
9  * 'Traps.c' handles hardware traps and faults after we have saved some
10  * state in 'asm.s'.
11  */
12
13 #include <linux/config.h>
14 #include <linux/sched.h>
15 #include <linux/kernel.h>
16 #include <linux/string.h>
17 #include <linux/errno.h>
18 #include <linux/ptrace.h>
19 #include <linux/timer.h>
20 #include <linux/mm.h>
21 #include <linux/module.h>
22 #include <linux/smp.h>
23 #include <linux/smp_lock.h>
24 #include <linux/spinlock.h>
25 #include <linux/init.h>
26 #include <linux/interrupt.h>
27 #include <linux/console.h>
28 #include <linux/kallsyms.h>
29
30 #include <asm/assembly.h>
31 #include <asm/system.h>
32 #include <asm/uaccess.h>
33 #include <asm/io.h>
34 #include <asm/irq.h>
35 #include <asm/traps.h>
36 #include <asm/unaligned.h>
37 #include <asm/atomic.h>
38 #include <asm/smp.h>
39 #include <asm/pdc.h>
40 #include <asm/pdc_chassis.h>
41 #include <asm/unwind.h>
42
43 #include "../math-emu/math-emu.h"       /* for handle_fpe() */
44
45 #define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */
46                           /*  dumped to the console via printk)          */
47
48 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
49 spinlock_t pa_dbit_lock = SPIN_LOCK_UNLOCKED;
50 #endif
51
52 int printbinary(char *buf, unsigned long x, int nbits)
53 {
54         unsigned long mask = 1UL << (nbits - 1);
55         while (mask != 0) {
56                 *buf++ = (mask & x ? '1' : '0');
57                 mask >>= 1;
58         }
59         *buf = '\0';
60
61         return nbits;
62 }
63
64 #ifdef __LP64__
65 #define RFMT "%016lx"
66 #else
67 #define RFMT "%08lx"
68 #endif
69
70 void show_regs(struct pt_regs *regs)
71 {
72         int i;
73         char buf[128], *p;
74         char *level;
75         unsigned long cr30;
76         unsigned long cr31;
77
78         level = user_mode(regs) ? KERN_DEBUG : KERN_CRIT;
79
80         printk("%s\n", level); /* don't want to have that pretty register dump messed up */
81
82         printk("%s     YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n", level);
83         printbinary(buf, regs->gr[0], 32);
84         printk("%sPSW: %s %s\n", level, buf, print_tainted());
85
86         for (i = 0; i < 32; i += 4) {
87                 int j;
88                 p = buf;
89                 p += sprintf(p, "%sr%02d-%02d ", level, i, i + 3);
90                 for (j = 0; j < 4; j++) {
91                         p += sprintf(p, " " RFMT, (i+j) == 0 ? 0 : regs->gr[i + j]);
92                 }
93                 printk("%s\n", buf);
94         }
95
96         for (i = 0; i < 8; i += 4) {
97                 int j;
98                 p = buf;
99                 p += sprintf(p, "%ssr%d-%d  ", level, i, i + 3);
100                 for (j = 0; j < 4; j++) {
101                         p += sprintf(p, " " RFMT, regs->sr[i + j]);
102                 }
103                 printk("%s\n", buf);
104         }
105
106 #if RIDICULOUSLY_VERBOSE
107         for (i = 0; i < 32; i += 2)
108                 printk("%sFR%02d : %016lx  FR%2d : %016lx", level, i,
109                                 regs->fr[i], i+1, regs->fr[i+1]);
110 #endif
111
112         cr30 = mfctl(30);
113         cr31 = mfctl(31);
114         printk("%s\n", level);
115         printk("%sIASQ: " RFMT " " RFMT " IAOQ: " RFMT " " RFMT "\n",
116                level, regs->iasq[0], regs->iasq[1], regs->iaoq[0], regs->iaoq[1]);
117         printk("%s IIR: %08lx    ISR: " RFMT "  IOR: " RFMT "\n",
118                level, regs->iir, regs->isr, regs->ior);
119         printk("%s CPU: %8d   CR30: " RFMT " CR31: " RFMT "\n",
120                level, current_thread_info()->cpu, cr30, cr31);
121         printk("%s ORIG_R28: " RFMT "\n", level, regs->orig_r28);
122         printk(level);
123         print_symbol(" IAOQ[0]: %s\n", regs->iaoq[0]);
124         printk(level);
125         print_symbol(" IAOQ[1]: %s\n", regs->iaoq[1]);
126         printk(level);
127         print_symbol(" RP(r2): %s\n", regs->gr[2]);
128 }
129
130
131 void dump_stack(void)
132 {
133         show_stack(NULL, NULL);
134 }
135
136 EXPORT_SYMBOL(dump_stack);
137
138 void show_stack(struct task_struct *task, unsigned long *s)
139 {
140         int i = 1;
141         struct unwind_frame_info info;
142
143         if (!task) {
144                 unsigned long sp, ip, rp;
145
146 HERE:
147                 asm volatile ("copy %%r30, %0" : "=r"(sp));
148                 ip = (unsigned long)&&HERE;
149                 rp = (unsigned long)__builtin_return_address(0);
150                 unwind_frame_init(&info, current, sp, ip, rp);
151         } else {
152                 unwind_frame_init_from_blocked_task(&info, task);
153         }
154
155         printk("Backtrace:\n");
156         while (i <= 16) {
157                 if (unwind_once(&info) < 0 || info.ip == 0)
158                         break;
159
160                 if (__kernel_text_address(info.ip)) {
161                         printk(" [<" RFMT ">] ", info.ip);
162 #ifdef CONFIG_KALLSYMS
163                         print_symbol("%s\n", info.ip);
164 #else
165                         if ((i & 0x03) == 0)
166                                 printk("\n");
167 #endif
168                         i++;
169                 }
170         }
171         printk("\n");
172 }
173
174 void die_if_kernel(char *str, struct pt_regs *regs, long err)
175 {
176         if (user_mode(regs)) {
177                 if (err == 0)
178                         return; /* STFU */
179
180                 printk(KERN_CRIT "%s (pid %d): %s (code %ld) at " RFMT "\n",
181                         current->comm, current->pid, str, err, regs->iaoq[0]);
182 #ifdef PRINT_USER_FAULTS
183                 /* XXX for debugging only */
184                 show_regs(regs);
185 #endif
186                 return;
187         }
188
189         oops_in_progress = 1;
190
191         /* Amuse the user in a SPARC fashion */
192         printk(
193 "      _______________________________ \n"
194 "     < Your System ate a SPARC! Gah! >\n"
195 "      ------------------------------- \n"
196 "             \\   ^__^\n"
197 "              \\  (xx)\\_______\n"
198 "                 (__)\\       )\\/\\\n"
199 "                  U  ||----w |\n"
200 "                     ||     ||\n");
201         
202         /* unlock the pdc lock if necessary */
203         pdc_emergency_unlock();
204
205         /* maybe the kernel hasn't booted very far yet and hasn't been able 
206          * to initialize the serial or STI console. In that case we should 
207          * re-enable the pdc console, so that the user will be able to 
208          * identify the problem. */
209         if (!console_drivers)
210                 pdc_console_restart();
211         
212         printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n",
213                 current->comm, current->pid, str, err);
214         show_regs(regs);
215
216         /* Wot's wrong wif bein' racy? */
217         if (current->thread.flags & PARISC_KERNEL_DEATH) {
218                 printk(KERN_CRIT "%s() recursion detected.\n", __FUNCTION__);
219                 local_irq_enable();
220                 while (1);
221         }
222
223         current->thread.flags |= PARISC_KERNEL_DEATH;
224         do_exit(SIGSEGV);
225 }
226
227 int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs)
228 {
229         return syscall(regs);
230 }
231
232 /* gdb uses break 4,8 */
233 #define GDB_BREAK_INSN 0x10004
234 void handle_gdb_break(struct pt_regs *regs, int wot)
235 {
236         struct siginfo si;
237
238         si.si_code = wot;
239         si.si_addr = (void *) (regs->iaoq[0] & ~3);
240         si.si_signo = SIGTRAP;
241         si.si_errno = 0;
242         force_sig_info(SIGTRAP, &si, current);
243 }
244
245 void handle_break(unsigned iir, struct pt_regs *regs)
246 {
247         struct siginfo si;
248
249         switch(iir) {
250         case 0x00:
251 #ifdef PRINT_USER_FAULTS
252                 printk(KERN_DEBUG "break 0,0: pid=%d command='%s'\n",
253                        current->pid, current->comm);
254 #endif
255                 die_if_kernel("Breakpoint", regs, 0);
256 #ifdef PRINT_USER_FAULTS
257                 show_regs(regs);
258 #endif
259                 si.si_code = TRAP_BRKPT;
260                 si.si_addr = (void *) (regs->iaoq[0] & ~3);
261                 si.si_signo = SIGTRAP;
262                 force_sig_info(SIGTRAP, &si, current);
263                 break;
264
265         case GDB_BREAK_INSN:
266                 die_if_kernel("Breakpoint", regs, 0);
267                 handle_gdb_break(regs, TRAP_BRKPT);
268                 break;
269
270         default:
271 #ifdef PRINT_USER_FAULTS
272                 printk(KERN_DEBUG "break %#08x: pid=%d command='%s'\n",
273                        iir, current->pid, current->comm);
274                 show_regs(regs);
275 #endif
276                 si.si_signo = SIGTRAP;
277                 si.si_code = TRAP_BRKPT;
278                 si.si_addr = (void *) (regs->iaoq[0] & ~3);
279                 force_sig_info(SIGTRAP, &si, current);
280                 return;
281         }
282 }
283
284
285 int handle_toc(void)
286 {
287         printk(KERN_CRIT "TOC call.\n");
288         return 0;
289 }
290
291 static void default_trap(int code, struct pt_regs *regs)
292 {
293         printk(KERN_ERR "Trap %d on CPU %d\n", code, smp_processor_id());
294         show_regs(regs);
295 }
296
297 void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap;
298
299
300 void transfer_pim_to_trap_frame(struct pt_regs *regs)
301 {
302     register int i;
303     extern unsigned int hpmc_pim_data[];
304     struct pdc_hpmc_pim_11 *pim_narrow;
305     struct pdc_hpmc_pim_20 *pim_wide;
306
307     if (boot_cpu_data.cpu_type >= pcxu) {
308
309         pim_wide = (struct pdc_hpmc_pim_20 *)hpmc_pim_data;
310
311         /*
312          * Note: The following code will probably generate a
313          * bunch of truncation error warnings from the compiler.
314          * Could be handled with an ifdef, but perhaps there
315          * is a better way.
316          */
317
318         regs->gr[0] = pim_wide->cr[22];
319
320         for (i = 1; i < 32; i++)
321             regs->gr[i] = pim_wide->gr[i];
322
323         for (i = 0; i < 32; i++)
324             regs->fr[i] = pim_wide->fr[i];
325
326         for (i = 0; i < 8; i++)
327             regs->sr[i] = pim_wide->sr[i];
328
329         regs->iasq[0] = pim_wide->cr[17];
330         regs->iasq[1] = pim_wide->iasq_back;
331         regs->iaoq[0] = pim_wide->cr[18];
332         regs->iaoq[1] = pim_wide->iaoq_back;
333
334         regs->sar  = pim_wide->cr[11];
335         regs->iir  = pim_wide->cr[19];
336         regs->isr  = pim_wide->cr[20];
337         regs->ior  = pim_wide->cr[21];
338     }
339     else {
340         pim_narrow = (struct pdc_hpmc_pim_11 *)hpmc_pim_data;
341
342         regs->gr[0] = pim_narrow->cr[22];
343
344         for (i = 1; i < 32; i++)
345             regs->gr[i] = pim_narrow->gr[i];
346
347         for (i = 0; i < 32; i++)
348             regs->fr[i] = pim_narrow->fr[i];
349
350         for (i = 0; i < 8; i++)
351             regs->sr[i] = pim_narrow->sr[i];
352
353         regs->iasq[0] = pim_narrow->cr[17];
354         regs->iasq[1] = pim_narrow->iasq_back;
355         regs->iaoq[0] = pim_narrow->cr[18];
356         regs->iaoq[1] = pim_narrow->iaoq_back;
357
358         regs->sar  = pim_narrow->cr[11];
359         regs->iir  = pim_narrow->cr[19];
360         regs->isr  = pim_narrow->cr[20];
361         regs->ior  = pim_narrow->cr[21];
362     }
363
364     /*
365      * The following fields only have meaning if we came through
366      * another path. So just zero them here.
367      */
368
369     regs->ksp = 0;
370     regs->kpc = 0;
371     regs->orig_r28 = 0;
372 }
373
374
375 /*
376  * This routine handles page faults.  It determines the address,
377  * and the problem, and then passes it off to one of the appropriate
378  * routines.
379  */
380 void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset)
381 {
382         static spinlock_t terminate_lock = SPIN_LOCK_UNLOCKED;
383
384         oops_in_progress = 1;
385
386         set_eiem(0);
387         local_irq_disable();
388         spin_lock(&terminate_lock);
389
390         /* unlock the pdc lock if necessary */
391         pdc_emergency_unlock();
392
393         /* restart pdc console if necessary */
394         if (!console_drivers)
395                 pdc_console_restart();
396
397         /* Not all paths will gutter the processor... */
398         switch(code){
399
400         case 1:
401                 transfer_pim_to_trap_frame(regs);
402                 break;
403
404         default:
405                 /* Fall through */
406                 break;
407
408         }
409             
410         show_stack(NULL, (unsigned long *)regs->gr[30]);
411
412         printk("\n");
413         printk(KERN_CRIT "%s: Code=%d regs=%p (Addr=" RFMT ")\n",
414                         msg, code, regs, offset);
415         show_regs(regs);
416
417         spin_unlock(&terminate_lock);
418
419         /* put soft power button back under hardware control;
420          * if the user had pressed it once at any time, the 
421          * system will shut down immediately right here. */
422         pdc_soft_power_button(0);
423         
424         /* Gutter the processor! */
425         for(;;)
426             ;
427 }
428
429 void handle_interruption(int code, struct pt_regs *regs)
430 {
431         unsigned long fault_address = 0;
432         unsigned long fault_space = 0;
433         struct siginfo si;
434
435         if (code == 1)
436             pdc_console_restart();  /* switch back to pdc if HPMC */
437         else
438             local_irq_enable();
439
440 #if 0
441         printk(KERN_CRIT "Interruption # %d\n", code);
442 #endif
443
444         switch(code) {
445
446         case  1:
447                 /* High-priority machine check (HPMC) */
448                 
449                 /* set up a new led state on systems shipped with a LED State panel */
450                 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_HPMC);
451                     
452                 parisc_terminate("High Priority Machine Check (HPMC)",
453                                 regs, code, 0);
454                 /* NOT REACHED */
455                 
456         case  2:
457                 /* Power failure interrupt */
458                 printk(KERN_CRIT "Power failure interrupt !\n");
459                 return;
460
461         case  3:
462                 /* Recovery counter trap */
463                 regs->gr[0] &= ~PSW_R;
464                 if (regs->iasq[0])
465                         handle_gdb_break(regs, TRAP_TRACE);
466                 /* else this must be the start of a syscall - just let it run */
467                 return;
468
469         case  5:
470                 /* Low-priority machine check */
471                 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_LPMC);
472                 
473                 flush_all_caches();
474                 cpu_lpmc(5, regs);
475                 return;
476
477         case  6:
478                 /* Instruction TLB miss fault/Instruction page fault */
479                 fault_address = regs->iaoq[0];
480                 fault_space   = regs->iasq[0];
481                 break;
482
483         case  8:
484                 /* Illegal instruction trap */
485                 die_if_kernel("Illegal instruction", regs, code);
486                 si.si_code = ILL_ILLOPC;
487                 goto give_sigill;
488
489         case  9:
490                 /* Break instruction trap */
491                 handle_break(regs->iir,regs);
492                 return;
493         
494         case 10:
495                 /* Privileged operation trap */
496                 die_if_kernel("Privileged operation", regs, code);
497                 si.si_code = ILL_PRVOPC;
498                 goto give_sigill;
499         
500         case 11:
501                 /* Privileged register trap */
502                 if ((regs->iir & 0xffdfffe0) == 0x034008a0) {
503
504                         /* This is a MFCTL cr26/cr27 to gr instruction.
505                          * PCXS traps on this, so we need to emulate it.
506                          */
507
508                         if (regs->iir & 0x00200000)
509                                 regs->gr[regs->iir & 0x1f] = mfctl(27);
510                         else
511                                 regs->gr[regs->iir & 0x1f] = mfctl(26);
512
513                         regs->iaoq[0] = regs->iaoq[1];
514                         regs->iaoq[1] += 4;
515                         regs->iasq[0] = regs->iasq[1];
516                         return;
517                 }
518
519                 die_if_kernel("Privileged register usage", regs, code);
520                 si.si_code = ILL_PRVREG;
521         give_sigill:
522                 si.si_signo = SIGILL;
523                 si.si_errno = 0;
524                 si.si_addr = (void *) regs->iaoq[0];
525                 force_sig_info(SIGILL, &si, current);
526                 return;
527
528         case 12:
529                 /* Overflow Trap, let the userland signal handler do the cleanup */
530                 si.si_signo = SIGFPE;
531                 si.si_code = FPE_INTOVF;
532                 si.si_addr = (void *) regs->iaoq[0];
533                 force_sig_info(SIGFPE, &si, current);
534                 return;
535                 
536         case 13:
537                 /* Conditional Trap
538                    The condition succees in an instruction which traps 
539                    on condition  */
540                 if(user_mode(regs)){
541                         si.si_signo = SIGFPE;
542                         /* Set to zero, and let the userspace app figure it out from
543                            the insn pointed to by si_addr */
544                         si.si_code = 0;
545                         si.si_addr = (void *) regs->iaoq[0];
546                         force_sig_info(SIGFPE, &si, current);
547                         return;
548                 } else 
549                         /* The kernel doesn't want to handle condition codes */
550                         break;
551                 
552         case 14:
553                 /* Assist Exception Trap, i.e. floating point exception. */
554                 die_if_kernel("Floating point exception", regs, 0); /* quiet */
555                 handle_fpe(regs);
556                 return;
557                 
558         case 15:
559                 /* Data TLB miss fault/Data page fault */
560                 /* Fall through */
561         case 16:
562                 /* Non-access instruction TLB miss fault */
563                 /* The instruction TLB entry needed for the target address of the FIC
564                    is absent, and hardware can't find it, so we get to cleanup */
565                 /* Fall through */
566         case 17:
567                 /* Non-access data TLB miss fault/Non-access data page fault */
568                 /* TODO: Still need to add slow path emulation code here */
569                 /* TODO: Understand what is meant by the TODO listed
570                          above this one. (Carlos) */
571                 fault_address = regs->ior;
572                 fault_space = regs->isr;
573                 break;
574
575         case 18:
576                 /* PCXS only -- later cpu's split this into types 26,27 & 28 */
577                 /* Check for unaligned access */
578                 if (check_unaligned(regs)) {
579                         handle_unaligned(regs);
580                         return;
581                 }
582                 /* Fall Through */
583         case 26: 
584                 /* PCXL: Data memory access rights trap */
585                 fault_address = regs->ior;
586                 fault_space   = regs->isr;
587                 break;
588
589         case 19:
590                 /* Data memory break trap */
591                 regs->gr[0] |= PSW_X; /* So we can single-step over the trap */
592                 /* fall thru */
593         case 21:
594                 /* Page reference trap */
595                 handle_gdb_break(regs, TRAP_HWBKPT);
596                 return;
597
598         case 25:
599                 /* Taken branch trap */
600                 regs->gr[0] &= ~PSW_T;
601                 if (regs->iasq[0])
602                         handle_gdb_break(regs, TRAP_BRANCH);
603                 /* else this must be the start of a syscall - just let it
604                  * run.
605                  */
606                 return;
607
608         case  7:  
609                 /* Instruction access rights */
610                 /* PCXL: Instruction memory protection trap */
611
612                 /*
613                  * This could be caused by either: 1) a process attempting
614                  * to execute within a vma that does not have execute
615                  * permission, or 2) an access rights violation caused by a
616                  * flush only translation set up by ptep_get_and_clear().
617                  * So we check the vma permissions to differentiate the two.
618                  * If the vma indicates we have execute permission, then
619                  * the cause is the latter one. In this case, we need to
620                  * call do_page_fault() to fix the problem.
621                  */
622
623                 if (user_mode(regs)) {
624                         struct vm_area_struct *vma;
625
626                         down_read(&current->mm->mmap_sem);
627                         vma = find_vma(current->mm,regs->iaoq[0]);
628                         if (vma && (regs->iaoq[0] >= vma->vm_start)
629                                 && (vma->vm_flags & VM_EXEC)) {
630
631                                 fault_address = regs->iaoq[0];
632                                 fault_space = regs->iasq[0];
633
634                                 up_read(&current->mm->mmap_sem);
635                                 break; /* call do_page_fault() */
636                         }
637                         up_read(&current->mm->mmap_sem);
638                 }
639                 /* Fall Through */
640         case 27: 
641                 /* Data memory protection ID trap */
642                 die_if_kernel("Protection id trap", regs, code);
643                 si.si_code = SEGV_MAPERR;
644                 si.si_signo = SIGSEGV;
645                 si.si_errno = 0;
646                 if (code == 7)
647                     si.si_addr = (void *) regs->iaoq[0];
648                 else
649                     si.si_addr = (void *) regs->ior;
650                 force_sig_info(SIGSEGV, &si, current);
651                 return;
652
653         case 28: 
654                 /* Unaligned data reference trap */
655                 handle_unaligned(regs);
656                 return;
657
658         default:
659                 if (user_mode(regs)) {
660 #ifdef PRINT_USER_FAULTS
661                         printk(KERN_DEBUG "\nhandle_interruption() pid=%d command='%s'\n",
662                             current->pid, current->comm);
663                         show_regs(regs);
664 #endif
665                         /* SIGBUS, for lack of a better one. */
666                         si.si_signo = SIGBUS;
667                         si.si_code = BUS_OBJERR;
668                         si.si_errno = 0;
669                         si.si_addr = (void *) regs->ior;
670                         force_sig_info(SIGBUS, &si, current);
671                         return;
672                 }
673                 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
674                 
675                 parisc_terminate("Unexpected interruption", regs, code, 0);
676                 /* NOT REACHED */
677         }
678
679         if (user_mode(regs)) {
680             if ((fault_space>>SPACEID_SHIFT) != (regs->sr[7] >> SPACEID_SHIFT)) {
681 #ifdef PRINT_USER_FAULTS
682                 if (fault_space == 0)
683                         printk(KERN_DEBUG "User Fault on Kernel Space ");
684                 else
685                         printk(KERN_DEBUG "User Fault (long pointer) (fault %d) ",
686                                code);
687                 printk("pid=%d command='%s'\n", current->pid, current->comm);
688                 show_regs(regs);
689 #endif
690                 si.si_signo = SIGSEGV;
691                 si.si_errno = 0;
692                 si.si_code = SEGV_MAPERR;
693                 si.si_addr = (void *) regs->ior;
694                 force_sig_info(SIGSEGV, &si, current);
695                 return;
696             }
697         }
698         else {
699
700             /*
701              * The kernel should never fault on its own address space.
702              */
703
704             if (fault_space == 0) 
705             {
706                 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
707                 parisc_terminate("Kernel Fault", regs, code, fault_address);
708         
709             }
710         }
711
712         do_page_fault(regs, code, fault_address);
713 }
714
715
716 int __init check_ivt(void *iva)
717 {
718         int i;
719         u32 check = 0;
720         u32 *ivap;
721         u32 *hpmcp;
722         u32 length;
723         extern void os_hpmc(void);
724         extern void os_hpmc_end(void);
725
726         if (strcmp((char *)iva, "cows can fly"))
727                 return -1;
728
729         ivap = (u32 *)iva;
730
731         for (i = 0; i < 8; i++)
732             *ivap++ = 0;
733
734         /* Compute Checksum for HPMC handler */
735
736         length = (u32)((unsigned long)os_hpmc_end - (unsigned long)os_hpmc);
737         ivap[7] = length;
738
739         hpmcp = (u32 *)os_hpmc;
740
741         for (i=0; i<length/4; i++)
742             check += *hpmcp++;
743
744         for (i=0; i<8; i++)
745             check += ivap[i];
746
747         ivap[5] = -check;
748
749         return 0;
750 }
751         
752 #ifndef __LP64__
753 extern const void fault_vector_11;
754 #endif
755 extern const void fault_vector_20;
756
757 void __init trap_init(void)
758 {
759         void *iva;
760
761         if (boot_cpu_data.cpu_type >= pcxu)
762                 iva = (void *) &fault_vector_20;
763         else
764 #ifdef __LP64__
765                 panic("Can't boot 64-bit OS on PA1.1 processor!");
766 #else
767                 iva = (void *) &fault_vector_11;
768 #endif
769
770         if (check_ivt(iva))
771                 panic("IVT invalid");
772 }