// SPDX-License-Identifier: BSD-2-Clause
/*-
 * Copyright (c) 2015 Linaro Limited
 * Copyright (c) 2015 The FreeBSD Foundation
 * All rights reserved.
 *
 * This software was developed by Semihalf under
 * the sponsorship of the FreeBSD Foundation.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <arm.h>
#include <kernel/linker.h>
#include <kernel/tee_misc.h>
#include <kernel/tee_ta_manager.h>
#include <kernel/thread.h>
#include <kernel/unwind.h>
#include <string.h>
#include <tee/tee_svc.h>
#include <trace.h>
#include <user_ta_header.h>
#include <util.h>

#include "unwind_private.h"

static void copy_in_reg(uint64_t *reg, vaddr_t addr)
{
	memcpy(reg, (void *)addr, sizeof(*reg));
}

#ifdef CFG_SYSCALL_FTRACE
static void ftrace_core_map_lr(uint64_t *lr)
{
	struct ftrace_buf *fbuf = NULL;
	struct tee_ta_session *s = NULL;

	if (tee_ta_get_current_session(&s) != TEE_SUCCESS)
		return;

	if (!s->fbuf)
		return;

	fbuf = s->fbuf;

	/*
	 * Function tracer inserts return hook (addr: &__ftrace_return)
	 * via modifying lr values in the stack frames. And during aborts,
	 * stack trace picks these modified lr values which needs to be
	 * replaced with original lr value. So here we use the ftrace return
	 * stack to retrieve original lr value but we need to first check if
	 * it has actually been modified or not in case TA is profiled
	 * partially.
	 */
	if ((*lr == (uint64_t)&__ftrace_return) &&
	    fbuf->lr_idx < fbuf->ret_idx) {
		fbuf->lr_idx++;
		*lr = fbuf->ret_stack[fbuf->ret_idx - fbuf->lr_idx];
	}
}
#else
static void ftrace_core_map_lr(uint64_t *lr __unused)
{
}
#endif

bool unwind_stack_arm64(struct unwind_state_arm64 *frame,
			vaddr_t stack, size_t stack_size)
{
	vaddr_t fp = frame->fp;

	if (!core_is_buffer_inside(fp, sizeof(uint64_t) * 3,
				   stack, stack_size))
		return false;

	frame->sp = fp + 0x10;
	/* FP to previous frame (X29) */
	copy_in_reg(&frame->fp, fp);
	/* LR (X30) */
	copy_in_reg(&frame->pc, fp + 8);

	ftrace_core_map_lr(&frame->pc);

	frame->pc -= 4;

	return true;
}

#if (TRACE_LEVEL > 0)

void print_stack_arm64(int level, struct unwind_state_arm64 *state,
		       vaddr_t stack, size_t stack_size)
{
	trace_printf_helper_raw(level, true, "Load address @ %#"PRIxVA,
				VCORE_START_VA);
	trace_printf_helper_raw(level, true, "Call stack:");

	do {
		trace_printf_helper_raw(level, true, " 0x%016" PRIx64,
					state->pc);
	} while (unwind_stack_arm64(state, stack, stack_size));
}

void print_kernel_stack(int level)
{
	struct unwind_state_arm64 state;
	uaddr_t stack = thread_stack_start();
	size_t stack_size = thread_stack_size();

	memset(&state, 0, sizeof(state));
	state.pc = read_pc();
	state.fp = read_fp();

	print_stack_arm64(level, &state, stack, stack_size);
}

#endif

vaddr_t *unw_get_kernel_stack(void)
{
	size_t n = 0;
	size_t size = 0;
	vaddr_t *tmp = NULL;
	vaddr_t *addr = NULL;
	struct unwind_state_arm64 state = { 0 };
	uaddr_t stack = thread_stack_start();
	size_t stack_size = thread_stack_size();

	state.pc = read_pc();
	state.fp = read_fp();

	while (unwind_stack_arm64(&state, stack, stack_size)) {
		tmp = unw_grow(addr, &size, (n + 1) * sizeof(vaddr_t));
		if (!tmp)
			goto err;
		addr = tmp;
		addr[n] = state.pc;
		n++;
	}

	if (addr) {
		tmp = unw_grow(addr, &size, (n + 1) * sizeof(vaddr_t));
		if (!tmp)
			goto err;
		addr = tmp;
		addr[n] = 0;
	}

	return addr;
err:
	EMSG("Out of memory");
	free(addr);
	return NULL;
}
