/*
 * 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("  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 */
