in kernel/stacktrace.c [115:163]
void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth,
int (*kfn)(struct stackframe *frame, void *data),
int (*ufn)(struct stackframe *frame, void *data),
void *data)
{
unsigned long pc = regs->depc > VALID_DOUBLE_EXCEPTION_ADDRESS ?
regs->depc : regs->pc;
unsigned long sp_start, sp_end;
unsigned long a0 = regs->areg[0];
unsigned long a1 = regs->areg[1];
sp_start = a1 & ~(THREAD_SIZE - 1);
sp_end = sp_start + THREAD_SIZE;
/* Spill the register window to the stack first. */
spill_registers();
/* Read the stack frames one by one and create the PC
* from the a0 and a1 registers saved there.
*/
while (a1 > sp_start && a1 < sp_end && depth--) {
struct stackframe frame;
frame.pc = pc;
frame.sp = a1;
if (kernel_text_address(pc) && kfn(&frame, data))
return;
if (pc == (unsigned long)&common_exception_return) {
regs = (struct pt_regs *)a1;
if (user_mode(regs)) {
if (ufn == NULL)
return;
xtensa_backtrace_user(regs, depth, ufn, data);
return;
}
a0 = regs->areg[0];
a1 = regs->areg[1];
continue;
}
sp_start = a1;
pc = MAKE_PC_FROM_RA(a0, pc);
a0 = SPILL_SLOT(a1, 0);
a1 = SPILL_SLOT(a1, 1);
}
}