[parisc-linux-cvs] linux deller
Helge Deller
deller@gmx.de
Sun, 6 Jan 2002 18:35:50 +0100
--------------Boundary-00=_Q72JVATHERHRP34J0E6L
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 8bit
On Sunday 06 January 2002 18:35, Helge Deller wrote:
> CVSROOT: /var/cvs
> Module name: linux
> Changes by: deller 02/01/06 10:35:10
>
> Modified files:
> arch/parisc/kernel: traps.c
> . : Makefile
>
> Log message:
> - 2.4.17-pa4
> - Changes in traps.c to get the real crash-dump of the c3k-STI-PCI problem,
> - added lots of comments to traps.c
>
> AFAIT the main problem with the old crash handler was that it crashed with
> a trap 15 inside the crash handler (during dumping a HPMC) while trying to
> print a stack-dump. This only happens if a PDC call (or as it happened for
> me in the copied STI ROM) crashed and where the stack-pointer was invalid
> from the sight of the linux kernel.
> So the main change in this patch is to dump_stack(__va(stack_start),
> __va(sp), 0) instead of dump_stack(stack_start, sp, 0) in case the Stack
> pointer and cr30 don't correspond. Maybe someone of you with better
> knowledge about the trap handler wants to comment ?
--------------Boundary-00=_Q72JVATHERHRP34J0E6L
Content-Type: text/plain;
charset="iso-8859-1";
name="diff"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="diff"
Index: arch/parisc/kernel/traps.c
===================================================================
RCS file: /var/cvs/linux/arch/parisc/kernel/traps.c,v
retrieving revision 1.60
diff -u -p -r1.60 traps.c
--- arch/parisc/kernel/traps.c 2001/12/26 22:43:43 1.60
+++ arch/parisc/kernel/traps.c 2002/01/06 17:26:24
@@ -129,18 +129,18 @@ static void dump_stack(unsigned long fro
fromptr = (unsigned int *)from;
toptr = (unsigned int *)to;
- if (istackflag)
- printk("\nDumping Interrupt Stack from %p to %p:\n",fromptr,toptr);
- else
- printk("\nDumping Stack from %p to %p:\n",fromptr,toptr);
+ printk("\n");
+ printk(KERN_CRIT "Dumping %sStack from 0x%p to 0x%p:\n",
+ istackflag ? "Interrupt " : "",
+ fromptr, toptr);
+
while (fromptr < toptr) {
- printk("%04lx %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ printk(KERN_CRIT "%04lx %08x %08x %08x %08x %08x %08x %08x %08x\n",
((unsigned long)fromptr) & 0xffff,
fromptr[0], fromptr[1], fromptr[2], fromptr[3],
fromptr[4], fromptr[5], fromptr[6], fromptr[7]);
fromptr += 8;
}
- return;
}
@@ -170,11 +170,15 @@ void show_stack(struct pt_regs *regs)
int_regs = (struct pt_regs *)cr31;
sp = int_regs->gr[30];
stack_start = sp & ~(INIT_TASK_SIZE - 1);
- if (stack_start != cr30)
- printk(KERN_CRIT "WARNING! Stack pointer and cr30 do not correspond!\n");
- dump_stack(stack_start, sp, 0);
+ if (stack_start != cr30) {
+ printk(KERN_CRIT "WARNING! Interrupt-Stack pointer and cr30 do not correspond!\n");
+ printk(KERN_CRIT "Dumping virtual address stack instead\n");
+ dump_stack(__va(stack_start), __va(sp), 0);
+ } else {
+ dump_stack(stack_start, sp, 0);
+ };
- printk("\n\nRegisters at Interrupt:\n");
+ printk("\n\n" KERN_DEBUG "Registers at Interrupt:\n");
show_regs(int_regs);
/* Now dump the interrupt stack */
@@ -187,7 +191,8 @@ void show_stack(struct pt_regs *regs)
{
/* Stack Dump! */
printk(KERN_CRIT "WARNING! Stack pointer and cr30 do not correspond!\n");
- dump_stack(stack_start, sp, 0);
+ printk(KERN_CRIT "Dumping virtual address stack instead\n");
+ dump_stack(__va(stack_start), __va(sp), 0);
}
}
#endif
@@ -208,6 +213,9 @@ void die_if_kernel(char *str, struct pt_
#endif
return;
}
+
+ /* unlock the pdc lock if necessary */
+ pdc_emergency_unlock();
/* maybe the kernel hasn't booted very far yet and hasn't been able
* to initialize the serial or STI console. In that case we should
@@ -330,7 +338,7 @@ void (*cpu_lpmc) (int code, struct pt_re
#ifdef CONFIG_KWDB
int debug_call (void)
{
- printk ("Debug call.\n");
+ printk (KERN_DEBUG "Debug call.\n");
return 0;
}
@@ -427,9 +435,11 @@ void parisc_terminate(char *msg, struct
set_eiem(0);
__cli();
-
spin_lock(&terminate_lock);
+ /* unlock the pdc lock if necessary */
+ pdc_emergency_unlock();
+
/* restart pdc console if necessary */
if (!console_drivers)
pdc_console_restart();
@@ -439,7 +449,9 @@ void parisc_terminate(char *msg, struct
show_stack(regs);
- printk("\n%s: Code=%d regs=%p (Addr=" RFMT ")\n", msg,code,regs,offset);
+ printk("\n");
+ printk(KERN_CRIT "%s: Code=%d regs=%p (Addr=" RFMT ")\n",
+ msg, code, regs, offset);
show_regs(regs);
spin_unlock(&terminate_lock);
@@ -465,37 +477,87 @@ void handle_interruption(int code, struc
else
sti();
+#if 0
+ printk(KERN_CRIT "Interruption # %d\n", code);
+#endif
+
switch(code) {
+
case 1:
- parisc_terminate("High Priority Machine Check (HPMC)",regs,code,0);
+ /* High-priority machine check (HPMC) */
+ parisc_terminate("High Priority Machine Check (HPMC)",
+ regs, code, 0);
/* NOT REACHED */
- case 2: /* power failure interrupt */
+ case 2:
+ /* Power failure interrupt */
printk(KERN_CRIT "Power failure interrupt !\n");
return;
- case 3: /* Recovery counter trap */
+ case 3:
+ /* Recovery counter trap */
regs->gr[0] &= ~PSW_R;
if (regs->iasq[0])
handle_gdb_break(regs, TRAP_TRACE);
- /* else this must be the start of a syscall - just let it
- * run.
- */
+ /* else this must be the start of a syscall - just let it run */
return;
case 5:
+ /* Low-priority machine check */
flush_all_caches();
cpu_lpmc(5, regs);
return;
case 6:
+ /* Instruction TLB miss fault/Instruction page fault */
fault_address = regs->iaoq[0];
fault_space = regs->iasq[0];
break;
- case 9: /* Break Instruction */
+ case 8:
+ /* Illegal instruction trap */
+ die_if_kernel("Illegal instruction", regs, code);
+ si.si_code = ILL_ILLOPC;
+ goto give_sigill;
+
+ case 9:
+ /* Break instruction trap */
handle_break(regs->iir,regs);
return;
+
+ case 10:
+ /* Privileged operation trap */
+ die_if_kernel("Privileged operation", regs, code);
+ si.si_code = ILL_PRVOPC;
+ goto give_sigill;
+
+ case 11:
+ /* Privileged register trap */
+ if ((regs->iir & 0xffdfffe0) == 0x034008a0) {
+
+ /* This is a MFCTL cr26/cr27 to gr instruction.
+ * PCXS traps on this, so we need to emulate it.
+ */
+
+ if (regs->iir & 0x00200000)
+ regs->gr[regs->iir & 0x1f] = mfctl(27);
+ else
+ regs->gr[regs->iir & 0x1f] = mfctl(26);
+
+ regs->iaoq[0] = regs->iaoq[1];
+ regs->iaoq[1] += 4;
+ regs->iasq[0] = regs->iasq[1];
+ return;
+ }
+
+ die_if_kernel("Privileged register usage", regs, code);
+ si.si_code = ILL_PRVREG;
+ give_sigill:
+ si.si_signo = SIGILL;
+ si.si_errno = 0;
+ si.si_addr = (void *) regs->iaoq[0];
+ force_sig_info(SIGILL, &si, current);
+ return;
case 14:
/* Assist Exception Trap, i.e. floating point exception. */
@@ -504,38 +566,38 @@ void handle_interruption(int code, struc
return;
case 17:
+ /* Non-access data TLB miss fault/Non-access data page fault */
/* TODO: Still need to add slow path emulation code here */
-
fault_address = regs->ior;
parisc_terminate("Non access data tlb fault!",regs,code,fault_address);
case 18:
/* PCXS only -- later cpu's split this into types 26,27 & 28 */
-
/* Check for unaligned access */
-
if (check_unaligned(regs)) {
handle_unaligned(regs);
return;
}
-
/* Fall Through */
- case 15:
- case 26:
- /* PCXL: data memory access rights trap */
+ case 15: /* Data TLB miss fault/Data page fault */
+ case 26: /* PCXL: Data memory access rights trap */
fault_address = regs->ior;
fault_space = regs->isr;
break;
case 19:
+ /* Data memory break trap */
regs->gr[0] |= PSW_X; /* So we can single-step over the trap */
/* fall thru */
case 21:
+ /* Page reference trap */
handle_gdb_break(regs, TRAP_HWBKPT);
return;
- case 25: /* Taken branch trap */
+ case 25:
+ /* Taken branch trap */
+#ifndef CONFIG_KWDB
regs->gr[0] &= ~PSW_T;
if (regs->iasq[0])
handle_gdb_break(regs, TRAP_BRANCH);
@@ -543,53 +605,18 @@ void handle_interruption(int code, struc
* run.
*/
return;
-
-#if 0 /* def CONFIG_KWDB */
- case I_TAKEN_BR: /* 25 */
+#else
+ /* Kernel debugger: */
mtctl(0, 15);
pt_regs_to_ssp(regs, &ssp);
kgdb_trap(I_TAKEN_BR, &ssp, 1);
ssp_to_pt_regs(&ssp, regs);
break;
#endif /* CONFIG_KWDB */
-
- case 8:
- die_if_kernel("Illegal instruction", regs, code);
- si.si_code = ILL_ILLOPC;
- goto give_sigill;
-
- case 10:
- die_if_kernel("Privileged operation", regs, code);
- si.si_code = ILL_PRVOPC;
- goto give_sigill;
- case 11:
- if ((regs->iir & 0xffdfffe0) == 0x034008a0) {
-
- /* This is a MFCTL cr26/cr27 to gr instruction.
- * PCXS traps on this, so we need to emulate it.
- */
-
- if (regs->iir & 0x00200000)
- regs->gr[regs->iir & 0x1f] = mfctl(27);
- else
- regs->gr[regs->iir & 0x1f] = mfctl(26);
-
- regs->iaoq[0] = regs->iaoq[1];
- regs->iaoq[1] += 4;
- regs->iasq[0] = regs->iasq[1];
- return;
- }
-
- die_if_kernel("Privileged register usage", regs, code);
- si.si_code = ILL_PRVREG;
- give_sigill:
- si.si_signo = SIGILL;
- si.si_errno = 0;
- si.si_addr = (void *) regs->iaoq[0];
- force_sig_info(SIGILL, &si, current);
- return;
- case 7: /* I access rights or I protection Id trap */
+ case 7:
+ /* Instruction access rights */
+ /* PCXL: Instruction memory protection trap */
/*
* This could be caused by either: 1) a process attempting
@@ -618,10 +645,10 @@ void handle_interruption(int code, struc
}
up_read(¤t->mm->mmap_sem);
}
-
/* Fall Through */
- case 27: /* data memory protection ID trap */
+ case 27:
+ /* Data memory protection ID trap */
die_if_kernel("Protection id trap", regs, code);
si.si_code = SEGV_MAPERR;
si.si_signo = SIGSEGV;
@@ -633,17 +660,9 @@ void handle_interruption(int code, struc
force_sig_info(SIGSEGV, &si, current);
return;
- case 28: /* unaligned data reference trap */
- /* just causes SIGBUS for now */
+ case 28:
+ /* Unaligned data reference trap */
handle_unaligned(regs);
-#if 0
- die_if_kernel("Unaligned data reference", regs, code);
- si.si_code = BUS_ADRALN;
- si.si_signo = SIGBUS;
- si.si_errno = 0;
- si.si_addr = (void *) regs->ior;
- force_sig_info(SIGBUS, &si, current);
-#endif
return;
default:
@@ -698,8 +717,6 @@ void handle_interruption(int code, struc
#endif /* CONFIG_KWDB */
do_page_fault(regs, code, fault_address);
-
- return;
}
--------------Boundary-00=_Q72JVATHERHRP34J0E6L--