/*
 * Xtensa hardware breakpoints/watchpoints handling functions
 *
 * 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) 2016 Cadence Design Systems Inc.
 */

#include <linux/hw_breakpoint.h>
#include <linux/log2.h>
#include <linux/percpu.h>
#include <linux/perf_event.h>
#include <variant/core.h>

/* Breakpoint currently in use for each IBREAKA. */
static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[XCHAL_NUM_IBREAK]);

/* Watchpoint currently in use for each DBREAKA. */
static DEFINE_PER_CPU(struct perf_event *, wp_on_reg[XCHAL_NUM_DBREAK]);

int hw_breakpoint_slots(int type)
{
	switch (type) {
	case TYPE_INST:
		return XCHAL_NUM_IBREAK;
	case TYPE_DATA:
		return XCHAL_NUM_DBREAK;
	default:
		pr_warn("unknown slot type: %d\n", type);
		return 0;
	}
}

int arch_check_bp_in_kernelspace(struct perf_event *bp)
{
	unsigned int len;
	unsigned long va;
	struct arch_hw_breakpoint *info = counter_arch_bp(bp);

	va = info->address;
	len = bp->attr.bp_len;

	return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);
}

/*
 * Construct an arch_hw_breakpoint from a perf_event.
 */
static int arch_build_bp_info(struct perf_event *bp)
{
	struct arch_hw_breakpoint *info = counter_arch_bp(bp);

	/* Type */
	switch (bp->attr.bp_type) {
	case HW_BREAKPOINT_X:
		info->type = XTENSA_BREAKPOINT_EXECUTE;
		break;
	case HW_BREAKPOINT_R:
		info->type = XTENSA_BREAKPOINT_LOAD;
		break;
	case HW_BREAKPOINT_W:
		info->type = XTENSA_BREAKPOINT_STORE;
		break;
	case HW_BREAKPOINT_RW:
		info->type = XTENSA_BREAKPOINT_LOAD | XTENSA_BREAKPOINT_STORE;
		break;
	default:
		return -EINVAL;
	}

	/* Len */
	info->len = bp->attr.bp_len;
	if (info->len < 1 || info->len > 64 || !is_power_of_2(info->len))
		return -EINVAL;

	/* Address */
	info->address = bp->attr.bp_addr;
	if (info->address & (info->len - 1))
		return -EINVAL;

	return 0;
}

int arch_validate_hwbkpt_settings(struct perf_event *bp)
{
	int ret;

	/* Build the arch_hw_breakpoint. */
	ret = arch_build_bp_info(bp);
	return ret;
}

int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
				    unsigned long val, void *data)
{
	return NOTIFY_DONE;
}

static void xtensa_wsr(unsigned long v, u8 sr)
{
	/* We don't have indexed wsr and creating instruction dynamically
	 * doesn't seem worth it given how small XCHAL_NUM_IBREAK and
	 * XCHAL_NUM_DBREAK are. Thus the switch. In case build breaks here
	 * the switch below needs to be extended.
	 */
	BUILD_BUG_ON(XCHAL_NUM_IBREAK > 2);
	BUILD_BUG_ON(XCHAL_NUM_DBREAK > 2);

	switch (sr) {
#if XCHAL_NUM_IBREAK > 0
	case SREG_IBREAKA + 0:
		WSR(v, SREG_IBREAKA + 0);
		break;
#endif
#if XCHAL_NUM_IBREAK > 1
	case SREG_IBREAKA + 1:
		WSR(v, SREG_IBREAKA + 1);
		break;
#endif

#if XCHAL_NUM_DBREAK > 0
	case SREG_DBREAKA + 0:
		WSR(v, SREG_DBREAKA + 0);
		break;
	case SREG_DBREAKC + 0:
		WSR(v, SREG_DBREAKC + 0);
		break;
#endif
#if XCHAL_NUM_DBREAK > 1
	case SREG_DBREAKA + 1:
		WSR(v, SREG_DBREAKA + 1);
		break;

	case SREG_DBREAKC + 1:
		WSR(v, SREG_DBREAKC + 1);
		break;
#endif
	}
}

static int alloc_slot(struct perf_event **slot, size_t n,
		      struct perf_event *bp)
{
	size_t i;

	for (i = 0; i < n; ++i) {
		if (!slot[i]) {
			slot[i] = bp;
			return i;
		}
	}
	return -EBUSY;
}

static void set_ibreak_regs(int reg, struct perf_event *bp)
{
	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
	unsigned long ibreakenable;

	xtensa_wsr(info->address, SREG_IBREAKA + reg);
	RSR(ibreakenable, SREG_IBREAKENABLE);
	WSR(ibreakenable | (1 << reg), SREG_IBREAKENABLE);
}

static void set_dbreak_regs(int reg, struct perf_event *bp)
{
	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
	unsigned long dbreakc = DBREAKC_MASK_MASK & -info->len;

	if (info->type & XTENSA_BREAKPOINT_LOAD)
		dbreakc |= DBREAKC_LOAD_MASK;
	if (info->type & XTENSA_BREAKPOINT_STORE)
		dbreakc |= DBREAKC_STOR_MASK;

	xtensa_wsr(info->address, SREG_DBREAKA + reg);
	xtensa_wsr(dbreakc, SREG_DBREAKC + reg);
}

int arch_install_hw_breakpoint(struct perf_event *bp)
{
	int i;

	if (counter_arch_bp(bp)->type == XTENSA_BREAKPOINT_EXECUTE) {
		/* Breakpoint */
		i = alloc_slot(this_cpu_ptr(bp_on_reg), XCHAL_NUM_IBREAK, bp);
		if (i < 0)
			return i;
		set_ibreak_regs(i, bp);

	} else {
		/* Watchpoint */
		i = alloc_slot(this_cpu_ptr(wp_on_reg), XCHAL_NUM_DBREAK, bp);
		if (i < 0)
			return i;
		set_dbreak_regs(i, bp);
	}
	return 0;
}

static int free_slot(struct perf_event **slot, size_t n,
		     struct perf_event *bp)
{
	size_t i;

	for (i = 0; i < n; ++i) {
		if (slot[i] == bp) {
			slot[i] = NULL;
			return i;
		}
	}
	return -EBUSY;
}

void arch_uninstall_hw_breakpoint(struct perf_event *bp)
{
	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
	int i;

	if (info->type == XTENSA_BREAKPOINT_EXECUTE) {
		unsigned long ibreakenable;

		/* Breakpoint */
		i = free_slot(this_cpu_ptr(bp_on_reg), XCHAL_NUM_IBREAK, bp);
		if (i >= 0) {
			RSR(ibreakenable, SREG_IBREAKENABLE);
			WSR(ibreakenable & ~(1 << i), SREG_IBREAKENABLE);
		}
	} else {
		/* Watchpoint */
		i = free_slot(this_cpu_ptr(wp_on_reg), XCHAL_NUM_DBREAK, bp);
		if (i >= 0)
			xtensa_wsr(0, SREG_DBREAKC + i);
	}
}

void hw_breakpoint_pmu_read(struct perf_event *bp)
{
}

void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
{
	int i;
	struct thread_struct *t = &tsk->thread;

	for (i = 0; i < XCHAL_NUM_IBREAK; ++i) {
		if (t->ptrace_bp[i]) {
			unregister_hw_breakpoint(t->ptrace_bp[i]);
			t->ptrace_bp[i] = NULL;
		}
	}
	for (i = 0; i < XCHAL_NUM_DBREAK; ++i) {
		if (t->ptrace_wp[i]) {
			unregister_hw_breakpoint(t->ptrace_wp[i]);
			t->ptrace_wp[i] = NULL;
		}
	}
}

/*
 * Set ptrace breakpoint pointers to zero for this task.
 * This is required in order to prevent child processes from unregistering
 * breakpoints held by their parent.
 */
void clear_ptrace_hw_breakpoint(struct task_struct *tsk)
{
	memset(tsk->thread.ptrace_bp, 0, sizeof(tsk->thread.ptrace_bp));
	memset(tsk->thread.ptrace_wp, 0, sizeof(tsk->thread.ptrace_wp));
}

void restore_dbreak(void)
{
	int i;

	for (i = 0; i < XCHAL_NUM_DBREAK; ++i) {
		struct perf_event *bp = this_cpu_ptr(wp_on_reg)[i];

		if (bp)
			set_dbreak_regs(i, bp);
	}
	clear_thread_flag(TIF_DB_DISABLED);
}

int check_hw_breakpoint(struct pt_regs *regs)
{
	if (regs->debugcause & BIT(DEBUGCAUSE_IBREAK_BIT)) {
		int i;
		struct perf_event **bp = this_cpu_ptr(bp_on_reg);

		for (i = 0; i < XCHAL_NUM_IBREAK; ++i) {
			if (bp[i] && !bp[i]->attr.disabled &&
			    regs->pc == bp[i]->attr.bp_addr)
				perf_bp_event(bp[i], regs);
		}
		return 0;
	} else if (regs->debugcause & BIT(DEBUGCAUSE_DBREAK_BIT)) {
		struct perf_event **bp = this_cpu_ptr(wp_on_reg);
		int dbnum = (regs->debugcause & DEBUGCAUSE_DBNUM_MASK) >>
			DEBUGCAUSE_DBNUM_SHIFT;

		if (dbnum < XCHAL_NUM_DBREAK && bp[dbnum]) {
			if (user_mode(regs)) {
				perf_bp_event(bp[dbnum], regs);
			} else {
				set_thread_flag(TIF_DB_DISABLED);
				xtensa_wsr(0, SREG_DBREAKC + dbnum);
			}
		} else {
			WARN_ONCE(1,
				  "Wrong/unconfigured DBNUM reported in DEBUGCAUSE: %d\n",
				  dbnum);
		}
		return 0;
	}
	return -ENOENT;
}
