[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(&current->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--