/*
 * Copyright (c) 2020 Intel Corporation.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <kernel_internal.h>
#include <ia32/exception.h>
#include <inttypes.h>
#include <zephyr/debug/gdbstub.h>


static struct gdb_ctx ctx;

/**
 * Currently we just handle vectors 1 and 3 but lets keep it generic
 * to be able to notify other exceptions in the future
 */
static unsigned int get_exception(unsigned int vector)
{
	unsigned int exception;

	switch (vector) {
	case IV_DIVIDE_ERROR:
		exception = GDB_EXCEPTION_DIVIDE_ERROR;
		break;
	case IV_DEBUG:
		exception = GDB_EXCEPTION_BREAKPOINT;
		break;
	case IV_BREAKPOINT:
		exception = GDB_EXCEPTION_BREAKPOINT;
		break;
	case IV_OVERFLOW:
		exception = GDB_EXCEPTION_OVERFLOW;
		break;
	case IV_BOUND_RANGE:
		exception = GDB_EXCEPTION_OVERFLOW;
		break;
	case IV_INVALID_OPCODE:
		exception = GDB_EXCEPTION_INVALID_INSTRUCTION;
		break;
	case IV_DEVICE_NOT_AVAILABLE:
		exception = GDB_EXCEPTION_DIVIDE_ERROR;
		break;
	case IV_DOUBLE_FAULT:
		exception = GDB_EXCEPTION_MEMORY_FAULT;
		break;
	case IV_COPROC_SEGMENT_OVERRUN:
		exception = GDB_EXCEPTION_INVALID_MEMORY;
		break;
	case IV_INVALID_TSS:
		exception = GDB_EXCEPTION_INVALID_MEMORY;
		break;
	case IV_SEGMENT_NOT_PRESENT:
		exception = GDB_EXCEPTION_INVALID_MEMORY;
		break;
	case IV_STACK_FAULT:
		exception = GDB_EXCEPTION_INVALID_MEMORY;
		break;
	case IV_GENERAL_PROTECTION:
		exception = GDB_EXCEPTION_INVALID_MEMORY;
		break;
	case IV_PAGE_FAULT:
		exception = GDB_EXCEPTION_INVALID_MEMORY;
		break;
	case IV_X87_FPU_FP_ERROR:
		exception = GDB_EXCEPTION_MEMORY_FAULT;
		break;
	default:
		exception = GDB_EXCEPTION_MEMORY_FAULT;
		break;
	}

	return exception;
}

/*
 * Debug exception handler.
 */
static void z_gdb_interrupt(unsigned int vector, z_arch_esf_t *esf)
{
	ctx.exception = get_exception(vector);

	ctx.registers[GDB_EAX] = esf->eax;
	ctx.registers[GDB_ECX] = esf->ecx;
	ctx.registers[GDB_EDX] = esf->edx;
	ctx.registers[GDB_EBX] = esf->ebx;
	ctx.registers[GDB_ESP] = esf->esp;
	ctx.registers[GDB_EBP] = esf->ebp;
	ctx.registers[GDB_ESI] = esf->esi;
	ctx.registers[GDB_EDI] = esf->edi;
	ctx.registers[GDB_PC] = esf->eip;
	ctx.registers[GDB_CS] = esf->cs;
	ctx.registers[GDB_EFLAGS]  = esf->eflags;
	ctx.registers[GDB_SS] = esf->ss;
	ctx.registers[GDB_DS] = esf->ds;
	ctx.registers[GDB_ES] = esf->es;
	ctx.registers[GDB_FS] = esf->fs;
	ctx.registers[GDB_GS] = esf->gs;

	z_gdb_main_loop(&ctx);

	esf->eax = ctx.registers[GDB_EAX];
	esf->ecx = ctx.registers[GDB_ECX];
	esf->edx = ctx.registers[GDB_EDX];
	esf->ebx = ctx.registers[GDB_EBX];
	esf->esp = ctx.registers[GDB_ESP];
	esf->ebp = ctx.registers[GDB_EBP];
	esf->esi = ctx.registers[GDB_ESI];
	esf->edi = ctx.registers[GDB_EDI];
	esf->eip = ctx.registers[GDB_PC];
	esf->cs = ctx.registers[GDB_CS];
	esf->eflags = ctx.registers[GDB_EFLAGS];
	esf->ss = ctx.registers[GDB_SS];
	esf->ds = ctx.registers[GDB_DS];
	esf->es = ctx.registers[GDB_ES];
	esf->fs = ctx.registers[GDB_FS];
	esf->gs = ctx.registers[GDB_GS];
}

void arch_gdb_continue(void)
{
	/* Clear the TRAP FLAG bit */
	ctx.registers[GDB_EFLAGS] &= ~BIT(8);
}

void arch_gdb_step(void)
{
	/* Set the TRAP FLAG bit */
	ctx.registers[GDB_EFLAGS] |= BIT(8);
}

size_t arch_gdb_reg_readall(struct gdb_ctx *ctx, uint8_t *buf, size_t buflen)
{
	size_t ret;

	if (buflen < (sizeof(ctx->registers) * 2)) {
		ret = 0;
	} else {
		ret = bin2hex((const uint8_t *)&(ctx->registers),
			      sizeof(ctx->registers), buf, buflen);
	}

	return ret;
}

size_t arch_gdb_reg_writeall(struct gdb_ctx *ctx, uint8_t *hex, size_t hexlen)
{
	size_t ret;

	if (hexlen != (sizeof(ctx->registers) * 2)) {
		ret = 0;
	} else {
		ret = hex2bin(hex, hexlen,
			      (uint8_t *)&(ctx->registers),
			      sizeof(ctx->registers));
	}

	return ret;
}

size_t arch_gdb_reg_readone(struct gdb_ctx *ctx, uint8_t *buf, size_t buflen,
			    uint32_t regno)
{
	size_t ret;

	if (buflen < (sizeof(unsigned int) * 2)) {
		/* Make sure there is enough space to write hex string */
		ret = 0;
	} else if (regno >= GDB_STUB_NUM_REGISTERS) {
		/* Return hex string "xx" to tell GDB that this register
		 * is not available. So GDB will continue probing other
		 * registers instead of stopping in the middle of
		 * "info registers all".
		 */
		if (buflen >= 2) {
			strncpy(buf, "xx", 2);
			ret = 2;
		} else {
			ret = 0;
		}
	} else {
		ret = bin2hex((const uint8_t *)&(ctx->registers[regno]),
			      sizeof(ctx->registers[regno]),
			      buf, buflen);
	}

	return ret;
}

size_t arch_gdb_reg_writeone(struct gdb_ctx *ctx, uint8_t *hex, size_t hexlen,
			     uint32_t regno)
{
	size_t ret;

	if (regno == GDB_ORIG_EAX) {
		/* GDB requires orig_eax that seems to be
		 * Linux specific. Unfortunately if we just
		 * return error, GDB will stop working.
		 * So just fake an OK response by saying
		 * that we have processed the hex string.
		 */
		ret = hexlen;
	} else if (regno >= GDB_STUB_NUM_REGISTERS) {
		ret = 0;
	} else if (hexlen != (sizeof(unsigned int) * 2)) {
		/* Make sure the input hex string matches register size */
		ret = 0;
	} else {
		ret = hex2bin(hex, hexlen,
			      (uint8_t *)&(ctx->registers[regno]),
			      sizeof(ctx->registers[regno]));
	}

	return ret;
}

static __used void z_gdb_debug_isr(z_arch_esf_t *esf)
{
	z_gdb_interrupt(IV_DEBUG, esf);
}

static __used void z_gdb_break_isr(z_arch_esf_t *esf)
{
	z_gdb_interrupt(IV_BREAKPOINT, esf);
}

void arch_gdb_init(void)
{
	__asm__ volatile ("int3");
}

/* Hook current IDT. */
_EXCEPTION_CONNECT_NOCODE(z_gdb_debug_isr, IV_DEBUG, 3);
_EXCEPTION_CONNECT_NOCODE(z_gdb_break_isr, IV_BREAKPOINT, 3);
