/*
 * 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/ftrace.h>
#include <asm/sections.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, _text);
		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

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);
