/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * Authors: Waiman Long <waiman.long@hpe.com>
 */

/*
 * When queued spinlock statistical counters are enabled, the following
 * debugfs files will be created for reporting the counter values:
 *
 * <debugfs>/qlockstat/
 *   pv_hash_hops	- average # of hops per hashing operation
 *   pv_kick_unlock	- # of vCPU kicks issued at unlock time
 *   pv_kick_wake	- # of vCPU kicks used for computing pv_latency_wake
 *   pv_latency_kick	- average latency (ns) of vCPU kick operation
 *   pv_latency_wake	- average latency (ns) from vCPU kick to wakeup
 *   pv_lock_slowpath	- # of locking operations via the slowpath
 *   pv_lock_stealing	- # of lock stealing operations
 *   pv_spurious_wakeup	- # of spurious wakeups in non-head vCPUs
 *   pv_wait_again	- # of wait's after a queue head vCPU kick
 *   pv_wait_early	- # of early vCPU wait's
 *   pv_wait_head	- # of vCPU wait's at the queue head
 *   pv_wait_node	- # of vCPU wait's at a non-head queue node
 *
 * Writing to the "reset_counters" file will reset all the above counter
 * values.
 *
 * These statistical counters are implemented as per-cpu variables which are
 * summed and computed whenever the corresponding debugfs files are read. This
 * minimizes added overhead making the counters usable even in a production
 * environment.
 *
 * There may be slight difference between pv_kick_wake and pv_kick_unlock.
 */
enum qlock_stats {
	qstat_pv_hash_hops,
	qstat_pv_kick_unlock,
	qstat_pv_kick_wake,
	qstat_pv_latency_kick,
	qstat_pv_latency_wake,
	qstat_pv_lock_slowpath,
	qstat_pv_lock_stealing,
	qstat_pv_spurious_wakeup,
	qstat_pv_wait_again,
	qstat_pv_wait_early,
	qstat_pv_wait_head,
	qstat_pv_wait_node,
	qstat_num,	/* Total number of statistical counters */
	qstat_reset_cnts = qstat_num,
};

#ifdef CONFIG_QUEUED_LOCK_STAT
/*
 * Collect pvqspinlock statistics
 */
#include <linux/debugfs.h>
#include <linux/sched.h>
#include <linux/fs.h>

static const char * const qstat_names[qstat_num + 1] = {
	[qstat_pv_hash_hops]	   = "pv_hash_hops",
	[qstat_pv_kick_unlock]     = "pv_kick_unlock",
	[qstat_pv_kick_wake]       = "pv_kick_wake",
	[qstat_pv_spurious_wakeup] = "pv_spurious_wakeup",
	[qstat_pv_latency_kick]	   = "pv_latency_kick",
	[qstat_pv_latency_wake]    = "pv_latency_wake",
	[qstat_pv_lock_slowpath]   = "pv_lock_slowpath",
	[qstat_pv_lock_stealing]   = "pv_lock_stealing",
	[qstat_pv_wait_again]      = "pv_wait_again",
	[qstat_pv_wait_early]      = "pv_wait_early",
	[qstat_pv_wait_head]       = "pv_wait_head",
	[qstat_pv_wait_node]       = "pv_wait_node",
	[qstat_reset_cnts]         = "reset_counters",
};

/*
 * Per-cpu counters
 */
static DEFINE_PER_CPU(unsigned long, qstats[qstat_num]);
static DEFINE_PER_CPU(u64, pv_kick_time);

/*
 * Function to read and return the qlock statistical counter values
 *
 * The following counters are handled specially:
 * 1. qstat_pv_latency_kick
 *    Average kick latency (ns) = pv_latency_kick/pv_kick_unlock
 * 2. qstat_pv_latency_wake
 *    Average wake latency (ns) = pv_latency_wake/pv_kick_wake
 * 3. qstat_pv_hash_hops
 *    Average hops/hash = pv_hash_hops/pv_kick_unlock
 */
static ssize_t qstat_read(struct file *file, char __user *user_buf,
			  size_t count, loff_t *ppos)
{
	char buf[64];
	int cpu, counter, len;
	u64 stat = 0, kicks = 0;

	/*
	 * Get the counter ID stored in file->f_inode->i_private
	 */
	counter = (long)file_inode(file)->i_private;

	if (counter >= qstat_num)
		return -EBADF;

	for_each_possible_cpu(cpu) {
		stat += per_cpu(qstats[counter], cpu);
		/*
		 * Need to sum additional counter for some of them
		 */
		switch (counter) {

		case qstat_pv_latency_kick:
		case qstat_pv_hash_hops:
			kicks += per_cpu(qstats[qstat_pv_kick_unlock], cpu);
			break;

		case qstat_pv_latency_wake:
			kicks += per_cpu(qstats[qstat_pv_kick_wake], cpu);
			break;
		}
	}

	if (counter == qstat_pv_hash_hops) {
		u64 frac = 0;

		if (kicks) {
			frac = 100ULL * do_div(stat, kicks);
			frac = DIV_ROUND_CLOSEST_ULL(frac, kicks);
		}

		/*
		 * Return a X.XX decimal number
		 */
		len = snprintf(buf, sizeof(buf) - 1, "%llu.%02llu\n", stat, frac);
	} else {
		/*
		 * Round to the nearest ns
		 */
		if ((counter == qstat_pv_latency_kick) ||
		    (counter == qstat_pv_latency_wake)) {
			if (kicks)
				stat = DIV_ROUND_CLOSEST_ULL(stat, kicks);
		}
		len = snprintf(buf, sizeof(buf) - 1, "%llu\n", stat);
	}

	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}

/*
 * Function to handle write request
 *
 * When counter = reset_cnts, reset all the counter values.
 * Since the counter updates aren't atomic, the resetting is done twice
 * to make sure that the counters are very likely to be all cleared.
 */
static ssize_t qstat_write(struct file *file, const char __user *user_buf,
			   size_t count, loff_t *ppos)
{
	int cpu;

	/*
	 * Get the counter ID stored in file->f_inode->i_private
	 */
	if ((long)file_inode(file)->i_private != qstat_reset_cnts)
		return count;

	for_each_possible_cpu(cpu) {
		int i;
		unsigned long *ptr = per_cpu_ptr(qstats, cpu);

		for (i = 0 ; i < qstat_num; i++)
			WRITE_ONCE(ptr[i], 0);
	}
	return count;
}

/*
 * Debugfs data structures
 */
static const struct file_operations fops_qstat = {
	.read = qstat_read,
	.write = qstat_write,
	.llseek = default_llseek,
};

/*
 * Initialize debugfs for the qspinlock statistical counters
 */
static int __init init_qspinlock_stat(void)
{
	struct dentry *d_qstat = debugfs_create_dir("qlockstat", NULL);
	int i;

	if (!d_qstat)
		goto out;

	/*
	 * Create the debugfs files
	 *
	 * As reading from and writing to the stat files can be slow, only
	 * root is allowed to do the read/write to limit impact to system
	 * performance.
	 */
	for (i = 0; i < qstat_num; i++)
		if (!debugfs_create_file(qstat_names[i], 0400, d_qstat,
					 (void *)(long)i, &fops_qstat))
			goto fail_undo;

	if (!debugfs_create_file(qstat_names[qstat_reset_cnts], 0200, d_qstat,
				 (void *)(long)qstat_reset_cnts, &fops_qstat))
		goto fail_undo;

	return 0;
fail_undo:
	debugfs_remove_recursive(d_qstat);
out:
	pr_warn("Could not create 'qlockstat' debugfs entries\n");
	return -ENOMEM;
}
fs_initcall(init_qspinlock_stat);

/*
 * Increment the PV qspinlock statistical counters
 */
static inline void qstat_inc(enum qlock_stats stat, bool cond)
{
	if (cond)
		this_cpu_inc(qstats[stat]);
}

/*
 * PV hash hop count
 */
static inline void qstat_hop(int hopcnt)
{
	this_cpu_add(qstats[qstat_pv_hash_hops], hopcnt);
}

/*
 * Replacement function for pv_kick()
 */
static inline void __pv_kick(int cpu)
{
	u64 start = sched_clock();

	per_cpu(pv_kick_time, cpu) = start;
	pv_kick(cpu);
	this_cpu_add(qstats[qstat_pv_latency_kick], sched_clock() - start);
}

/*
 * Replacement function for pv_wait()
 */
static inline void __pv_wait(u8 *ptr, u8 val)
{
	u64 *pkick_time = this_cpu_ptr(&pv_kick_time);

	*pkick_time = 0;
	pv_wait(ptr, val);
	if (*pkick_time) {
		this_cpu_add(qstats[qstat_pv_latency_wake],
			     sched_clock() - *pkick_time);
		qstat_inc(qstat_pv_kick_wake, true);
	}
}

#define pv_kick(c)	__pv_kick(c)
#define pv_wait(p, v)	__pv_wait(p, v)

#else /* CONFIG_QUEUED_LOCK_STAT */

static inline void qstat_inc(enum qlock_stats stat, bool cond)	{ }
static inline void qstat_hop(int hopcnt)			{ }

#endif /* CONFIG_QUEUED_LOCK_STAT */
