summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgonzo <gonzo@FreeBSD.org>2012-01-13 23:31:36 +0000
committergonzo <gonzo@FreeBSD.org>2012-01-13 23:31:36 +0000
commita97c56fa2ab8649a7f6695df50ab3c6cc735d54f (patch)
tree7b5c0b0bb30d679d8bec1a9941424f354184091f
parentb07aec8b25cb766e3da445ecc6e63257a63efa00 (diff)
downloadFreeBSD-src-a97c56fa2ab8649a7f6695df50ab3c6cc735d54f.zip
FreeBSD-src-a97c56fa2ab8649a7f6695df50ab3c6cc735d54f.tar.gz
Fix backtrace for MIPS64:
- Properly print 64-bit addresses - Get whole 64 bits of address using kdbpeekd - Make check for kernel address compatible with MIPS64
-rw-r--r--sys/mips/include/db_machdep.h3
-rw-r--r--sys/mips/mips/db_trace.c31
-rw-r--r--sys/mips/mips/support.S19
3 files changed, 38 insertions, 15 deletions
diff --git a/sys/mips/include/db_machdep.h b/sys/mips/include/db_machdep.h
index 657e303..a495955 100644
--- a/sys/mips/include/db_machdep.h
+++ b/sys/mips/include/db_machdep.h
@@ -93,6 +93,7 @@ db_addr_t next_instr_address(db_addr_t, boolean_t);
int db_inst_type(int);
db_addr_t branch_taken(int inst, db_addr_t pc);
void stacktrace_subr(register_t pc, register_t sp, register_t ra, int (*)(const char *, ...));
-int kdbpeek(int *);
+int32_t kdbpeek(int *);
+int64_t kdbpeekd(int *);
#endif /* !_MIPS_DB_MACHDEP_H_ */
diff --git a/sys/mips/mips/db_trace.c b/sys/mips/mips/db_trace.c
index ebb9e1b..062ad30 100644
--- a/sys/mips/mips/db_trace.c
+++ b/sys/mips/mips/db_trace.c
@@ -49,10 +49,13 @@ extern char edata[];
*/
#define MIPS_END_OF_FUNCTION(ins) ((ins) == 0x03e00008)
-/*
- * kdbpeekD(addr) - skip one word starting at 'addr', then read the second word
- */
-#define kdbpeekD(addr) kdbpeek(((int *)(addr)) + 1)
+#if defined(__mips_n64)
+# define MIPS_IS_VALID_KERNELADDR(reg) ((((reg) & 3) == 0) && \
+ ((vm_offset_t)(reg) >= MIPS_XKPHYS_START))
+#else
+# define MIPS_IS_VALID_KERNELADDR(reg) ((((reg) & 3) == 0) && \
+ ((vm_offset_t)(reg) >= MIPS_KSEG0_START))
+#endif
/*
* Functions ``special'' enough to print by name
@@ -141,8 +144,8 @@ loop:
}
/* check for bad SP: could foul up next frame */
/*XXX MIPS64 bad: this hard-coded SP is lame */
- if (sp & 3 || (uintptr_t)sp < 0x80000000u) {
- (*printfn) ("SP 0x%x: not in kernel\n", sp);
+ if (!MIPS_IS_VALID_KERNELADDR(sp)) {
+ (*printfn) ("SP 0x%jx: not in kernel\n", sp);
ra = 0;
subr = 0;
goto done;
@@ -182,8 +185,8 @@ loop:
}
/* check for bad PC */
/*XXX MIPS64 bad: These hard coded constants are lame */
- if (pc & 3 || pc < (uintptr_t)0x80000000) {
- (*printfn) ("PC 0x%x: not in kernel\n", pc);
+ if (!MIPS_IS_VALID_KERNELADDR(pc)) {
+ (*printfn) ("PC 0x%jx: not in kernel\n", pc);
ra = 0;
goto done;
}
@@ -304,27 +307,27 @@ loop:
mask |= (1 << i.IType.rt);
switch (i.IType.rt) {
case 4:/* a0 */
- args[0] = kdbpeekD((int *)(sp + (short)i.IType.imm));
+ args[0] = kdbpeekd((int *)(sp + (short)i.IType.imm));
valid_args[0] = 1;
break;
case 5:/* a1 */
- args[1] = kdbpeekD((int *)(sp + (short)i.IType.imm));
+ args[1] = kdbpeekd((int *)(sp + (short)i.IType.imm));
valid_args[1] = 1;
break;
case 6:/* a2 */
- args[2] = kdbpeekD((int *)(sp + (short)i.IType.imm));
+ args[2] = kdbpeekd((int *)(sp + (short)i.IType.imm));
valid_args[2] = 1;
break;
case 7:/* a3 */
- args[3] = kdbpeekD((int *)(sp + (short)i.IType.imm));
+ args[3] = kdbpeekd((int *)(sp + (short)i.IType.imm));
valid_args[3] = 1;
break;
case 31: /* ra */
- ra = kdbpeekD((int *)(sp + (short)i.IType.imm));
+ ra = kdbpeekd((int *)(sp + (short)i.IType.imm));
}
break;
@@ -350,7 +353,7 @@ done:
(*printfn)("?");
}
- (*printfn) (") ra %x sp %x sz %d\n", ra, sp, stksize);
+ (*printfn) (") ra %jx sp %jx sz %d\n", ra, sp, stksize);
if (ra) {
if (pc == ra && stksize == 0)
diff --git a/sys/mips/mips/support.S b/sys/mips/mips/support.S
index 6623d0a..9173f49 100644
--- a/sys/mips/mips/support.S
+++ b/sys/mips/mips/support.S
@@ -1340,6 +1340,25 @@ LEAF(kdbpeek)
PTR_S zero, U_PCB_ONFAULT(t1)
END(kdbpeek)
+LEAF(kdbpeekd)
+ PTR_LA v1, ddberr
+ and v0, a0, 3 # unaligned ?
+ GET_CPU_PCPU(t1)
+ PTR_L t1, PC_CURPCB(t1)
+ bne v0, zero, 1f
+ PTR_S v1, U_PCB_ONFAULT(t1)
+
+ ld v0, (a0)
+ jr ra
+ PTR_S zero, U_PCB_ONFAULT(t1)
+
+1:
+ REG_LHI v0, 0(a0)
+ REG_LLO v0, 7(a0)
+ jr ra
+ PTR_S zero, U_PCB_ONFAULT(t1)
+END(kdbpeekd)
+
ddberr:
jr ra
nop
OpenPOWER on IntegriCloud