// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2022-2023 Loongson Technology Corporation Limited
 */
#define pr_fmt(fmt) "hw-breakpoint: " fmt

#include <linux/hw_breakpoint.h>
#include <linux/kprobes.h>
#include <linux/perf_event.h>

#include <asm/hw_breakpoint.h>

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

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

int hw_breakpoint_slots(int type)
{
	/*
	 * We can be called early, so don't rely on
	 * our static variables being initialised.
	 */
	switch (type) {
	case TYPE_INST:
		return get_num_brps();
	case TYPE_DATA:
		return get_num_wrps();
	default:
		pr_warn("unknown slot type: %d\n", type);
		return 0;
	}
}

#define READ_WB_REG_CASE(OFF, N, REG, T, VAL)		\
	case (OFF + N):					\
		LOONGARCH_CSR_WATCH_READ(N, REG, T, VAL);	\
		break

#define WRITE_WB_REG_CASE(OFF, N, REG, T, VAL)		\
	case (OFF + N):					\
		LOONGARCH_CSR_WATCH_WRITE(N, REG, T, VAL);	\
		break

#define GEN_READ_WB_REG_CASES(OFF, REG, T, VAL)		\
	READ_WB_REG_CASE(OFF, 0, REG, T, VAL);		\
	READ_WB_REG_CASE(OFF, 1, REG, T, VAL);		\
	READ_WB_REG_CASE(OFF, 2, REG, T, VAL);		\
	READ_WB_REG_CASE(OFF, 3, REG, T, VAL);		\
	READ_WB_REG_CASE(OFF, 4, REG, T, VAL);		\
	READ_WB_REG_CASE(OFF, 5, REG, T, VAL);		\
	READ_WB_REG_CASE(OFF, 6, REG, T, VAL);		\
	READ_WB_REG_CASE(OFF, 7, REG, T, VAL);

#define GEN_WRITE_WB_REG_CASES(OFF, REG, T, VAL)	\
	WRITE_WB_REG_CASE(OFF, 0, REG, T, VAL);		\
	WRITE_WB_REG_CASE(OFF, 1, REG, T, VAL);		\
	WRITE_WB_REG_CASE(OFF, 2, REG, T, VAL);		\
	WRITE_WB_REG_CASE(OFF, 3, REG, T, VAL);		\
	WRITE_WB_REG_CASE(OFF, 4, REG, T, VAL);		\
	WRITE_WB_REG_CASE(OFF, 5, REG, T, VAL);		\
	WRITE_WB_REG_CASE(OFF, 6, REG, T, VAL);		\
	WRITE_WB_REG_CASE(OFF, 7, REG, T, VAL);

static u64 read_wb_reg(int reg, int n, int t)
{
	u64 val = 0;

	switch (reg + n) {
	GEN_READ_WB_REG_CASES(CSR_CFG_ADDR, ADDR, t, val);
	GEN_READ_WB_REG_CASES(CSR_CFG_MASK, MASK, t, val);
	GEN_READ_WB_REG_CASES(CSR_CFG_CTRL, CTRL, t, val);
	GEN_READ_WB_REG_CASES(CSR_CFG_ASID, ASID, t, val);
	default:
		pr_warn("Attempt to read from unknown breakpoint register %d\n", n);
	}

	return val;
}
NOKPROBE_SYMBOL(read_wb_reg);

static void write_wb_reg(int reg, int n, int t, u64 val)
{
	switch (reg + n) {
	GEN_WRITE_WB_REG_CASES(CSR_CFG_ADDR, ADDR, t, val);
	GEN_WRITE_WB_REG_CASES(CSR_CFG_MASK, MASK, t, val);
	GEN_WRITE_WB_REG_CASES(CSR_CFG_CTRL, CTRL, t, val);
	GEN_WRITE_WB_REG_CASES(CSR_CFG_ASID, ASID, t, val);
	default:
		pr_warn("Attempt to write to unknown breakpoint register %d\n", n);
	}
}
NOKPROBE_SYMBOL(write_wb_reg);

enum hw_breakpoint_ops {
	HW_BREAKPOINT_INSTALL,
	HW_BREAKPOINT_UNINSTALL,
};

/*
 * hw_breakpoint_slot_setup - Find and setup a perf slot according to operations
 *
 * @slots: pointer to array of slots
 * @max_slots: max number of slots
 * @bp: perf_event to setup
 * @ops: operation to be carried out on the slot
 *
 * Return:
 *	slot index on success
 *	-ENOSPC if no slot is available/matches
 *	-EINVAL on wrong operations parameter
 */

static int hw_breakpoint_slot_setup(struct perf_event **slots, int max_slots,
				    struct perf_event *bp, enum hw_breakpoint_ops ops)
{
	int i;
	struct perf_event **slot;

	for (i = 0; i < max_slots; ++i) {
		slot = &slots[i];
		switch (ops) {
		case HW_BREAKPOINT_INSTALL:
			if (!*slot) {
				*slot = bp;
				return i;
			}
			break;
		case HW_BREAKPOINT_UNINSTALL:
			if (*slot == bp) {
				*slot = NULL;
				return i;
			}
			break;
		default:
			pr_warn_once("Unhandled hw breakpoint ops %d\n", ops);
			return -EINVAL;
		}
	}

	return -ENOSPC;
}

void ptrace_hw_copy_thread(struct task_struct *tsk)
{
	memset(tsk->thread.hbp_break, 0, sizeof(tsk->thread.hbp_break));
	memset(tsk->thread.hbp_watch, 0, sizeof(tsk->thread.hbp_watch));
}

/*
 * Unregister breakpoints from this task and reset the pointers in the thread_struct.
 */
void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
{
	int i;
	struct thread_struct *t = &tsk->thread;

	for (i = 0; i < LOONGARCH_MAX_BRP; i++) {
		if (t->hbp_break[i]) {
			unregister_hw_breakpoint(t->hbp_break[i]);
			t->hbp_break[i] = NULL;
		}
	}

	for (i = 0; i < LOONGARCH_MAX_WRP; i++) {
		if (t->hbp_watch[i]) {
			unregister_hw_breakpoint(t->hbp_watch[i]);
			t->hbp_watch[i] = NULL;
		}
	}
}

static int hw_breakpoint_control(struct perf_event *bp,
				 enum hw_breakpoint_ops ops)
{
	u32 ctrl;
	int i, max_slots, enable;
	struct perf_event **slots;
	struct arch_hw_breakpoint *info = counter_arch_bp(bp);

	if (info->ctrl.type == LOONGARCH_BREAKPOINT_EXECUTE) {
		/* Breakpoint */
		slots = this_cpu_ptr(bp_on_reg);
		max_slots = boot_cpu_data.watch_ireg_count;
	} else {
		/* Watchpoint */
		slots = this_cpu_ptr(wp_on_reg);
		max_slots = boot_cpu_data.watch_dreg_count;
	}

	i = hw_breakpoint_slot_setup(slots, max_slots, bp, ops);

	if (WARN_ONCE(i < 0, "Can't find any breakpoint slot"))
		return i;

	switch (ops) {
	case HW_BREAKPOINT_INSTALL:
		/* Set the FWPnCFG/MWPnCFG 1~4 register. */
		write_wb_reg(CSR_CFG_ADDR, i, 0, info->address);
		write_wb_reg(CSR_CFG_ADDR, i, 1, info->address);
		write_wb_reg(CSR_CFG_MASK, i, 0, info->mask);
		write_wb_reg(CSR_CFG_MASK, i, 1, info->mask);
		write_wb_reg(CSR_CFG_ASID, i, 0, 0);
		write_wb_reg(CSR_CFG_ASID, i, 1, 0);
		if (info->ctrl.type == LOONGARCH_BREAKPOINT_EXECUTE) {
			write_wb_reg(CSR_CFG_CTRL, i, 0, CTRL_PLV_ENABLE);
		} else {
			ctrl = encode_ctrl_reg(info->ctrl);
			write_wb_reg(CSR_CFG_CTRL, i, 1, ctrl | CTRL_PLV_ENABLE |
				     1 << MWPnCFG3_LoadEn | 1 << MWPnCFG3_StoreEn);
		}
		enable = csr_read64(LOONGARCH_CSR_CRMD);
		csr_write64(CSR_CRMD_WE | enable, LOONGARCH_CSR_CRMD);
		break;
	case HW_BREAKPOINT_UNINSTALL:
		/* Reset the FWPnCFG/MWPnCFG 1~4 register. */
		write_wb_reg(CSR_CFG_ADDR, i, 0, 0);
		write_wb_reg(CSR_CFG_ADDR, i, 1, 0);
		write_wb_reg(CSR_CFG_MASK, i, 0, 0);
		write_wb_reg(CSR_CFG_MASK, i, 1, 0);
		write_wb_reg(CSR_CFG_CTRL, i, 0, 0);
		write_wb_reg(CSR_CFG_CTRL, i, 1, 0);
		write_wb_reg(CSR_CFG_ASID, i, 0, 0);
		write_wb_reg(CSR_CFG_ASID, i, 1, 0);
		break;
	}

	return 0;
}

/*
 * Install a perf counter breakpoint.
 */
int arch_install_hw_breakpoint(struct perf_event *bp)
{
	return hw_breakpoint_control(bp, HW_BREAKPOINT_INSTALL);
}

void arch_uninstall_hw_breakpoint(struct perf_event *bp)
{
	hw_breakpoint_control(bp, HW_BREAKPOINT_UNINSTALL);
}

static int get_hbp_len(u8 hbp_len)
{
	unsigned int len_in_bytes = 0;

	switch (hbp_len) {
	case LOONGARCH_BREAKPOINT_LEN_1:
		len_in_bytes = 1;
		break;
	case LOONGARCH_BREAKPOINT_LEN_2:
		len_in_bytes = 2;
		break;
	case LOONGARCH_BREAKPOINT_LEN_4:
		len_in_bytes = 4;
		break;
	case LOONGARCH_BREAKPOINT_LEN_8:
		len_in_bytes = 8;
		break;
	}

	return len_in_bytes;
}

/*
 * Check whether bp virtual address is in kernel space.
 */
int arch_check_bp_in_kernelspace(struct arch_hw_breakpoint *hw)
{
	unsigned int len;
	unsigned long va;

	va = hw->address;
	len = get_hbp_len(hw->ctrl.len);

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

/*
 * Extract generic type and length encodings from an arch_hw_breakpoint_ctrl.
 * Hopefully this will disappear when ptrace can bypass the conversion
 * to generic breakpoint descriptions.
 */
int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
			   int *gen_len, int *gen_type, int *offset)
{
	/* Type */
	switch (ctrl.type) {
	case LOONGARCH_BREAKPOINT_EXECUTE:
		*gen_type = HW_BREAKPOINT_X;
		break;
	case LOONGARCH_BREAKPOINT_LOAD:
		*gen_type = HW_BREAKPOINT_R;
		break;
	case LOONGARCH_BREAKPOINT_STORE:
		*gen_type = HW_BREAKPOINT_W;
		break;
	case LOONGARCH_BREAKPOINT_LOAD | LOONGARCH_BREAKPOINT_STORE:
		*gen_type = HW_BREAKPOINT_RW;
		break;
	default:
		return -EINVAL;
	}

	if (!ctrl.len)
		return -EINVAL;

	*offset = __ffs(ctrl.len);

	/* Len */
	switch (ctrl.len) {
	case LOONGARCH_BREAKPOINT_LEN_1:
		*gen_len = HW_BREAKPOINT_LEN_1;
		break;
	case LOONGARCH_BREAKPOINT_LEN_2:
		*gen_len = HW_BREAKPOINT_LEN_2;
		break;
	case LOONGARCH_BREAKPOINT_LEN_4:
		*gen_len = HW_BREAKPOINT_LEN_4;
		break;
	case LOONGARCH_BREAKPOINT_LEN_8:
		*gen_len = HW_BREAKPOINT_LEN_8;
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

/*
 * Construct an arch_hw_breakpoint from a perf_event.
 */
static int arch_build_bp_info(struct perf_event *bp,
			      const struct perf_event_attr *attr,
			      struct arch_hw_breakpoint *hw)
{
	/* Type */
	switch (attr->bp_type) {
	case HW_BREAKPOINT_X:
		hw->ctrl.type = LOONGARCH_BREAKPOINT_EXECUTE;
		break;
	case HW_BREAKPOINT_R:
		hw->ctrl.type = LOONGARCH_BREAKPOINT_LOAD;
		break;
	case HW_BREAKPOINT_W:
		hw->ctrl.type = LOONGARCH_BREAKPOINT_STORE;
		break;
	case HW_BREAKPOINT_RW:
		hw->ctrl.type = LOONGARCH_BREAKPOINT_LOAD | LOONGARCH_BREAKPOINT_STORE;
		break;
	default:
		return -EINVAL;
	}

	/* Len */
	switch (attr->bp_len) {
	case HW_BREAKPOINT_LEN_1:
		hw->ctrl.len = LOONGARCH_BREAKPOINT_LEN_1;
		break;
	case HW_BREAKPOINT_LEN_2:
		hw->ctrl.len = LOONGARCH_BREAKPOINT_LEN_2;
		break;
	case HW_BREAKPOINT_LEN_4:
		hw->ctrl.len = LOONGARCH_BREAKPOINT_LEN_4;
		break;
	case HW_BREAKPOINT_LEN_8:
		hw->ctrl.len = LOONGARCH_BREAKPOINT_LEN_8;
		break;
	default:
		return -EINVAL;
	}

	/* Address */
	hw->address = attr->bp_addr;

	return 0;
}

/*
 * Validate the arch-specific HW Breakpoint register settings.
 */
int hw_breakpoint_arch_parse(struct perf_event *bp,
			     const struct perf_event_attr *attr,
			     struct arch_hw_breakpoint *hw)
{
	int ret;
	u64 alignment_mask, offset;

	/* Build the arch_hw_breakpoint. */
	ret = arch_build_bp_info(bp, attr, hw);
	if (ret)
		return ret;

	if (hw->ctrl.type != LOONGARCH_BREAKPOINT_EXECUTE)
		alignment_mask = 0x7;
	else
		alignment_mask = 0x3;
	offset = hw->address & alignment_mask;

	hw->address &= ~alignment_mask;
	hw->ctrl.len <<= offset;

	return 0;
}

static void update_bp_registers(struct pt_regs *regs, int enable, int type)
{
	u32 ctrl;
	int i, max_slots;
	struct perf_event **slots;
	struct arch_hw_breakpoint *info;

	switch (type) {
	case 0:
		slots = this_cpu_ptr(bp_on_reg);
		max_slots = boot_cpu_data.watch_ireg_count;
		break;
	case 1:
		slots = this_cpu_ptr(wp_on_reg);
		max_slots = boot_cpu_data.watch_dreg_count;
		break;
	default:
		return;
	}

	for (i = 0; i < max_slots; ++i) {
		if (!slots[i])
			continue;

		info = counter_arch_bp(slots[i]);
		if (enable) {
			if ((info->ctrl.type == LOONGARCH_BREAKPOINT_EXECUTE) && (type == 0)) {
				write_wb_reg(CSR_CFG_CTRL, i, 0, CTRL_PLV_ENABLE);
				write_wb_reg(CSR_CFG_CTRL, i, 0, CTRL_PLV_ENABLE);
			} else {
				ctrl = read_wb_reg(CSR_CFG_CTRL, i, 1);
				if (info->ctrl.type == LOONGARCH_BREAKPOINT_LOAD)
					ctrl |= 0x1 << MWPnCFG3_LoadEn;
				if (info->ctrl.type == LOONGARCH_BREAKPOINT_STORE)
					ctrl |= 0x1 << MWPnCFG3_StoreEn;
				write_wb_reg(CSR_CFG_CTRL, i, 1, ctrl);
			}
			regs->csr_prmd |= CSR_PRMD_PWE;
		} else {
			if ((info->ctrl.type == LOONGARCH_BREAKPOINT_EXECUTE) && (type == 0)) {
				write_wb_reg(CSR_CFG_CTRL, i, 0, 0);
			} else {
				ctrl = read_wb_reg(CSR_CFG_CTRL, i, 1);
				if (info->ctrl.type == LOONGARCH_BREAKPOINT_LOAD)
					ctrl &= ~0x1 << MWPnCFG3_LoadEn;
				if (info->ctrl.type == LOONGARCH_BREAKPOINT_STORE)
					ctrl &= ~0x1 << MWPnCFG3_StoreEn;
				write_wb_reg(CSR_CFG_CTRL, i, 1, ctrl);
			}
			regs->csr_prmd &= ~CSR_PRMD_PWE;
		}
	}
}
NOKPROBE_SYMBOL(update_bp_registers);

/*
 * Debug exception handlers.
 */
void breakpoint_handler(struct pt_regs *regs)
{
	int i;
	struct perf_event *bp, **slots;

	slots = this_cpu_ptr(bp_on_reg);

	for (i = 0; i < boot_cpu_data.watch_ireg_count; ++i) {
		bp = slots[i];
		if (bp == NULL)
			continue;
		perf_bp_event(bp, regs);
	}
	update_bp_registers(regs, 0, 0);
}
NOKPROBE_SYMBOL(breakpoint_handler);

void watchpoint_handler(struct pt_regs *regs)
{
	int i;
	struct perf_event *wp, **slots;

	slots = this_cpu_ptr(wp_on_reg);

	for (i = 0; i < boot_cpu_data.watch_dreg_count; ++i) {
		wp = slots[i];
		if (wp == NULL)
			continue;
		perf_bp_event(wp, regs);
	}
	update_bp_registers(regs, 0, 1);
}
NOKPROBE_SYMBOL(watchpoint_handler);

static int __init arch_hw_breakpoint_init(void)
{
	int cpu;

	boot_cpu_data.watch_ireg_count = get_num_brps();
	boot_cpu_data.watch_dreg_count = get_num_wrps();

	pr_info("Found %d breakpoint and %d watchpoint registers.\n",
		boot_cpu_data.watch_ireg_count, boot_cpu_data.watch_dreg_count);

	for (cpu = 1; cpu < NR_CPUS; cpu++) {
		cpu_data[cpu].watch_ireg_count = boot_cpu_data.watch_ireg_count;
		cpu_data[cpu].watch_dreg_count = boot_cpu_data.watch_dreg_count;
	}

	return 0;
}
arch_initcall(arch_hw_breakpoint_init);

void hw_breakpoint_thread_switch(struct task_struct *next)
{
	u64 addr, mask;
	struct pt_regs *regs = task_pt_regs(next);

	if (test_tsk_thread_flag(next, TIF_SINGLESTEP)) {
		addr = read_wb_reg(CSR_CFG_ADDR, 0, 0);
		mask = read_wb_reg(CSR_CFG_MASK, 0, 0);
		if (!((regs->csr_era ^ addr) & ~mask))
			csr_write32(CSR_FWPC_SKIP, LOONGARCH_CSR_FWPS);
		regs->csr_prmd |= CSR_PRMD_PWE;
	} else {
		/* Update breakpoints */
		update_bp_registers(regs, 1, 0);
		/* Update watchpoints */
		update_bp_registers(regs, 1, 1);
	}
}

void hw_breakpoint_pmu_read(struct perf_event *bp)
{
}

/*
 * Dummy function to register with die_notifier.
 */
int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
				    unsigned long val, void *data)
{
	return NOTIFY_DONE;
}
