void xtensa_backtrace_user()

in kernel/stacktrace.c [26:112]


void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth,
			   int (*ufn)(struct stackframe *frame, void *data),
			   void *data)
{
	unsigned long windowstart = regs->windowstart;
	unsigned long windowbase = regs->windowbase;
	unsigned long a0 = regs->areg[0];
	unsigned long a1 = regs->areg[1];
	unsigned long pc = regs->pc;
	struct stackframe frame;
	int index;

	if (!depth--)
		return;

	frame.pc = pc;
	frame.sp = a1;

	if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
		return;

	if (IS_ENABLED(CONFIG_USER_ABI_CALL0_ONLY) ||
	    (IS_ENABLED(CONFIG_USER_ABI_CALL0_PROBE) &&
	     !(regs->ps & PS_WOE_MASK)))
		return;

	/* Two steps:
	 *
	 * 1. Look through the register window for the
	 * previous PCs in the call trace.
	 *
	 * 2. Look on the stack.
	 */

	/* Step 1.  */
	/* Rotate WINDOWSTART to move the bit corresponding to
	 * the current window to the bit #0.
	 */
	windowstart = (windowstart << WSBITS | windowstart) >> windowbase;

	/* Look for bits that are set, they correspond to
	 * valid windows.
	 */
	for (index = WSBITS - 1; (index > 0) && depth; depth--, index--)
		if (windowstart & (1 << index)) {
			/* Get the PC from a0 and a1. */
			pc = MAKE_PC_FROM_RA(a0, pc);
			/* Read a0 and a1 from the
			 * corresponding position in AREGs.
			 */
			a0 = regs->areg[index * 4];
			a1 = regs->areg[index * 4 + 1];

			frame.pc = pc;
			frame.sp = a1;

			if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
				return;
		}

	/* Step 2. */
	/* We are done with the register window, we need to
	 * look through the stack.
	 */
	if (!depth)
		return;

	/* Start from the a1 register. */
	/* a1 = regs->areg[1]; */
	while (a0 != 0 && depth--) {
		pc = MAKE_PC_FROM_RA(a0, pc);

		/* Check if the region is OK to access. */
		if (!access_ok(&SPILL_SLOT(a1, 0), 8))
			return;
		/* Copy a1, a0 from user space stack frame. */
		if (__get_user(a0, &SPILL_SLOT(a1, 0)) ||
		    __get_user(a1, &SPILL_SLOT(a1, 1)))
			return;

		frame.pc = pc;
		frame.sp = a1;

		if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
			return;
	}
}