mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user