// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) 2023 SiFive
 * Author: Andy Chiu <andy.chiu@sifive.com>
 */
#include <linux/export.h>
#include <linux/sched/signal.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/prctl.h>

#include <asm/thread_info.h>
#include <asm/processor.h>
#include <asm/insn.h>
#include <asm/vector.h>
#include <asm/csr.h>
#include <asm/elf.h>
#include <asm/ptrace.h>
#include <asm/bug.h>

static bool riscv_v_implicit_uacc = IS_ENABLED(CONFIG_RISCV_ISA_V_DEFAULT_ENABLE);

unsigned long riscv_v_vsize __read_mostly;
EXPORT_SYMBOL_GPL(riscv_v_vsize);

int riscv_v_setup_vsize(void)
{
	unsigned long this_vsize;

	/* There are 32 vector registers with vlenb length. */
	riscv_v_enable();
	this_vsize = csr_read(CSR_VLENB) * 32;
	riscv_v_disable();

	if (!riscv_v_vsize) {
		riscv_v_vsize = this_vsize;
		return 0;
	}

	if (riscv_v_vsize != this_vsize) {
		WARN(1, "RISCV_ISA_V only supports one vlenb on SMP systems");
		return -EOPNOTSUPP;
	}

	return 0;
}

static bool insn_is_vector(u32 insn_buf)
{
	u32 opcode = insn_buf & __INSN_OPCODE_MASK;
	u32 width, csr;

	/*
	 * All V-related instructions, including CSR operations are 4-Byte. So,
	 * do not handle if the instruction length is not 4-Byte.
	 */
	if (unlikely(GET_INSN_LENGTH(insn_buf) != 4))
		return false;

	switch (opcode) {
	case RVV_OPCODE_VECTOR:
		return true;
	case RVV_OPCODE_VL:
	case RVV_OPCODE_VS:
		width = RVV_EXRACT_VL_VS_WIDTH(insn_buf);
		if (width == RVV_VL_VS_WIDTH_8 || width == RVV_VL_VS_WIDTH_16 ||
		    width == RVV_VL_VS_WIDTH_32 || width == RVV_VL_VS_WIDTH_64)
			return true;

		break;
	case RVG_OPCODE_SYSTEM:
		csr = RVG_EXTRACT_SYSTEM_CSR(insn_buf);
		if ((csr >= CSR_VSTART && csr <= CSR_VCSR) ||
		    (csr >= CSR_VL && csr <= CSR_VLENB))
			return true;
	}

	return false;
}

static int riscv_v_thread_zalloc(void)
{
	void *datap;

	datap = kzalloc(riscv_v_vsize, GFP_KERNEL);
	if (!datap)
		return -ENOMEM;

	current->thread.vstate.datap = datap;
	memset(&current->thread.vstate, 0, offsetof(struct __riscv_v_ext_state,
						    datap));
	return 0;
}

#define VSTATE_CTRL_GET_CUR(x) ((x) & PR_RISCV_V_VSTATE_CTRL_CUR_MASK)
#define VSTATE_CTRL_GET_NEXT(x) (((x) & PR_RISCV_V_VSTATE_CTRL_NEXT_MASK) >> 2)
#define VSTATE_CTRL_MAKE_NEXT(x) (((x) << 2) & PR_RISCV_V_VSTATE_CTRL_NEXT_MASK)
#define VSTATE_CTRL_GET_INHERIT(x) (!!((x) & PR_RISCV_V_VSTATE_CTRL_INHERIT))
static inline int riscv_v_ctrl_get_cur(struct task_struct *tsk)
{
	return VSTATE_CTRL_GET_CUR(tsk->thread.vstate_ctrl);
}

static inline int riscv_v_ctrl_get_next(struct task_struct *tsk)
{
	return VSTATE_CTRL_GET_NEXT(tsk->thread.vstate_ctrl);
}

static inline bool riscv_v_ctrl_test_inherit(struct task_struct *tsk)
{
	return VSTATE_CTRL_GET_INHERIT(tsk->thread.vstate_ctrl);
}

static inline void riscv_v_ctrl_set(struct task_struct *tsk, int cur, int nxt,
				    bool inherit)
{
	unsigned long ctrl;

	ctrl = cur & PR_RISCV_V_VSTATE_CTRL_CUR_MASK;
	ctrl |= VSTATE_CTRL_MAKE_NEXT(nxt);
	if (inherit)
		ctrl |= PR_RISCV_V_VSTATE_CTRL_INHERIT;
	tsk->thread.vstate_ctrl = ctrl;
}

bool riscv_v_vstate_ctrl_user_allowed(void)
{
	return riscv_v_ctrl_get_cur(current) == PR_RISCV_V_VSTATE_CTRL_ON;
}
EXPORT_SYMBOL_GPL(riscv_v_vstate_ctrl_user_allowed);

bool riscv_v_first_use_handler(struct pt_regs *regs)
{
	u32 __user *epc = (u32 __user *)regs->epc;
	u32 insn = (u32)regs->badaddr;

	/* Do not handle if V is not supported, or disabled */
	if (!(ELF_HWCAP & COMPAT_HWCAP_ISA_V))
		return false;

	/* If V has been enabled then it is not the first-use trap */
	if (riscv_v_vstate_query(regs))
		return false;

	/* Get the instruction */
	if (!insn) {
		if (__get_user(insn, epc))
			return false;
	}

	/* Filter out non-V instructions */
	if (!insn_is_vector(insn))
		return false;

	/* Sanity check. datap should be null by the time of the first-use trap */
	WARN_ON(current->thread.vstate.datap);

	/*
	 * Now we sure that this is a V instruction. And it executes in the
	 * context where VS has been off. So, try to allocate the user's V
	 * context and resume execution.
	 */
	if (riscv_v_thread_zalloc()) {
		force_sig(SIGBUS);
		return true;
	}
	riscv_v_vstate_on(regs);
	riscv_v_vstate_restore(current, regs);
	return true;
}

void riscv_v_vstate_ctrl_init(struct task_struct *tsk)
{
	bool inherit;
	int cur, next;

	if (!has_vector())
		return;

	next = riscv_v_ctrl_get_next(tsk);
	if (!next) {
		if (READ_ONCE(riscv_v_implicit_uacc))
			cur = PR_RISCV_V_VSTATE_CTRL_ON;
		else
			cur = PR_RISCV_V_VSTATE_CTRL_OFF;
	} else {
		cur = next;
	}
	/* Clear next mask if inherit-bit is not set */
	inherit = riscv_v_ctrl_test_inherit(tsk);
	if (!inherit)
		next = PR_RISCV_V_VSTATE_CTRL_DEFAULT;

	riscv_v_ctrl_set(tsk, cur, next, inherit);
}

long riscv_v_vstate_ctrl_get_current(void)
{
	if (!has_vector())
		return -EINVAL;

	return current->thread.vstate_ctrl & PR_RISCV_V_VSTATE_CTRL_MASK;
}

long riscv_v_vstate_ctrl_set_current(unsigned long arg)
{
	bool inherit;
	int cur, next;

	if (!has_vector())
		return -EINVAL;

	if (arg & ~PR_RISCV_V_VSTATE_CTRL_MASK)
		return -EINVAL;

	cur = VSTATE_CTRL_GET_CUR(arg);
	switch (cur) {
	case PR_RISCV_V_VSTATE_CTRL_OFF:
		/* Do not allow user to turn off V if current is not off */
		if (riscv_v_ctrl_get_cur(current) != PR_RISCV_V_VSTATE_CTRL_OFF)
			return -EPERM;

		break;
	case PR_RISCV_V_VSTATE_CTRL_ON:
		break;
	case PR_RISCV_V_VSTATE_CTRL_DEFAULT:
		cur = riscv_v_ctrl_get_cur(current);
		break;
	default:
		return -EINVAL;
	}

	next = VSTATE_CTRL_GET_NEXT(arg);
	inherit = VSTATE_CTRL_GET_INHERIT(arg);
	switch (next) {
	case PR_RISCV_V_VSTATE_CTRL_DEFAULT:
	case PR_RISCV_V_VSTATE_CTRL_OFF:
	case PR_RISCV_V_VSTATE_CTRL_ON:
		riscv_v_ctrl_set(current, cur, next, inherit);
		return 0;
	}

	return -EINVAL;
}

#ifdef CONFIG_SYSCTL

static struct ctl_table riscv_v_default_vstate_table[] = {
	{
		.procname	= "riscv_v_default_allow",
		.data		= &riscv_v_implicit_uacc,
		.maxlen		= sizeof(riscv_v_implicit_uacc),
		.mode		= 0644,
		.proc_handler	= proc_dobool,
	},
	{ }
};

static int __init riscv_v_sysctl_init(void)
{
	if (has_vector())
		if (!register_sysctl("abi", riscv_v_default_vstate_table))
			return -EINVAL;
	return 0;
}

#else /* ! CONFIG_SYSCTL */
static int __init riscv_v_sysctl_init(void) { return 0; }
#endif /* ! CONFIG_SYSCTL */

static int riscv_v_init(void)
{
	return riscv_v_sysctl_init();
}
core_initcall(riscv_v_init);
