static void microblaze_unwind_inner()

in kernel/unwind.c [182:264]


static void microblaze_unwind_inner(struct task_struct *task,
			     unsigned long pc, unsigned long fp,
			     unsigned long leaf_return,
			     struct stack_trace *trace,
			     const char *loglvl)
{
	int ofs = 0;

	pr_debug("    Unwinding with PC=%p, FP=%p\n", (void *)pc, (void *)fp);
	if (!pc || !fp || (pc & 3) || (fp & 3)) {
		pr_debug("    Invalid state for unwind, aborting\n");
		return;
	}
	for (; pc != 0;) {
		unsigned long next_fp, next_pc = 0;
		unsigned long return_to = pc +  2 * sizeof(unsigned long);
		const struct trap_handler_info *handler =
			&microblaze_trap_handlers;

		/* Is previous function the HW exception handler? */
		if ((return_to >= (unsigned long)&_hw_exception_handler)
		    &&(return_to < (unsigned long)&ex_handler_unhandled)) {
			/*
			 * HW exception handler doesn't save all registers,
			 * so we open-code a special case of unwind_trap()
			 */
			printk("%sHW EXCEPTION\n", loglvl);
			return;
		}

		/* Is previous function a trap handler? */
		for (; handler->start_addr; ++handler) {
			if ((return_to >= handler->start_addr)
			    && (return_to <= handler->end_addr)) {
				if (!trace)
					printk("%s%s\n", loglvl, handler->trap_name);
				unwind_trap(task, pc, fp, trace, loglvl);
				return;
			}
		}
		pc -= ofs;

		if (trace) {
#ifdef CONFIG_STACKTRACE
			if (trace->skip > 0)
				trace->skip--;
			else
				trace->entries[trace->nr_entries++] = pc;

			if (trace->nr_entries >= trace->max_entries)
				break;
#endif
		} else {
			/* Have we reached userland? */
			if (unlikely(pc == task_pt_regs(task)->pc)) {
				printk("%s[<%p>] PID %lu [%s]\n",
					loglvl, (void *) pc,
					(unsigned long) task->pid,
					task->comm);
				break;
			} else
				print_ip_sym(loglvl, pc);
		}

		/* Stop when we reach anything not part of the kernel */
		if (!kernel_text_address(pc))
			break;

		if (lookup_prev_stack_frame(fp, pc, leaf_return, &next_fp,
					    &next_pc) == 0) {
			ofs = sizeof(unsigned long);
			pc = next_pc & ~3;
			fp = next_fp;
			leaf_return = 0;
		} else {
			pr_debug("    Failed to find previous stack frame\n");
			break;
		}

		pr_debug("    Next PC=%p, next FP=%p\n",
			 (void *)next_pc, (void *)next_fp);
	}
}