/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/mutex.h>
#include <linux/bpf.h>
#include <linux/bpf_verifier.h>

#include "io_uring.h"
#include "register.h"
#include "loop.h"
#include "memmap.h"
#include "bpf-ops.h"

static DEFINE_MUTEX(io_bpf_ctrl_mutex);
static const struct btf_type *loop_params_type;

__bpf_kfunc_start_defs();

__bpf_kfunc int bpf_io_uring_submit_sqes(struct iou_ctx *loop_ctx, u32 nr)
{
	struct io_ring_ctx *ctx = io_loop_demangle_ctx(loop_ctx);

	return io_submit_sqes(ctx, nr);
}

__bpf_kfunc
__u8 *bpf_io_uring_get_region(struct iou_ctx *loop_ctx, __u32 region_id,
			      const size_t rdwr_buf_size)
{
	struct io_ring_ctx *ctx = io_loop_demangle_ctx(loop_ctx);
	struct io_mapped_region *r;

	lockdep_assert_held(&ctx->uring_lock);

	switch (region_id) {
	case IOU_REGION_MEM:
		r = &ctx->param_region;
		break;
	case IOU_REGION_CQ:
		r = &ctx->ring_region;
		break;
	case IOU_REGION_SQ:
		r = &ctx->sq_region;
		break;
	default:
		return NULL;
	}

	if (unlikely(rdwr_buf_size > io_region_size(r)))
		return NULL;
	return io_region_get_ptr(r);
}

__bpf_kfunc_end_defs();

BTF_KFUNCS_START(io_uring_kfunc_set)
BTF_ID_FLAGS(func, bpf_io_uring_submit_sqes, KF_SLEEPABLE);
BTF_ID_FLAGS(func, bpf_io_uring_get_region, KF_RET_NULL);
BTF_KFUNCS_END(io_uring_kfunc_set)

static const struct btf_kfunc_id_set bpf_io_uring_kfunc_set = {
	.owner = THIS_MODULE,
	.set = &io_uring_kfunc_set,
};

static int io_bpf_ops__loop_step(struct iou_ctx *ctx,
				 struct iou_loop_params *lp)
{
	return IOU_LOOP_STOP;
}

static struct io_uring_bpf_ops io_bpf_ops_stubs = {
	.loop_step = io_bpf_ops__loop_step,
};

static bool bpf_io_is_valid_access(int off, int size,
				    enum bpf_access_type type,
				    const struct bpf_prog *prog,
				    struct bpf_insn_access_aux *info)
{
	if (type != BPF_READ)
		return false;
	if (off < 0 || off >= sizeof(__u64) * MAX_BPF_FUNC_ARGS)
		return false;
	if (off % size != 0)
		return false;

	return btf_ctx_access(off, size, type, prog, info);
}

static int bpf_io_btf_struct_access(struct bpf_verifier_log *log,
				    const struct bpf_reg_state *reg, int off,
				    int size)
{
	const struct btf_type *t = btf_type_by_id(reg->btf, reg->btf_id);

	if (t == loop_params_type) {
		if (off + size <= offsetofend(struct iou_loop_params, cq_wait_idx))
			return SCALAR_VALUE;
	}

	return -EACCES;
}

static const struct bpf_verifier_ops bpf_io_verifier_ops = {
	.get_func_proto = bpf_base_func_proto,
	.is_valid_access = bpf_io_is_valid_access,
	.btf_struct_access = bpf_io_btf_struct_access,
};

static const struct btf_type *
io_lookup_struct_type(struct btf *btf, const char *name)
{
	s32 type_id;

	type_id = btf_find_by_name_kind(btf, name, BTF_KIND_STRUCT);
	if (type_id < 0)
		return NULL;
	return btf_type_by_id(btf, type_id);
}

static int bpf_io_init(struct btf *btf)
{
	int ret;

	loop_params_type = io_lookup_struct_type(btf, "iou_loop_params");
	if (!loop_params_type) {
		pr_err("io_uring: Failed to locate iou_loop_params\n");
		return -EINVAL;
	}

	ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,
					&bpf_io_uring_kfunc_set);
	if (ret) {
		pr_err("io_uring: Failed to register kfuncs (%d)\n", ret);
		return ret;
	}
	return 0;
}

static int bpf_io_check_member(const struct btf_type *t,
				const struct btf_member *member,
				const struct bpf_prog *prog)
{
	return 0;
}

static int bpf_io_init_member(const struct btf_type *t,
			       const struct btf_member *member,
			       void *kdata, const void *udata)
{
	u32 moff = __btf_member_bit_offset(t, member) / 8;
	const struct io_uring_bpf_ops *uops = udata;
	struct io_uring_bpf_ops *ops = kdata;

	switch (moff) {
	case offsetof(struct io_uring_bpf_ops, ring_fd):
		ops->ring_fd = uops->ring_fd;
		return 1;
	}
	return 0;
}

static int io_install_bpf(struct io_ring_ctx *ctx, struct io_uring_bpf_ops *ops)
{
	if (ctx->flags & (IORING_SETUP_SQPOLL | IORING_SETUP_IOPOLL))
		return -EOPNOTSUPP;
	if (!(ctx->flags & IORING_SETUP_DEFER_TASKRUN))
		return -EOPNOTSUPP;

	if (ctx->bpf_ops)
		return -EBUSY;
	if (ops->priv)
		return -EBUSY;
	if (WARN_ON_ONCE(!ops->loop_step))
		return -EINVAL;

	ops->priv = ctx;
	ctx->bpf_ops = ops;
	ctx->loop_step = ops->loop_step;
	return 0;
}

static int bpf_io_reg(void *kdata, struct bpf_link *link)
{
	struct io_uring_bpf_ops *ops = kdata;
	struct io_ring_ctx *ctx;
	struct file *file;
	int ret = -EBUSY;

	file = io_uring_ctx_get_file(ops->ring_fd, false);
	if (IS_ERR(file))
		return PTR_ERR(file);
	ctx = file->private_data;

	scoped_guard(mutex, &io_bpf_ctrl_mutex) {
		guard(mutex)(&ctx->uring_lock);
		ret = io_install_bpf(ctx, ops);
	}

	fput(file);
	return ret;
}

static void io_eject_bpf(struct io_ring_ctx *ctx)
{
	struct io_uring_bpf_ops *ops = ctx->bpf_ops;

	if (WARN_ON_ONCE(!ops))
		return;
	if (WARN_ON_ONCE(ops->priv != ctx))
		return;

	ops->priv = NULL;
	ctx->bpf_ops = NULL;
	ctx->loop_step = NULL;
}

static void bpf_io_unreg(void *kdata, struct bpf_link *link)
{
	struct io_uring_bpf_ops *ops = kdata;
	struct io_ring_ctx *ctx;

	guard(mutex)(&io_bpf_ctrl_mutex);
	ctx = ops->priv;
	if (ctx) {
		guard(mutex)(&ctx->uring_lock);
		if (WARN_ON_ONCE(ctx->bpf_ops != ops))
			return;

		io_eject_bpf(ctx);
	}
}

void io_unregister_bpf_ops(struct io_ring_ctx *ctx)
{
	/*
	 * ->bpf_ops is write protected by io_bpf_ctrl_mutex and uring_lock,
	 * and read protected by either. Try to avoid taking the global lock
	 * for rings that never had any bpf installed.
	 */
	scoped_guard(mutex, &ctx->uring_lock) {
		if (!ctx->bpf_ops)
			return;
	}

	guard(mutex)(&io_bpf_ctrl_mutex);
	guard(mutex)(&ctx->uring_lock);
	if (ctx->bpf_ops)
		io_eject_bpf(ctx);
}

static struct bpf_struct_ops bpf_ring_ops = {
	.verifier_ops = &bpf_io_verifier_ops,
	.reg = bpf_io_reg,
	.unreg = bpf_io_unreg,
	.check_member = bpf_io_check_member,
	.init_member = bpf_io_init_member,
	.init = bpf_io_init,
	.cfi_stubs = &io_bpf_ops_stubs,
	.name = "io_uring_bpf_ops",
	.owner = THIS_MODULE,
};

static int __init io_uring_bpf_init(void)
{
	int ret;

	ret = register_bpf_struct_ops(&bpf_ring_ops, io_uring_bpf_ops);
	if (ret) {
		pr_err("io_uring: Failed to register struct_ops (%d)\n", ret);
		return ret;
	}

	return 0;
}
__initcall(io_uring_bpf_init);
