debug: fail to show active cpu stacks [1/1]

PD#SWPL-4718

Problem:
Will have "PC=0, LR=0" issue when try to
show active cpu stacks via sysrq

Solution:
Save the addr of current interrupted task's context to the
interrupt stack first, so that we can easily obtain pt_regs
later

Verify:
Locally on Ampere

Change-Id: I1cc5095e0ec356bed90f76cdf9af1b2617ce7834
Signed-off-by: Jiamin Ma <jiamin.ma@amlogic.com>
This commit is contained in:
Jiamin Ma
2019-02-19 18:19:27 +08:00
committed by Luke Go
parent 2e760511d0
commit c5536d6d81
4 changed files with 45 additions and 18 deletions

View File

@@ -47,7 +47,11 @@
#endif
#ifdef CONFIG_MULTI_IRQ_HANDLER
ldr r1, =handle_arch_irq
#ifdef CONFIG_AMLOGIC_VMAP
mov r0, r8
#else
mov r0, sp
#endif
badr lr, 9997f
ldr pc, [r1]
#else

View File

@@ -46,6 +46,7 @@
#include <linux/list.h>
#ifdef CONFIG_AMLOGIC_VMAP
#include <linux/amlogic/vmap_stack.h>
#include <asm/irq.h>
#endif
#include <asm/stacktrace.h>
@@ -524,25 +525,36 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk)
#ifdef CONFIG_AMLOGIC_VMAP
if (urc < 0) {
int keep = 0;
int cpu;
unsigned long addr;
struct pt_regs *pt_regs;
cpu = raw_smp_processor_id();
/* continue search for irq stack */
if (on_irq_stack(frame.sp, raw_smp_processor_id())) {
unsigned long *prev_fp;
if (on_irq_stack(frame.sp, cpu)) {
unsigned long sp_irq;
prev_fp = (unsigned long *)(frame.fp - 12);
if (frame.fp >= TASK_SIZE) {
keep = 1;
frame.fp = prev_fp[0];
frame.sp = prev_fp[1];
frame.lr = prev_fp[2];
frame.pc = prev_fp[3];
}
keep = 1;
sp_irq = (unsigned long)irq_stack[cpu];
addr = *((unsigned long *)(sp_irq +
THREAD_INFO_OFFSET - 8 -
sizeof(addr)));
pt_regs = (struct pt_regs *)addr;
frame.fp = pt_regs->ARM_fp;
frame.sp = pt_regs->ARM_sp;
frame.lr = pt_regs->ARM_lr;
frame.pc = pt_regs->ARM_pc;
}
if (!keep)
break;
}
where = frame.lr;
dump_backtrace_entry_fp(where, frame.fp, frame.sp);
where = frame.pc;
/*
* The last "where" may be an invalid one,
* rechecking it
*/
if (kernel_text_address(where))
dump_backtrace_entry_fp(where, frame.fp, frame.sp);
#else
if (urc < 0)
break;

View File

@@ -56,7 +56,7 @@ DEFINE_PER_CPU(unsigned long [THREAD_SIZE/sizeof(long)], vmap_stack)
#else
static unsigned long irq_stack1[(THREAD_SIZE/sizeof(long))]
__aligned(THREAD_SIZE);
static void *irq_stack[NR_CPUS] = {
void *irq_stack[NR_CPUS] = {
irq_stack1, /* only assign 1st irq stack ,other need alloc */
};
static unsigned long vmap_stack1[(THREAD_SIZE/sizeof(long))]
@@ -142,23 +142,29 @@ int on_irq_stack(unsigned long sp, int cpu)
return 0;
}
unsigned long notrace irq_stack_entry(unsigned long sp_irq)
unsigned long notrace irq_stack_entry(unsigned long sp)
{
int cpu = raw_smp_processor_id();
if (!on_irq_stack(sp_irq, cpu)) {
unsigned long sp = (unsigned long)irq_stack[cpu];
if (!on_irq_stack(sp, cpu)) {
unsigned long sp_irq = (unsigned long)irq_stack[cpu];
void *src, *dst;
/*
* copy some data to irq stack
*/
src = current_thread_info();
dst = (void *)(sp + THREAD_INFO_OFFSET);
dst = (void *)(sp_irq + THREAD_INFO_OFFSET);
memcpy(dst, src, offsetof(struct thread_info, cpu_context));
sp_irq = (unsigned long)dst - 8;
/*
* save start addr of the interrupted task's context
*/
sp_irq = sp_irq - sizeof(sp);
*((unsigned long *)sp_irq) = sp;
return sp_irq;
}
return sp_irq;
return sp;
}
unsigned long notrace pmd_check(unsigned long addr, unsigned long far)
@@ -403,6 +409,7 @@ static noinline void show_fault_stack(unsigned long addr, struct pt_regs *regs)
#elif defined(CONFIG_ARM)
frame.fp = regs->ARM_fp;
frame.sp = regs->ARM_sp;
frame.lr = regs->ARM_lr;
frame.pc = (unsigned long)regs->uregs[15];
#endif

View File

@@ -55,6 +55,10 @@ struct aml_vmap {
spinlock_t page_lock;
};
#ifndef CONFIG_ARM64
extern void *irq_stack[NR_CPUS];
#endif
extern int handle_vmap_fault(unsigned long addr,
unsigned int esr, struct pt_regs *regs);