// SPDX-License-Identifier: GPL-2.0
/*
 * bpf_kwork_top.c
 *
 * Copyright (c) 2022  Huawei Inc,  Yang Jihong <yangjihong1@huawei.com>
 */

#include <time.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

#include <linux/time64.h>

#include "util/debug.h"
#include "util/evsel.h"
#include "util/kwork.h"

#include <bpf/bpf.h>
#include <perf/cpumap.h>

#include "util/bpf_skel/kwork_top.skel.h"

/*
 * This should be in sync with "util/kwork_top.bpf.c"
 */
#define MAX_COMMAND_LEN 16

struct time_data {
	__u64 timestamp;
};

struct work_data {
	__u64 runtime;
};

struct task_data {
	__u32 tgid;
	__u32 is_kthread;
	char comm[MAX_COMMAND_LEN];
};

struct work_key {
	__u32 type;
	__u32 pid;
	__u64 task_p;
};

struct task_key {
	__u32 pid;
	__u32 cpu;
};

struct kwork_class_bpf {
	struct kwork_class *class;
	void (*load_prepare)(void);
};

static struct kwork_top_bpf *skel;

void perf_kwork__top_start(void)
{
	struct timespec ts;

	clock_gettime(CLOCK_MONOTONIC, &ts);
	skel->bss->from_timestamp = (u64)ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
	skel->bss->enabled = 1;
	pr_debug("perf kwork top start at: %lld\n", skel->bss->from_timestamp);
}

void perf_kwork__top_finish(void)
{
	struct timespec ts;

	skel->bss->enabled = 0;
	clock_gettime(CLOCK_MONOTONIC, &ts);
	skel->bss->to_timestamp = (u64)ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
	pr_debug("perf kwork top finish at: %lld\n", skel->bss->to_timestamp);
}

static void irq_load_prepare(void)
{
	bpf_program__set_autoload(skel->progs.on_irq_handler_entry, true);
	bpf_program__set_autoload(skel->progs.on_irq_handler_exit, true);
}

static struct kwork_class_bpf kwork_irq_bpf = {
	.load_prepare = irq_load_prepare,
};

static void softirq_load_prepare(void)
{
	bpf_program__set_autoload(skel->progs.on_softirq_entry, true);
	bpf_program__set_autoload(skel->progs.on_softirq_exit, true);
}

static struct kwork_class_bpf kwork_softirq_bpf = {
	.load_prepare = softirq_load_prepare,
};

static void sched_load_prepare(void)
{
	bpf_program__set_autoload(skel->progs.on_switch, true);
}

static struct kwork_class_bpf kwork_sched_bpf = {
	.load_prepare = sched_load_prepare,
};

static struct kwork_class_bpf *
kwork_class_bpf_supported_list[KWORK_CLASS_MAX] = {
	[KWORK_CLASS_IRQ]	= &kwork_irq_bpf,
	[KWORK_CLASS_SOFTIRQ]	= &kwork_softirq_bpf,
	[KWORK_CLASS_SCHED]	= &kwork_sched_bpf,
};

static bool valid_kwork_class_type(enum kwork_class_type type)
{
	return type >= 0 && type < KWORK_CLASS_MAX;
}

static int setup_filters(struct perf_kwork *kwork)
{
	u8 val = 1;
	int i, nr_cpus, fd;
	struct perf_cpu_map *map;

	if (kwork->cpu_list) {
		fd = bpf_map__fd(skel->maps.kwork_top_cpu_filter);
		if (fd < 0) {
			pr_debug("Invalid cpu filter fd\n");
			return -1;
		}

		map = perf_cpu_map__new(kwork->cpu_list);
		if (!map) {
			pr_debug("Invalid cpu_list\n");
			return -1;
		}

		nr_cpus = libbpf_num_possible_cpus();
		for (i = 0; i < perf_cpu_map__nr(map); i++) {
			struct perf_cpu cpu = perf_cpu_map__cpu(map, i);

			if (cpu.cpu >= nr_cpus) {
				perf_cpu_map__put(map);
				pr_err("Requested cpu %d too large\n", cpu.cpu);
				return -1;
			}
			bpf_map_update_elem(fd, &cpu.cpu, &val, BPF_ANY);
		}
		perf_cpu_map__put(map);

		skel->bss->has_cpu_filter = 1;
	}

	return 0;
}

int perf_kwork__top_prepare_bpf(struct perf_kwork *kwork __maybe_unused)
{
	struct bpf_program *prog;
	struct kwork_class *class;
	struct kwork_class_bpf *class_bpf;
	enum kwork_class_type type;

	skel = kwork_top_bpf__open();
	if (!skel) {
		pr_debug("Failed to open kwork top skeleton\n");
		return -1;
	}

	/*
	 * set all progs to non-autoload,
	 * then set corresponding progs according to config
	 */
	bpf_object__for_each_program(prog, skel->obj)
		bpf_program__set_autoload(prog, false);

	list_for_each_entry(class, &kwork->class_list, list) {
		type = class->type;
		if (!valid_kwork_class_type(type) ||
		    !kwork_class_bpf_supported_list[type]) {
			pr_err("Unsupported bpf trace class %s\n", class->name);
			goto out;
		}

		class_bpf = kwork_class_bpf_supported_list[type];
		class_bpf->class = class;

		if (class_bpf->load_prepare)
			class_bpf->load_prepare();
	}

	if (kwork_top_bpf__load(skel)) {
		pr_debug("Failed to load kwork top skeleton\n");
		goto out;
	}

	if (setup_filters(kwork))
		goto out;

	if (kwork_top_bpf__attach(skel)) {
		pr_debug("Failed to attach kwork top skeleton\n");
		goto out;
	}

	return 0;

out:
	kwork_top_bpf__destroy(skel);
	return -1;
}

static void read_task_info(struct kwork_work *work)
{
	int fd;
	struct task_data data;
	struct task_key key = {
		.pid = work->id,
		.cpu = work->cpu,
	};

	fd = bpf_map__fd(skel->maps.kwork_top_tasks);
	if (fd < 0) {
		pr_debug("Invalid top tasks map fd\n");
		return;
	}

	if (!bpf_map_lookup_elem(fd, &key, &data)) {
		work->tgid = data.tgid;
		work->is_kthread = data.is_kthread;
		work->name = strdup(data.comm);
	}
}
static int add_work(struct perf_kwork *kwork, struct work_key *key,
		    struct work_data *data, int cpu)
{
	struct kwork_class_bpf *bpf_trace;
	struct kwork_work *work;
	struct kwork_work tmp = {
		.id = key->pid,
		.cpu = cpu,
		.name = NULL,
	};
	enum kwork_class_type type = key->type;

	if (!valid_kwork_class_type(type)) {
		pr_debug("Invalid class type %d to add work\n", type);
		return -1;
	}

	bpf_trace = kwork_class_bpf_supported_list[type];
	tmp.class = bpf_trace->class;

	work = perf_kwork_add_work(kwork, tmp.class, &tmp);
	if (!work)
		return -1;

	work->total_runtime = data->runtime;
	read_task_info(work);

	return 0;
}

int perf_kwork__top_read_bpf(struct perf_kwork *kwork)
{
	int i, fd, nr_cpus;
	struct work_data *data;
	struct work_key key, prev;

	fd = bpf_map__fd(skel->maps.kwork_top_works);
	if (fd < 0) {
		pr_debug("Invalid top runtime fd\n");
		return -1;
	}

	nr_cpus = libbpf_num_possible_cpus();
	data = calloc(nr_cpus, sizeof(struct work_data));
	if (!data)
		return -1;

	memset(&prev, 0, sizeof(prev));
	while (!bpf_map_get_next_key(fd, &prev, &key)) {
		if ((bpf_map_lookup_elem(fd, &key, data)) != 0) {
			pr_debug("Failed to lookup top elem\n");
			return -1;
		}

		for (i = 0; i < nr_cpus; i++) {
			if (data[i].runtime == 0)
				continue;

			if (add_work(kwork, &key, &data[i], i))
				return -1;
		}
		prev = key;
	}
	free(data);

	return 0;
}

void perf_kwork__top_cleanup_bpf(void)
{
	kwork_top_bpf__destroy(skel);
}
