/*
 * Xen hypercall batching.
 *
 * Xen allows multiple hypercalls to be issued at once, using the
 * multicall interface.  This allows the cost of trapping into the
 * hypervisor to be amortized over several calls.
 *
 * This file implements a simple interface for multicalls.  There's a
 * per-cpu buffer of outstanding multicalls.  When you want to queue a
 * multicall for issuing, you can allocate a multicall slot for the
 * call and its arguments, along with storage for space which is
 * pointed to by the arguments (for passing pointers to structures,
 * etc).  When the multicall is actually issued, all the space for the
 * commands and allocated memory is freed for reuse.
 *
 * Multicalls are flushed whenever any of the buffers get full, or
 * when explicitly requested.  There's no way to get per-multicall
 * return results back.  It will BUG if any of the multicalls fail.
 *
 * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007
 */
#include <linux/percpu.h>
#include <linux/hardirq.h>
#include <linux/debugfs.h>

#include <asm/xen/hypercall.h>

#include "multicalls.h"
#include "debugfs.h"

#define MC_BATCH	32

#define MC_DEBUG	1

#define MC_ARGS		(MC_BATCH * 16)


struct mc_buffer {
	struct multicall_entry entries[MC_BATCH];
#if MC_DEBUG
	struct multicall_entry debug[MC_BATCH];
#endif
	unsigned char args[MC_ARGS];
	struct callback {
		void (*fn)(void *);
		void *data;
	} callbacks[MC_BATCH];
	unsigned mcidx, argidx, cbidx;
};

static DEFINE_PER_CPU(struct mc_buffer, mc_buffer);
DEFINE_PER_CPU(unsigned long, xen_mc_irq_flags);

/* flush reasons 0- slots, 1- args, 2- callbacks */
enum flush_reasons
{
	FL_SLOTS,
	FL_ARGS,
	FL_CALLBACKS,

	FL_N_REASONS
};

#ifdef CONFIG_XEN_DEBUG_FS
#define NHYPERCALLS	40		/* not really */

static struct {
	unsigned histo[MC_BATCH+1];

	unsigned issued;
	unsigned arg_total;
	unsigned hypercalls;
	unsigned histo_hypercalls[NHYPERCALLS];

	unsigned flush[FL_N_REASONS];
} mc_stats;

static u8 zero_stats;

static inline void check_zero(void)
{
	if (unlikely(zero_stats)) {
		memset(&mc_stats, 0, sizeof(mc_stats));
		zero_stats = 0;
	}
}

static void mc_add_stats(const struct mc_buffer *mc)
{
	int i;

	check_zero();

	mc_stats.issued++;
	mc_stats.hypercalls += mc->mcidx;
	mc_stats.arg_total += mc->argidx;

	mc_stats.histo[mc->mcidx]++;
	for(i = 0; i < mc->mcidx; i++) {
		unsigned op = mc->entries[i].op;
		if (op < NHYPERCALLS)
			mc_stats.histo_hypercalls[op]++;
	}
}

static void mc_stats_flush(enum flush_reasons idx)
{
	check_zero();

	mc_stats.flush[idx]++;
}

#else  /* !CONFIG_XEN_DEBUG_FS */

static inline void mc_add_stats(const struct mc_buffer *mc)
{
}

static inline void mc_stats_flush(enum flush_reasons idx)
{
}
#endif	/* CONFIG_XEN_DEBUG_FS */

void xen_mc_flush(void)
{
	struct mc_buffer *b = &__get_cpu_var(mc_buffer);
	int ret = 0;
	unsigned long flags;
	int i;

	BUG_ON(preemptible());

	/* Disable interrupts in case someone comes in and queues
	   something in the middle */
	local_irq_save(flags);

	mc_add_stats(b);

	if (b->mcidx) {
#if MC_DEBUG
		memcpy(b->debug, b->entries,
		       b->mcidx * sizeof(struct multicall_entry));
#endif

		if (HYPERVISOR_multicall(b->entries, b->mcidx) != 0)
			BUG();
		for (i = 0; i < b->mcidx; i++)
			if (b->entries[i].result < 0)
				ret++;

#if MC_DEBUG
		if (ret) {
			printk(KERN_ERR "%d multicall(s) failed: cpu %d\n",
			       ret, smp_processor_id());
			dump_stack();
			for (i = 0; i < b->mcidx; i++) {
				printk(KERN_DEBUG "  call %2d/%d: op=%lu arg=[%lx] result=%ld\n",
				       i+1, b->mcidx,
				       b->debug[i].op,
				       b->debug[i].args[0],
				       b->entries[i].result);
			}
		}
#endif

		b->mcidx = 0;
		b->argidx = 0;
	} else
		BUG_ON(b->argidx != 0);

	local_irq_restore(flags);

	for (i = 0; i < b->cbidx; i++) {
		struct callback *cb = &b->callbacks[i];

		(*cb->fn)(cb->data);
	}
	b->cbidx = 0;

	BUG_ON(ret);
}

struct multicall_space __xen_mc_entry(size_t args)
{
	struct mc_buffer *b = &__get_cpu_var(mc_buffer);
	struct multicall_space ret;
	unsigned argidx = roundup(b->argidx, sizeof(u64));

	BUG_ON(preemptible());
	BUG_ON(b->argidx > MC_ARGS);

	if (b->mcidx == MC_BATCH ||
	    (argidx + args) > MC_ARGS) {
		mc_stats_flush(b->mcidx == MC_BATCH ? FL_SLOTS : FL_ARGS);
		xen_mc_flush();
		argidx = roundup(b->argidx, sizeof(u64));
	}

	ret.mc = &b->entries[b->mcidx];
	b->mcidx++;
	ret.args = &b->args[argidx];
	b->argidx = argidx + args;

	BUG_ON(b->argidx > MC_ARGS);
	return ret;
}

struct multicall_space xen_mc_extend_args(unsigned long op, size_t size)
{
	struct mc_buffer *b = &__get_cpu_var(mc_buffer);
	struct multicall_space ret = { NULL, NULL };

	BUG_ON(preemptible());
	BUG_ON(b->argidx > MC_ARGS);

	if (b->mcidx == 0)
		return ret;

	if (b->entries[b->mcidx - 1].op != op)
		return ret;

	if ((b->argidx + size) > MC_ARGS)
		return ret;

	ret.mc = &b->entries[b->mcidx - 1];
	ret.args = &b->args[b->argidx];
	b->argidx += size;

	BUG_ON(b->argidx > MC_ARGS);
	return ret;
}

void xen_mc_callback(void (*fn)(void *), void *data)
{
	struct mc_buffer *b = &__get_cpu_var(mc_buffer);
	struct callback *cb;

	if (b->cbidx == MC_BATCH) {
		mc_stats_flush(FL_CALLBACKS);
		xen_mc_flush();
	}

	cb = &b->callbacks[b->cbidx++];
	cb->fn = fn;
	cb->data = data;
}

#ifdef CONFIG_XEN_DEBUG_FS

static struct dentry *d_mc_debug;

static int __init xen_mc_debugfs(void)
{
	struct dentry *d_xen = xen_init_debugfs();

	if (d_xen == NULL)
		return -ENOMEM;

	d_mc_debug = debugfs_create_dir("multicalls", d_xen);

	debugfs_create_u8("zero_stats", 0644, d_mc_debug, &zero_stats);

	debugfs_create_u32("batches", 0444, d_mc_debug, &mc_stats.issued);
	debugfs_create_u32("hypercalls", 0444, d_mc_debug, &mc_stats.hypercalls);
	debugfs_create_u32("arg_total", 0444, d_mc_debug, &mc_stats.arg_total);

	xen_debugfs_create_u32_array("batch_histo", 0444, d_mc_debug,
				     mc_stats.histo, MC_BATCH);
	xen_debugfs_create_u32_array("hypercall_histo", 0444, d_mc_debug,
				     mc_stats.histo_hypercalls, NHYPERCALLS);
	xen_debugfs_create_u32_array("flush_reasons", 0444, d_mc_debug,
				     mc_stats.flush, FL_N_REASONS);

	return 0;
}
fs_initcall(xen_mc_debugfs);

#endif	/* CONFIG_XEN_DEBUG_FS */
