/*
 * Copyright (c) 2019-2020 Cobham Gaisler AB
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <kernel.h>
#include <logging/log.h>
LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);

/*
 * EXAMPLE OUTPUT
 *
 * ---------------------------------------------------------------------
 *
 *  tt = 0x02, illegal_instruction
 *
 *        INS        LOCALS     OUTS       GLOBALS
 *    0:  00000000   f3900fc0   40007c50   00000000
 *    1:  00000000   40004bf0   40008d30   40008c00
 *    2:  00000000   40004bf4   40008000   00000003
 *    3:  40009158   00000000   40009000   00000002
 *    4:  40008fa8   40003c00   40008fa8   00000008
 *    5:  40009000   f3400fc0   00000000   00000080
 *    6:  4000a1f8   40000050   4000a190   00000000
 *    7:  40002308   00000000   40001fb8   000000c1
 *
 *  psr: f30000c7   wim: 00000008   tbr: 40000020   y: 00000000
 *   pc: 4000a1f4   npc: 4000a1f8
 *
 *        pc         sp
 *   #0   4000a1f4   4000a190
 *   #1   40002308   4000a1f8
 *   #2   40003b24   4000a258
 *
 * ---------------------------------------------------------------------
 *
 *
 * INTERPRETATION
 *
 * INS, LOCALS, OUTS and GLOBALS represent the %i, %l, %o and %g
 * registers before the trap was taken.
 *
 * wim, y, pc and npc are the values before the trap was taken.
 * tbr has the tbr.tt field (bits 11..4) filled in by hardware
 * representing the current trap type. psr is read immediately
 * after the trap was taken so it will have the new CWP and ET=0.
 *
 * The "#i pc sp" rows is the stack backtrace. All register
 * windows are flushed to the stack prior to printing. First row
 * is the trapping pc and sp (o6).
 *
 *
 * HOW TO USE
 *
 * When invesetigating a crashed program, the first things to look
 * at is typically the tt, pc and sp (o6). You can lookup the pc
 * in the assembly list file or use addr2line. In the listing, the
 * register values in the table above can be used. The linker map
 * file will give a hint on which stack is active and if it has
 * overflowed.
 *
 * psr bits 11..8 is the processor interrupt (priority) level. 0
 * is lowest priority level (all can be taken), and 0xf is the
 * highest level where only non-maskable interrupts are taken.
 *
 * g0 is always zero. g5, g6 are never accessed by the compiler.
 * g7 is the TLS pointer if enabled. A SAVE instruction decreases
 * the current window pointer (psr bits 4..0) which results in %o
 * registers becoming %i registers and a new set of %l registers
 * appear. RESTORE does the oppposite.
 */


/*
 * The SPARC V8 ABI guarantees that the stack pointer register
 * (o6) points to an area organized as "struct savearea" below at
 * all times when traps are enabled. This is the register save
 * area where register window registers can be flushed to the
 * stack.
 *
 * We flushed registers to this space in the fault trap entry
 * handler. Note that the space is allocated by the ABI (compiler)
 * for each stack frame.
 *
 * When printing the registers, we get the "local" and "in"
 * registers from the ABI stack save area, while the "out" and
 * "global" registares are taken from the exception stack frame
 * generated in the fault trap entry.
 */
struct savearea {
	uint32_t local[8];
	uint32_t in[8];
};


/*
 * Exception trap type (tt) values according to The SPARC V8
 * manual, Table 7-1.
 */
static const struct {
	int tt;
	const char *desc;
} TTDESC[] = {
	{ .tt = 0x02, .desc = "illegal_instruction", },
	{ .tt = 0x07, .desc = "mem_address_not_aligned", },
	{ .tt = 0x2B, .desc = "data_store_error", },
	{ .tt = 0x29, .desc = "data_access_error", },
	{ .tt = 0x09, .desc = "data_access_exception", },
	{ .tt = 0x21, .desc = "instruction_access_error", },
	{ .tt = 0x01, .desc = "instruction_access_exception", },
	{ .tt = 0x04, .desc = "fp_disabled", },
	{ .tt = 0x08, .desc = "fp_exception", },
	{ .tt = 0x2A, .desc = "division_by_zero", },
	{ .tt = 0x03, .desc = "privileged_instruction", },
	{ .tt = 0x20, .desc = "r_register_access_error", },
	{ .tt = 0x0B, .desc = "watchpoint_detected", },
	{ .tt = 0x2C, .desc = "data_access_MMU_miss", },
	{ .tt = 0x3C, .desc = "instruction_access_MMU_miss", },
	{ .tt = 0x05, .desc = "window_overflow", },
	{ .tt = 0x06, .desc = "window_underflow", },
	{ .tt = 0x0A, .desc = "tag_overflow", },
};

static void print_trap_type(const z_arch_esf_t *esf)
{
	const int tt = (esf->tbr & TBR_TT) >> TBR_TT_BIT;
	const char *desc = "unknown";

	if (tt & 0x80) {
		desc = "trap_instruction";
	} else if (tt >= 0x11 && tt <= 0x1F) {
		desc = "interrupt";
	} else {
		for (int i = 0; i < ARRAY_SIZE(TTDESC); i++) {
			if (TTDESC[i].tt == tt) {
				desc = TTDESC[i].desc;
				break;
			}
		}
	}
	LOG_ERR("tt = 0x%02X, %s", tt, desc);
}

static void print_integer_registers(const z_arch_esf_t *esf)
{
	const struct savearea *flushed = (struct savearea *) esf->out[6];

	LOG_ERR("      INS        LOCALS     OUTS       GLOBALS");
	for (int i = 0; i < 8; i++) {
		LOG_ERR(
			"  %d:  %08x   %08x   %08x   %08x",
			i,
			flushed ? flushed->in[i] : 0,
			flushed ? flushed->local[i] : 0,
			esf->out[i],
			esf->global[i]
		);
	}
}

static void print_special_registers(const z_arch_esf_t *esf)
{
	LOG_ERR(
		"psr: %08x   wim: %08x   tbr: %08x   y: %08x",
		esf->psr, esf->wim, esf->tbr, esf->y
	);
	LOG_ERR(" pc: %08x   npc: %08x", esf->pc, esf->npc);
}

static void print_backtrace(const z_arch_esf_t *esf)
{
	const int MAX_LOGLINES = 40;
	const struct savearea *s = (struct savearea *) esf->out[6];

	LOG_ERR("      pc         sp");
	LOG_ERR(" #0   %08x   %08x", esf->pc, (unsigned int) s);
	for (int i = 1; s && i < MAX_LOGLINES; i++) {
		const uint32_t pc = s->in[7];
		const uint32_t sp = s->in[6];

		if (sp == 0U && pc == 0U) {
			break;
		}
		LOG_ERR(" #%-2d  %08x   %08x", i, pc, sp);
		if (sp == 0U || sp & 7U) {
			break;
		}
		s = (const struct savearea *) sp;
	}
}

static void print_all(const z_arch_esf_t *esf)
{
	LOG_ERR("");
	print_trap_type(esf);
	LOG_ERR("");
	print_integer_registers(esf);
	LOG_ERR("");
	print_special_registers(esf);
	LOG_ERR("");
	print_backtrace(esf);
	LOG_ERR("");
}

FUNC_NORETURN void z_sparc_fatal_error(unsigned int reason,
				       const z_arch_esf_t *esf)
{
	if (esf != NULL) {
		if (IS_ENABLED(CONFIG_EXTRA_EXCEPTION_INFO)) {
			print_all(esf);
		} else {
			print_special_registers(esf);
		}
	}
	z_fatal_error(reason, esf);
	CODE_UNREACHABLE;
}
