/* Copyright (c) 2016-7 Google Inc.
 * Barret Rhoden <brho@cs.berkeley.edu>
 * See LICENSE for details.
 *
 * Usage: turbo [reset]
 *
 * This will print the turbo ratio since the last reset for each core.
 *
 * x86 only (TODO) */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <unistd.h>
#include <parlib/sysinfo.h>
#include <parlib/arch/arch.h>
#include <ros/arch/msr-index.h>
#include <argp.h>

static const char doc[] = "turbo -- control for turbo mode";
static const char args_doc[] = "";

static struct argp_option options[] = {
	{"enable",		'e', 0, 0, "Enable turbo mode"},
	{"disable",		'd', 0, 0, "Disable turbo mode"},
	{"status",		's', 0, 0, "Print status of turbo mode"},
	{0, 0, 0, 0, ""},
	{"ratio",		'r', 0, 0, "Print the experienced turbo ratio"},
	{"zero",		'z', 0, 0, "Zero the turbo ratio"},
	{NULL,			'h', 0, OPTION_HIDDEN, NULL},
	{ 0 }
};

#define PROG_CMD_ENABLE		1
#define PROG_CMD_DISABLE	2
#define PROG_CMD_STATUS		3
#define PROG_CMD_PRINT_RATIO	4
#define PROG_CMD_ZERO_RATIO	5

struct prog_opts {
	int			cmd;
};

static int num_cores;

static error_t parse_opt(int key, char *arg, struct argp_state *state)
{
	struct prog_opts *p_opts = state->input;

	switch (key) {
	case 'e':
		if (p_opts->cmd) {
			fprintf(stderr, "Too many commands; one allowed.\n\n");
			argp_usage(state);
		}
		p_opts->cmd = PROG_CMD_ENABLE;
		break;
	case 'd':
		if (p_opts->cmd) {
			fprintf(stderr, "Too many commands; one allowed.\n\n");
			argp_usage(state);
		}
		p_opts->cmd = PROG_CMD_DISABLE;
		break;
	case 's':
		if (p_opts->cmd) {
			fprintf(stderr, "Too many commands; one allowed.\n\n");
			argp_usage(state);
		}
		p_opts->cmd = PROG_CMD_STATUS;
		break;
	case 'r':
		if (p_opts->cmd) {
			fprintf(stderr, "Too many commands; one allowed.\n\n");
			argp_usage(state);
		}
		p_opts->cmd = PROG_CMD_PRINT_RATIO;
		break;
	case 'z':
		if (p_opts->cmd) {
			fprintf(stderr, "Too many commands; one allowed.\n\n");
			argp_usage(state);
		}
		p_opts->cmd = PROG_CMD_ZERO_RATIO;
		break;
	case ARGP_KEY_ARG:
		fprintf(stderr, "Extra arguments\n");
		argp_usage(state);
		break;
	case ARGP_KEY_END:
		if (!p_opts->cmd)
			argp_usage(state);
		break;
	case 'h':
		argp_state_help(state, stderr, ARGP_HELP_LONG);
		break;
	default:
		return ARGP_ERR_UNKNOWN;
	};
	return 0;
}

static struct argp argp = {options, parse_opt, args_doc, doc};

static int get_msr_fd(void)
{
	int fd;

	fd = open("#arch/msr", O_RDWR);
	if (fd < 0) {
		perror("open");
		exit(-1);
	}
	return fd;
}

static int set_turbo_mode(bool enable)
{
	size_t buf_sz;
	ssize_t ret;
	int fd;
	uint64_t *buf;
	uint64_t msr_val;

	fd = get_msr_fd();
	buf_sz = num_cores * sizeof(uint64_t);
	buf = malloc(buf_sz);
	assert(buf);

	ret = pread(fd, buf, buf_sz, MSR_IA32_PERF_CTL);
	if (ret < 0) {
		perror("pread MSR_PERF_CTL");
		exit(-1);
	}
	/* The assumption here is that all cores have the same MSR value.
	 * Changing this would require changing the wrmsr kernel interface. */
	msr_val = buf[0];
	if (enable)
		msr_val &= ~(1ULL << 32);
	else
		msr_val |= 1ULL << 32;
	ret = pwrite(fd, &msr_val, sizeof(msr_val), MSR_IA32_PERF_CTL);
	if (ret < 0) {
		perror("pwrite MSR_PERF_CTL");
		exit(-1);
	}
	printf("%s turbo mode for all cores\n",
	       enable ? "Enabled" : "Disabled");
	free(buf);
	close(fd);
	return 0;
}

static int print_turbo_status(void)
{
	size_t buf_sz;
	ssize_t ret;
	int fd;
	uint64_t *buf;
	uint64_t msr_val;

	fd = get_msr_fd();
	buf_sz = num_cores * sizeof(uint64_t);
	buf = malloc(buf_sz);
	assert(buf);

	ret = pread(fd, buf, buf_sz, MSR_IA32_PERF_CTL);
	if (ret < 0) {
		perror("pread MSR_PERF_CTL");
		exit(-1);
	}
	/* The assumption here is that all cores have the same MSR value.
	 * Changing this would require changing the wrmsr kernel interface. */
	msr_val = buf[0];
	printf("Turbo mode is %s for all cores\n", msr_val & (1ULL << 32) ?
	                                           "disabled" : "enabled");
	free(buf);
	close(fd);
	return 0;
}

static void check_for_ratio_msrs(void)
{
	uint32_t ecx;

	parlib_cpuid(0x6, 0, NULL, NULL, &ecx, NULL);
	if (!(ecx & (1 << 0))) {
		fprintf(stderr, "cpuid says no MPERF and APERF\n");
		exit(-1);
	}
}

static int print_turbo_ratio(void)
{
	size_t buf_sz;
	ssize_t ret;
	int fd;
	uint64_t *mperf_buf, *aperf_buf;

	check_for_ratio_msrs();

	fd = get_msr_fd();
	buf_sz = num_cores * sizeof(uint64_t);
	mperf_buf = malloc(buf_sz);
	aperf_buf = malloc(buf_sz);
	assert(mperf_buf && aperf_buf);
	/* ideally these reads happen with no interference/interrupts in between
	 */
	ret = pread(fd, mperf_buf, buf_sz, MSR_IA32_MPERF);
	if (ret < 0) {
		perror("pread MSR_MPERF");
		exit(-1);
	}
	ret = pread(fd, aperf_buf, buf_sz, MSR_IA32_APERF);
	if (ret < 0) {
		perror("pread MSR_APERF");
		exit(-1);
	}
	for (int i = 0; i < num_cores; i++)
		printf("Core %3d: %4f%\n", i,
		       100.0 * aperf_buf[i] / mperf_buf[i]);
	free(mperf_buf);
	free(aperf_buf);
	close(fd);
	return 0;
}

static int zero_turbo_ratio(void)
{
	uint64_t reset_val = 0;
	ssize_t ret;
	int fd;

	check_for_ratio_msrs();

	fd = get_msr_fd();
	ret = pwrite(fd, &reset_val, sizeof(reset_val), MSR_IA32_MPERF);
	if (ret < 0) {
		perror("pwrite MSR_MPERF");
		exit(-1);
	}
	ret = pwrite(fd, &reset_val, sizeof(reset_val), MSR_IA32_APERF);
	if (ret < 0) {
		perror("pwrite MSR_APERF");
		exit(-1);
	}
	close(fd);
	return 0;
}

int main(int argc, char **argv)
{
	struct prog_opts popts = {0};

	argp_parse(&argp, argc, argv, 0, 0, &popts);
	/* TODO: could use a core list or something in the future (like perf) */
	num_cores = get_num_pcores();

	switch (popts.cmd) {
	case PROG_CMD_ENABLE:
		return set_turbo_mode(TRUE);
	case PROG_CMD_DISABLE:
		return set_turbo_mode(FALSE);
	case PROG_CMD_STATUS:
		return print_turbo_status();
	case PROG_CMD_PRINT_RATIO:
		return print_turbo_ratio();
	case PROG_CMD_ZERO_RATIO:
		return zero_turbo_ratio();
	default:
		fprintf(stderr, "Unhandled cmd (argp should catch this)!\n");
		return -1;
	};
}
