patch-2.2.14 linux/arch/alpha/kernel/traps.c

Next file: linux/arch/alpha/math-emu/Makefile
Previous file: linux/arch/alpha/kernel/sys_takara.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.13/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
@@ -27,66 +27,270 @@
 {
 	printk("pc = [<%016lx>]  ra = [<%016lx>]  ps = %04lx\n",
 	       regs->pc, regs->r26, regs->ps);
-	printk("r0 = %016lx  r1 = %016lx  r2 = %016lx\n",
+	printk("v0 = %016lx  t0 = %016lx  t1 = %016lx\n",
 	       regs->r0, regs->r1, regs->r2);
-	printk("r3 = %016lx  r4 = %016lx  r5 = %016lx\n",
+	printk("t2 = %016lx  t3 = %016lx  t4 = %016lx\n",
  	       regs->r3, regs->r4, regs->r5);
-	printk("r6 = %016lx  r7 = %016lx  r8 = %016lx\n",
+	printk("t5 = %016lx  t6 = %016lx  t7 = %016lx\n",
 	       regs->r6, regs->r7, regs->r8);
 
 	if (r9_15) {
-		printk("r9 = %016lx  r10= %016lx  r11= %016lx\n",
+		printk("s0 = %016lx  s1 = %016lx  s2 = %016lx\n",
 		       r9_15[9], r9_15[10], r9_15[11]);
-		printk("r12= %016lx  r13= %016lx  r14= %016lx\n",
+		printk("s3 = %016lx  s4 = %016lx  s5 = %016lx\n",
 		       r9_15[12], r9_15[13], r9_15[14]);
-		printk("r15= %016lx\n", r9_15[15]);
+		printk("s6 = %016lx", r9_15[15]);
 	}
 
-	printk("r16= %016lx  r17= %016lx  r18= %016lx\n",
+	printk("  a0 = %016lx  a1 = %016lx\na2 = %016lx",
 	       regs->r16, regs->r17, regs->r18);
-	printk("r19= %016lx  r20= %016lx  r21= %016lx\n",
+	printk("  a3 = %016lx  a4 = %016lx\na5 = %016lx",
  	       regs->r19, regs->r20, regs->r21);
- 	printk("r22= %016lx  r23= %016lx  r24= %016lx\n",
+ 	printk("  t8 = %016lx  t9 = %016lx\nt10= %016lx",
 	       regs->r22, regs->r23, regs->r24);
-	printk("r25= %016lx  r27= %016lx  r28= %016lx\n",
+	printk("  t11= %016lx  pv = %016lx\nat = %016lx",
 	       regs->r25, regs->r27, regs->r28);
-	printk("gp = %016lx  sp = %p\n", regs->gp, regs+1);
+	printk("  gp = %016lx  sp = %p\n", regs->gp, regs+1);
+}
+
+static char * ireg_name[] = {"v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
+			   "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6",
+			   "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
+			   "t10", "t11", "ra", "pv", "at", "gp", "sp", "zero"};
+
+static char * inst_name[] = {"call_pal", "", "", "", "", "", "", "",
+	"lda", "ldah", "ldbu", "ldq_u", "ldwu", "stw", "stb", "stq_u",
+	"ALU", "ALU", "ALU", "ALU", "SQRT", "FVAX", "FIEEE", "FLOAT",
+	"MISC", "PAL19", "JMP", "PAL1B", "GRAPH", "PAL1D", "PAL1E", "PAL1F",
+	"ldf", "ldg", "lds", "ldt", "stf", "stg", "sts", "stt",
+	"ldl", "ldq", "ldl_l", "ldq_l", "stl", "stq", "stl_c", "stq_c",
+	"br", "fbeq", "fblt", "fble", "bsr", "fbne", "fbge", "fbgt"
+	"blbc", "beq", "blt", "ble", "blbs", "bne", "bge", "bgt"
+};
+
+static char * jump_name[] = {"jmp", "jsr", "ret", "jsr_coroutine"};
+
+typedef struct {int func; char * text;} alist;
+
+static alist inta_name[] = {{0, "addl"}, {2, "s4addl"}, {9, "subl"},
+	{0xb, "s4subl"}, {0xf, "cmpbge"}, {0x12, "s8addl"}, {0x1b, "s8subl"},
+	{0x1d, "cmpult"}, {0x20, "addq"}, {0x22, "s4addq"}, {0x29, "subq"},
+	{0x2b, "s4subq"}, {0x2d, "cmpeq"}, {0x32, "s8addq"}, {0x3b, "s8subq"},
+	{0x3d, "cmpule"}, {0x40, "addl/v"}, {0x49, "subl/v"}, {0x4d, "cmplt"},
+	{0x60, "addq/v"}, {0x69, "subq/v"}, {0x6d, "cmple"}, {-1, 0}};
+
+static alist intl_name[] = {{0, "and"}, {8, "andnot"}, {0x14, "cmovlbs"},
+	{0x16, "cmovlbc"}, {0x20, "or"}, {0x24, "cmoveq"}, {0x26, "cmovne"},
+	{0x28, "ornot"}, {0x40, "xor"}, {0x44, "cmovlt"}, {0x46, "cmovge"},
+	{0x48, "eqv"}, {0x61, "amask"}, {0x64, "cmovle"}, {0x66, "cmovgt"},
+	{0x6c, "implver"}, {-1, 0}};
+
+static alist ints_name[] = {{2, "mskbl"}, {6, "extbl"}, {0xb, "insbl"},
+	{0x12, "mskwl"}, {0x16, "extwl"}, {0x1b, "inswl"}, {0x22, "mskll"},
+	{0x26, "extll"}, {0x2b, "insll"}, {0x30, "zap"}, {0x31, "zapnot"},
+	{0x32, "mskql"}, {0x34, "srl"}, {0x36, "extql"}, {0x39, "sll"},
+	{0x3b, "insql"}, {0x3c, "sra"}, {0x52, "mskwh"}, {0x57, "inswh"},
+	{0x5a, "extwh"}, {0x62, "msklh"}, {0x67, "inslh"}, {0x6a, "extlh"},
+	{0x72, "mskqh"}, {0x77, "insqh"}, {0x7a, "extqh"}, {-1, 0}};
+
+static alist intm_name[] = {{0, "mull"}, {0x20, "mulq"}, {0x30, "umulh"},
+	{0x40, "mull/v"}, {0x60, "mulq/v"}, {-1, 0}};
+
+static alist * int_name[] = {inta_name, intl_name, ints_name, intm_name};
+
+static char *
+assoc(int fcode, alist * a)
+{
+	while ((fcode != a->func) && (a->func != -1))
+		++a;
+	return a->text;
+}
+
+static char *
+iname(unsigned int instr)
+{
+	int opcode = instr >> 26;
+	char * name = inst_name[opcode];
+
+	switch (opcode) {
+		default:
+			break;
+
+		case 0x10:
+		case 0x11:
+		case 0x12:
+		case 0x13: {
+			char * specific_name
+			  = assoc((instr >> 5) & 0x3f, int_name[opcode - 0x10]);
+			if (specific_name)
+				name = specific_name;
+			break;
+		}
+
+		case 0x1a:
+			name = jump_name[(instr >> 14) & 3];
+			break;
+	}
+	
+	return name;
+}
+
+static enum {NOT_INST, PAL, BRANCH, MEMORY, JUMP, OPERATE, FOPERATE, MISC}
+iformat(int opcode)
+{
+	if (opcode >= 0x30)
+		return BRANCH;
+	if (opcode >= 0x20)
+		return MEMORY;
+	if (opcode == 0)
+		return PAL;
+	if (opcode < 8)
+		return NOT_INST;
+	if (opcode < 0x10)
+		return MEMORY;
+	if (opcode < 0x14)
+		return OPERATE;
+	if (opcode < 0x18)
+		return FOPERATE;
+	switch (opcode) {
+		case 0x18:
+			return MISC;
+		case 0x1A:
+			return JUMP;
+		case 0x1C:
+			return OPERATE;
+		default:
+			return NOT_INST;
+	}
+}
+
+/*
+ * The purpose here is to provide useful clues about a kernel crash, so
+ * less likely instructions, e.g. floating point, aren't fully decoded.
+ */
+static void
+disassemble(unsigned int instr)
+{
+	int optype = instr >> 26;
+	char buf[40], *s = buf;
+
+	s += sprintf(buf, "%08x  %s ", instr, iname(instr));
+	switch (iformat(optype)) {
+		default:
+		case NOT_INST:
+		case MISC:
+			break;
+
+		case PAL:
+			s += sprintf(s, "%d", instr);
+			break;
+
+		case BRANCH: {
+			int reg = (instr >> 21) & 0x1f;
+			int offset = instr & 0x1fffff;
+
+			if (offset >= 0x100000)
+				offset -= 0x200000;
+			if (((optype & 3) == 0) || (optype >= 0x38)) {
+				if ((optype != 0x30) || (reg != 0x1f))
+					s += sprintf(s, "%s,", ireg_name[reg]);
+			} else
+				s += sprintf(s, "f%d,", reg);
+			s += sprintf(s, ".%+d", (offset + 1) << 2);
+			break;
+		}
+
+		case MEMORY: {
+			int addr_reg = (instr >> 16) & 0x1f;
+			int value_reg = (instr >> 21) & 0x1f;
+			int offset = instr & 0xffff;
+
+			if (offset >= 0x8000)
+				offset -= 0x10000;
+			if ((optype >= 0x20) && (optype < 0x28))
+				s += sprintf(s, "f%d", value_reg);
+			else
+				s += sprintf(s, "%s", ireg_name[value_reg]);
+
+			s += sprintf(s, ",%d(%s)", offset, ireg_name[addr_reg]);
+			break;
+		}
+
+		case JUMP: {
+			int target_reg = (instr >> 16) & 0x1f;
+			int return_reg = (instr >> 21) & 0x1f;
+
+			s += sprintf(s, "%s,", ireg_name[return_reg]);
+			s += sprintf(s, "(%s)", ireg_name[target_reg]);
+			break;
+		}
+
+		case OPERATE: {
+			int areg = (instr >> 21) & 0x1f;
+			int breg = (instr >> 16) & 0x1f;
+			int creg = instr & 0x1f;
+			int litflag = instr & (1<<12);
+			int lit = (instr >> 13) & 0xff;
+
+			s += sprintf(s, "%s,", ireg_name[areg]);
+			if (litflag)
+				s += sprintf(s, "%d", lit);
+			else
+				s += sprintf(s, "%s", ireg_name[breg]);
+			s += sprintf(s, ",%s", ireg_name[creg]);
+			break;
+		}
+
+		case FOPERATE: {
+			int areg = (instr >> 21) & 0x1f;
+			int breg = (instr >> 16) & 0x1f;
+			int creg = instr & 0x1f;
+
+			s += sprintf(s, "f%d,f%d,f%d", areg, breg, creg);
+			break;
+		}
+	}
+	buf[s-buf] = 0;
+	printk("%s\n", buf);
 }
 
 static void
 dik_show_code(unsigned int *pc)
 {
-	long i;
+	int i;
 
-	printk("Code:");
-	for (i = -3; i < 6; i++) {
+	printk("Code:\n");
+	for (i = -6; i < 2; i++) {
 		unsigned int insn;
 		if (__get_user(insn, pc+i))
 			break;
-		printk("%c%08x%c",i?' ':'<',insn,i?' ':'>');
+		printk("%c", i ? ' ' : '*');
+		disassemble(insn);
 	}
-	printk("\n");
 }
 
 static void
 dik_show_trace(unsigned long *sp)
 {
-	long i = 0;
-	printk("Trace:");
-	while (0x1ff8 & (unsigned long) sp) {
+	int i = 1;
+
+	printk("Trace: ");
+	do {
 		extern unsigned long _stext, _etext;
-		unsigned long tmp = *sp;
-		sp++;
-		if (tmp < (unsigned long) &_stext)
+		unsigned long kpc = *sp;
+
+		if (kpc < (unsigned long) &_stext)
 			continue;
-		if (tmp >= (unsigned long) &_etext)
+		if (kpc >= (unsigned long) &_etext)
 			continue;
-		printk(" [<%lx>]", tmp);
-		if (++i > 40) {
-			printk(" ...");
-			break;
-		}
-	}
+		/*
+		 * Assume that only the low 24-bits of a kernel text address
+		 * is interesting.
+		 */
+		printk("%6x%c", (int)kpc & 0xffffff, (++i % 11) ? ' ' : '\n');
+	} while (((unsigned long)++sp & 0x1ff8) && (i < 33));
+	if (i >= 33)
+		printk(" ...");
 	printk("\n");
 }
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)