/*
 * kvm trace
 *
 * It is designed to allow debugging traces of kvm to be generated
 * on UP / SMP machines.  Each trace entry can be timestamped so that
 * it's possible to reconstruct a chronological record of trace events.
 * The implementation refers to blktrace kernel support.
 *
 * Copyright (c) 2008 Intel Corporation
 * Copyright (C) 2006 Jens Axboe <axboe@kernel.dk>
 *
 * Authors: Feng(Eric) Liu, eric.e.liu@intel.com
 *
 * Date:    Feb 2008
 */

#include <linux/module.h>
#include <linux/relay.h>
#include <linux/debugfs.h>
#include <linux/ktime.h>

#include <linux/kvm_host.h>

#define KVM_TRACE_STATE_RUNNING 	(1 << 0)
#define KVM_TRACE_STATE_PAUSE 		(1 << 1)
#define KVM_TRACE_STATE_CLEARUP 	(1 << 2)

struct kvm_trace {
	int trace_state;
	struct rchan *rchan;
	struct dentry *lost_file;
	atomic_t lost_records;
};
static struct kvm_trace *kvm_trace;

struct kvm_trace_probe {
	const char *name;
	const char *format;
	u32 timestamp_in;
	marker_probe_func *probe_func;
};

static inline int calc_rec_size(int timestamp, int extra)
{
	int rec_size = KVM_TRC_HEAD_SIZE;

	rec_size += extra;
	return timestamp ? rec_size += KVM_TRC_CYCLE_SIZE : rec_size;
}

static void kvm_add_trace(void *probe_private, void *call_data,
			  const char *format, va_list *args)
{
	struct kvm_trace_probe *p = probe_private;
	struct kvm_trace *kt = kvm_trace;
	struct kvm_trace_rec rec;
	struct kvm_vcpu *vcpu;
	int    i, size;
	u32    extra;

	if (unlikely(kt->trace_state != KVM_TRACE_STATE_RUNNING))
		return;

	rec.rec_val	= TRACE_REC_EVENT_ID(va_arg(*args, u32));
	vcpu		= va_arg(*args, struct kvm_vcpu *);
	rec.pid		= current->tgid;
	rec.vcpu_id	= vcpu->vcpu_id;

	extra   	= va_arg(*args, u32);
	WARN_ON(!(extra <= KVM_TRC_EXTRA_MAX));
	extra 		= min_t(u32, extra, KVM_TRC_EXTRA_MAX);

	rec.rec_val |= TRACE_REC_TCS(p->timestamp_in)
			| TRACE_REC_NUM_DATA_ARGS(extra);

	if (p->timestamp_in) {
		rec.u.timestamp.timestamp = ktime_to_ns(ktime_get());

		for (i = 0; i < extra; i++)
			rec.u.timestamp.extra_u32[i] = va_arg(*args, u32);
	} else {
		for (i = 0; i < extra; i++)
			rec.u.notimestamp.extra_u32[i] = va_arg(*args, u32);
	}

	size = calc_rec_size(p->timestamp_in, extra * sizeof(u32));
	relay_write(kt->rchan, &rec, size);
}

static struct kvm_trace_probe kvm_trace_probes[] = {
	{ "kvm_trace_entryexit", "%u %p %u %u %u %u %u %u", 1, kvm_add_trace },
	{ "kvm_trace_handler", "%u %p %u %u %u %u %u %u", 0, kvm_add_trace },
};

static int lost_records_get(void *data, u64 *val)
{
	struct kvm_trace *kt = data;

	*val = atomic_read(&kt->lost_records);
	return 0;
}

DEFINE_SIMPLE_ATTRIBUTE(kvm_trace_lost_ops, lost_records_get, NULL, "%llu\n");

/*
 *  The relay channel is used in "no-overwrite" mode, it keeps trace of how
 *  many times we encountered a full subbuffer, to tell user space app the
 *  lost records there were.
 */
static int kvm_subbuf_start_callback(struct rchan_buf *buf, void *subbuf,
				     void *prev_subbuf, size_t prev_padding)
{
	struct kvm_trace *kt;

	if (!relay_buf_full(buf)) {
		if (!prev_subbuf) {
			/*
			 * executed only once when the channel is opened
			 * save metadata as first record
			 */
			subbuf_start_reserve(buf, sizeof(u32));
			*(u32 *)subbuf = 0x12345678;
		}

		return 1;
	}

	kt = buf->chan->private_data;
	atomic_inc(&kt->lost_records);

	return 0;
}

static struct dentry *kvm_create_buf_file_callack(const char *filename,
						 struct dentry *parent,
						 int mode,
						 struct rchan_buf *buf,
						 int *is_global)
{
	return debugfs_create_file(filename, mode, parent, buf,
				   &relay_file_operations);
}

static int kvm_remove_buf_file_callback(struct dentry *dentry)
{
	debugfs_remove(dentry);
	return 0;
}

static struct rchan_callbacks kvm_relay_callbacks = {
	.subbuf_start 		= kvm_subbuf_start_callback,
	.create_buf_file 	= kvm_create_buf_file_callack,
	.remove_buf_file 	= kvm_remove_buf_file_callback,
};

static int do_kvm_trace_enable(struct kvm_user_trace_setup *kuts)
{
	struct kvm_trace *kt;
	int i, r = -ENOMEM;

	if (!kuts->buf_size || !kuts->buf_nr)
		return -EINVAL;

	kt = kzalloc(sizeof(*kt), GFP_KERNEL);
	if (!kt)
		goto err;

	r = -EIO;
	atomic_set(&kt->lost_records, 0);
	kt->lost_file = debugfs_create_file("lost_records", 0444, kvm_debugfs_dir,
					    kt, &kvm_trace_lost_ops);
	if (!kt->lost_file)
		goto err;

	kt->rchan = relay_open("trace", kvm_debugfs_dir, kuts->buf_size,
				kuts->buf_nr, &kvm_relay_callbacks, kt);
	if (!kt->rchan)
		goto err;

	kvm_trace = kt;

	for (i = 0; i < ARRAY_SIZE(kvm_trace_probes); i++) {
		struct kvm_trace_probe *p = &kvm_trace_probes[i];

		r = marker_probe_register(p->name, p->format, p->probe_func, p);
		if (r)
			printk(KERN_INFO "Unable to register probe %s\n",
			       p->name);
	}

	kvm_trace->trace_state = KVM_TRACE_STATE_RUNNING;

	return 0;
err:
	if (kt) {
		if (kt->lost_file)
			debugfs_remove(kt->lost_file);
		if (kt->rchan)
			relay_close(kt->rchan);
		kfree(kt);
	}
	return r;
}

static int kvm_trace_enable(char __user *arg)
{
	struct kvm_user_trace_setup kuts;
	int ret;

	ret = copy_from_user(&kuts, arg, sizeof(kuts));
	if (ret)
		return -EFAULT;

	ret = do_kvm_trace_enable(&kuts);
	if (ret)
		return ret;

	return 0;
}

static int kvm_trace_pause(void)
{
	struct kvm_trace *kt = kvm_trace;
	int r = -EINVAL;

	if (kt == NULL)
		return r;

	if (kt->trace_state == KVM_TRACE_STATE_RUNNING) {
		kt->trace_state = KVM_TRACE_STATE_PAUSE;
		relay_flush(kt->rchan);
		r = 0;
	}

	return r;
}

void kvm_trace_cleanup(void)
{
	struct kvm_trace *kt = kvm_trace;
	int i;

	if (kt == NULL)
		return;

	if (kt->trace_state == KVM_TRACE_STATE_RUNNING ||
	    kt->trace_state == KVM_TRACE_STATE_PAUSE) {

		kt->trace_state = KVM_TRACE_STATE_CLEARUP;

		for (i = 0; i < ARRAY_SIZE(kvm_trace_probes); i++) {
			struct kvm_trace_probe *p = &kvm_trace_probes[i];
			marker_probe_unregister(p->name, p->probe_func, p);
		}

		relay_close(kt->rchan);
		debugfs_remove(kt->lost_file);
		kfree(kt);
	}
}

int kvm_trace_ioctl(unsigned int ioctl, unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	long r = -EINVAL;

	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;

	switch (ioctl) {
	case KVM_TRACE_ENABLE:
		r = kvm_trace_enable(argp);
		break;
	case KVM_TRACE_PAUSE:
		r = kvm_trace_pause();
		break;
	case KVM_TRACE_DISABLE:
		r = 0;
		kvm_trace_cleanup();
		break;
	}

	return r;
}
