/*
 * Kernel and userspace stack tracing.
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2001 - 2013 Tensilica Inc.
 * Copyright (C) 2015 Cadence Design Systems Inc.
 */
#include <linux/export.h>
#include <linux/sched.h>
#include <linux/stacktrace.h>

#include <asm/stacktrace.h>
#include <asm/traps.h>
#include <linux/uaccess.h>

#if IS_ENABLED(CONFIG_PERF_EVENTS)

/* Address of common_exception_return, used to check the
 * transition from kernel to user space.
 */
extern int common_exception_return;

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;
	}
}
EXPORT_SYMBOL(xtensa_backtrace_user);

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);
	}
}
EXPORT_SYMBOL(xtensa_backtrace_kernel);

#endif

void walk_stackframe(unsigned long *sp,
		int (*fn)(struct stackframe *frame, void *data),
		void *data)
{
	unsigned long a0, a1;
	unsigned long sp_end;

	a1 = (unsigned long)sp;
	sp_end = ALIGN(a1, THREAD_SIZE);

	spill_registers();

	while (a1 < sp_end) {
		struct stackframe frame;

		sp = (unsigned long *)a1;

		a0 = SPILL_SLOT(a1, 0);
		a1 = SPILL_SLOT(a1, 1);

		if (a1 <= (unsigned long)sp)
			break;

		frame.pc = MAKE_PC_FROM_RA(a0, a1);
		frame.sp = a1;

		if (fn(&frame, data))
			return;
	}
}

#ifdef CONFIG_STACKTRACE

struct stack_trace_data {
	struct stack_trace *trace;
	unsigned skip;
};

static int stack_trace_cb(struct stackframe *frame, void *data)
{
	struct stack_trace_data *trace_data = data;
	struct stack_trace *trace = trace_data->trace;

	if (trace_data->skip) {
		--trace_data->skip;
		return 0;
	}
	if (!kernel_text_address(frame->pc))
		return 0;

	trace->entries[trace->nr_entries++] = frame->pc;
	return trace->nr_entries >= trace->max_entries;
}

void save_stack_trace_tsk(struct task_struct *task, struct stack_trace *trace)
{
	struct stack_trace_data trace_data = {
		.trace = trace,
		.skip = trace->skip,
	};
	walk_stackframe(stack_pointer(task), stack_trace_cb, &trace_data);
}
EXPORT_SYMBOL_GPL(save_stack_trace_tsk);

void save_stack_trace(struct stack_trace *trace)
{
	save_stack_trace_tsk(current, trace);
}
EXPORT_SYMBOL_GPL(save_stack_trace);

#endif

#ifdef CONFIG_FRAME_POINTER

struct return_addr_data {
	unsigned long addr;
	unsigned skip;
};

static int return_address_cb(struct stackframe *frame, void *data)
{
	struct return_addr_data *r = data;

	if (r->skip) {
		--r->skip;
		return 0;
	}
	if (!kernel_text_address(frame->pc))
		return 0;
	r->addr = frame->pc;
	return 1;
}

/*
 * level == 0 is for the return address from the caller of this function,
 * not from this function itself.
 */
unsigned long return_address(unsigned level)
{
	struct return_addr_data r = {
		.skip = level,
	};
	walk_stackframe(stack_pointer(NULL), return_address_cb, &r);
	return r.addr;
}
EXPORT_SYMBOL(return_address);

#endif
