[PATCH] stacktrace build-fix and improvement

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Fix build error due to stacktrace API change.  Now save_stack_trace()
tries to save all kernel context, including interrupts and exception.
Also some asm code are changed a bit so that we can detect the end of
current context easily.

Signed-off-by: Atsushi Nemoto <anemo@xxxxxxxxxxxxx>

 kernel/genex.S      |    8 ++++----
 kernel/stacktrace.c |   52 +++++++++++++++++++++++-----------------------------
 mm/tlbex-fault.S    |    4 ++--
 3 files changed, 29 insertions(+), 35 deletions(-)

diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 37fda3d..af6ef2f 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -220,8 +220,8 @@ #endif /* CONFIG_MIPS_MT_SMTC */
 	CLI
 	TRACE_IRQS_OFF
 	move	a0, sp
-	jalr	v0
-	j	ret_from_irq
+	PTR_LA	ra, ret_from_irq
+	jr	v0
 	END(except_vec_vi_handler)
 
 /*
@@ -349,8 +349,8 @@ #endif
 	.set	at
 	__BUILD_\verbose \exception
 	move	a0, sp
-	jal	do_\handler
-	j	ret_from_exception
+	PTR_LA	ra, ret_from_exception
+	j	do_\handler
 	END(handle_\exception)
 	.endm
 
diff --git a/arch/mips/kernel/stacktrace.c b/arch/mips/kernel/stacktrace.c
index f851d0c..676e6f6 100644
--- a/arch/mips/kernel/stacktrace.c
+++ b/arch/mips/kernel/stacktrace.c
@@ -13,7 +13,7 @@ #include <asm/stacktrace.h>
  * Save stack-backtrace addresses into a stack_trace buffer:
  */
 static void save_raw_context_stack(struct stack_trace *trace,
-	unsigned int skip, unsigned long reg29)
+	unsigned long reg29)
 {
 	unsigned long *sp = (unsigned long *)reg29;
 	unsigned long addr;
@@ -21,10 +21,10 @@ static void save_raw_context_stack(struc
 	while (!kstack_end(sp)) {
 		addr = *sp++;
 		if (__kernel_text_address(addr)) {
-			if (!skip)
-				trace->entries[trace->nr_entries++] = addr;
+			if (trace->skip > 0)
+				trace->skip--;
 			else
-				skip--;
+				trace->entries[trace->nr_entries++] = addr;
 			if (trace->nr_entries >= trace->max_entries)
 				break;
 		}
@@ -32,37 +32,40 @@ static void save_raw_context_stack(struc
 }
 
 static struct pt_regs * save_context_stack(struct stack_trace *trace,
-	unsigned int skip, struct task_struct *task, struct pt_regs *regs)
+	struct task_struct *task, struct pt_regs *regs)
 {
 	unsigned long sp = regs->regs[29];
 #ifdef CONFIG_KALLSYMS
 	unsigned long ra = regs->regs[31];
 	unsigned long pc = regs->cp0_epc;
+	unsigned long stack_page =
+		(unsigned long)task_stack_page(task);
 	extern void ret_from_irq(void);
+	extern void ret_from_exception(void);
 
 	if (raw_show_trace || !__kernel_text_address(pc)) {
-		save_raw_context_stack(trace, skip, sp);
+		if (stack_page && sp >= stack_page &&
+		    sp <= stack_page + THREAD_SIZE - 32)
+			save_raw_context_stack(trace, sp);
 		return NULL;
 	}
 	do {
-		if (!skip)
-			trace->entries[trace->nr_entries++] = pc;
+		if (trace->skip > 0)
+			trace->skip--;
 		else
-			skip--;
+			trace->entries[trace->nr_entries++] = pc;
 		if (trace->nr_entries >= trace->max_entries)
 			break;
 		/*
 		 * If we reached the bottom of interrupt context,
 		 * return saved pt_regs.
 		 */
-		if (pc == (unsigned long)ret_from_irq) {
-			unsigned long stack_page =
-				(unsigned long)task_stack_page(task);
-			if (!stack_page ||
-			    sp < stack_page ||
-			    sp > stack_page + THREAD_SIZE - 32)
-				break;
-			return (struct pt_regs *)sp;
+		if (pc == (unsigned long)ret_from_irq ||
+		    pc == (unsigned long)ret_from_exception) {
+			if (stack_page && sp >= stack_page &&
+			    sp <= stack_page + THREAD_SIZE - 32)
+				return (struct pt_regs *)sp;
+			break;
 		}
 		pc = unwind_stack(task, &sp, pc, ra);
 		ra = 0;
@@ -76,12 +79,8 @@ #endif
 
 /*
  * Save stack-backtrace addresses into a stack_trace buffer.
- * If all_contexts is set, all contexts (hardirq, softirq and process)
- * are saved. If not set then only the current context is saved.
  */
-void save_stack_trace(struct stack_trace *trace,
-		      struct task_struct *task, int all_contexts,
-		      unsigned int skip)
+void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
 {
 	struct pt_regs dummyregs;
 	struct pt_regs *regs = &dummyregs;
@@ -99,13 +98,8 @@ void save_stack_trace(struct stack_trace
 	}
 
 	while (1) {
-		regs = save_context_stack(trace, skip, task, regs);
-		if (!all_contexts || !regs ||
-		    trace->nr_entries >= trace->max_entries)
-			break;
-		trace->entries[trace->nr_entries++] = ULONG_MAX;
-		if (trace->nr_entries >= trace->max_entries)
+		regs = save_context_stack(trace, task, regs);
+		if (!regs || trace->nr_entries >= trace->max_entries)
 			break;
-		skip = 0;
 	}
 }
diff --git a/arch/mips/mm/tlbex-fault.S b/arch/mips/mm/tlbex-fault.S
index 9e7f417..e99eaa1 100644
--- a/arch/mips/mm/tlbex-fault.S
+++ b/arch/mips/mm/tlbex-fault.S
@@ -19,8 +19,8 @@ #include <asm/stackframe.h>
 	move	a0, sp
 	REG_S	a2, PT_BVADDR(sp)
 	li	a1, \write
-	jal	do_page_fault
-	j	ret_from_exception
+	PTR_LA	ra, ret_from_exception
+	j	do_page_fault
 	END(tlb_do_page_fault_\write)
 	.endm
 


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux