/*
 * MSR emulation
 *
 * Copyright 2015 Google Inc.
 *
 * See LICENSE for details.
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <parlib/arch/arch.h>
#include <parlib/ros_debug.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/uio.h>
#include <stdint.h>
#include <err.h>
#include <sys/mman.h>
#include <ros/vmm.h>
#include <ros/arch/msr-index.h>
#include <vmm/virtio.h>
#include <vmm/virtio_mmio.h>
#include <vmm/virtio_ids.h>
#include <vmm/virtio_config.h>
#include <vmm/sched.h>
#include <vmm/vmm.h>
#include <ros/arch/trapframe.h>
#include <parlib/alarm.h>

struct emmsr {
	uint32_t reg;
	char *name;
	int (*f)(struct guest_thread *vm_thread, struct emmsr *, uint32_t);
	bool written;
	uint32_t edx, eax;
};

static inline uint64_t read_msr(uint32_t reg)
{
	panic("Not implemented for userspace");
}

static inline void write_msr(uint32_t reg, uint64_t val)
{
	panic("Not implemented for userspace");
}

static int emsr_readonly(struct guest_thread *vm_thread, struct emmsr *,
                         uint32_t);
static int emsr_readzero(struct guest_thread *vm_thread, struct emmsr *,
                         uint32_t);
static int emsr_fakewrite(struct guest_thread *vm_thread, struct emmsr *,
                          uint32_t);
static int emsr_ok(struct guest_thread *vm_thread, struct emmsr *, uint32_t);

struct emmsr emmsrs[] = {
	{MSR_RAPL_POWER_UNIT, "MSR_RAPL_POWER_UNIT", emsr_readzero},
};

static inline uint32_t low32(uint64_t val)
{
	return val & 0xffffffff;
}

static inline uint32_t high32(uint64_t val)
{
	return val >> 32;
}

static int emsr_ok(struct guest_thread *vm_thread, struct emmsr *msr,
                   uint32_t opcode)
{
	struct vm_trapframe *vm_tf = &(vm_thread->uthread.u_ctx.tf.vm_tf);
	uint64_t msr_val;

	if (opcode == EXIT_REASON_MSR_READ) {
		msr_val = read_msr(msr->reg);
		vm_tf->tf_rax = low32(msr_val);
		vm_tf->tf_rdx = high32(msr_val);
	} else {
		msr_val = (vm_tf->tf_rdx << 32) | vm_tf->tf_rax;
		write_msr(msr->reg, msr_val);
	}
	return 0;
}

static int emsr_readonly(struct guest_thread *vm_thread, struct emmsr *msr,
                         uint32_t opcode)
{
	struct vm_trapframe *vm_tf = &(vm_thread->uthread.u_ctx.tf.vm_tf);
	uint64_t msr_val;

	msr_val = read_msr(msr->reg);
	if (opcode == EXIT_REASON_MSR_READ) {
		vm_tf->tf_rax = low32(msr_val);
		vm_tf->tf_rdx = high32(msr_val);
		return 0;
	}

	fprintf(stderr,"%s: Tried to write a readonly register\n", msr->name);
	return SHUTDOWN_UNHANDLED_EXIT_REASON;
}

static int emsr_readzero(struct guest_thread *vm_thread, struct emmsr *msr,
                         uint32_t opcode)
{
	struct vm_trapframe *vm_tf = &(vm_thread->uthread.u_ctx.tf.vm_tf);

	if (opcode == EXIT_REASON_MSR_READ) {
		vm_tf->tf_rax = 0;
		vm_tf->tf_rdx = 0;
		return 0;
	}

	fprintf(stderr,"%s: Tried to write a readonly register\n", msr->name);
	return SHUTDOWN_UNHANDLED_EXIT_REASON;
}

/* pretend to write it, but don't write it. */
static int emsr_fakewrite(struct guest_thread *vm_thread, struct emmsr *msr,
                          uint32_t opcode)
{
	uint32_t eax, edx;
	uint64_t msr_val;
	struct vm_trapframe *vm_tf = &(vm_thread->uthread.u_ctx.tf.vm_tf);

	if (!msr->written) {
		msr_val = read_msr(msr->reg);
		eax = low32(msr_val);
		edx = high32(msr_val);
	} else {
		eax = msr->eax;
		edx = msr->edx;
	}
	if (opcode == EXIT_REASON_MSR_READ) {
		vm_tf->tf_rax = eax;
		vm_tf->tf_rdx = edx;
		return 0;
	} else {
		msr->edx = vm_tf->tf_rdx;
		msr->eax = vm_tf->tf_rax;
		msr->written = true;
	}
	return 0;
}

static int apic_icr_write(struct guest_thread *vm_thread,
                          struct vmm_gpcore_init *gpci)
{
	/* We currently only handle physical destinations.
	 * TODO(ganshun): Support logical destinations if needed. */
	struct virtual_machine *vm = gth_to_vm(vm_thread);
	struct vm_trapframe *vm_tf = gth_to_vmtf(vm_thread);
	uint32_t destination = vm_tf->tf_rdx & 0xffffffff;
	uint8_t vector = vm_tf->tf_rax & 0xff;
	uint8_t type = (vm_tf->tf_rax >> 8) & 0x7;
	int apic_offset = vm_tf->tf_rcx & 0xff;

	if (destination >= vm->nr_gpcs && destination != 0xffffffff) {
		fprintf(stderr, "UNSUPPORTED DESTINATION 0x%02x!\n",
				destination);
		return SHUTDOWN_UNHANDLED_EXIT_REASON;
	}
	switch (type) {
	case 0:
		/* Send IPI */
		if (destination == 0xffffffff) {
			/* Broadcast */
			for (int i = 0; i < vm->nr_gpcs; i++)
				vmm_interrupt_guest(vm, i, vector);
		} else {
			/* Send individual IPI */
			vmm_interrupt_guest(vm, destination, vector);
		}
		break;
	case 0x5:	/* INIT */
	case 0x6:	/* SIPI */
		/* We don't use INIT/SIPI for SMP boot.  The guest is still
		 * allowed to try to make them for now. */
		break;
	default:
		fprintf(stderr, "Unsupported IPI type %d!\n", type);
		break;
	}

	((uint32_t *)(gpci->vapic_addr))[apic_offset] =
	                                       (uint32_t)(vm_tf->tf_rax);
	((uint32_t *)(gpci->vapic_addr))[apic_offset + 1] =
	                                       (uint32_t)(vm_tf->tf_rdx);
	return 0;
}

static int apic_timer_write(struct guest_thread *gth,
                            struct vmm_gpcore_init *gpci)
{
	uint32_t multiplier;
	uint8_t vector;
	uint32_t initial_count;
	uint32_t divide_config_reg;
	struct alarm_waiter *timer_waiter;
	struct vm_trapframe *vm_tf = gth_to_vmtf(gth);
	int apic_offset = vm_tf->tf_rcx & 0xff;

	((uint32_t *)(gpci->vapic_addr))[apic_offset] =
                                       (uint32_t)(vm_tf->tf_rax);

	/* See if we can set the timer. */
	vector = ((uint32_t *)gpci->vapic_addr)[0x32] & 0xff;
	initial_count = ((uint32_t *)gpci->vapic_addr)[0x38];
	divide_config_reg = ((uint32_t *)gpci->vapic_addr)[0x3E];
	timer_waiter = (struct alarm_waiter*)gth->user_data;

	/* This is a precaution on my part, in case the guest tries to look at
	 * the current count on the lapic. I wanted it to be something other
	 * than 0 just in case. The current count will never be right short of
	 * us properly emulating it. */
	((uint32_t *)(gpci->vapic_addr))[0x39] = initial_count;

	if (!timer_waiter)
		panic("NO WAITER");

	/* Look at the intel manual Vol 3 10.5.4 APIC Timer */
	multiplier = (((divide_config_reg & 0x08) >> 1) |
	              (divide_config_reg & 0x03)) + 1;
	multiplier &= 0x07;

	unset_alarm(timer_waiter);

	if (vector && initial_count) {
		set_awaiter_rel(timer_waiter, initial_count << multiplier);
		set_alarm(timer_waiter);
	}
	return 0;
}

static int emsr_apic(struct guest_thread *vm_thread,
                     struct vmm_gpcore_init *gpci, uint32_t opcode)
{
	struct vm_trapframe *vm_tf = &(vm_thread->uthread.u_ctx.tf.vm_tf);
	int apic_offset = vm_tf->tf_rcx & 0xff;
	uint64_t value;
	int error;

	if (opcode == EXIT_REASON_MSR_READ) {
		if (vm_tf->tf_rcx != MSR_LAPIC_ICR) {
			vm_tf->tf_rax =
				((uint32_t*)(gpci->vapic_addr))[apic_offset];
			vm_tf->tf_rdx = 0;
		} else {
			vm_tf->tf_rax =
				((uint32_t*)(gpci->vapic_addr))[apic_offset];
			vm_tf->tf_rdx =
				((uint32_t*)(gpci->vapic_addr))[apic_offset +1];
		}
	} else {
		switch (vm_tf->tf_rcx) {
		case MSR_LAPIC_ICR:
			error = apic_icr_write(vm_thread, gpci);
			if (error != 0)
				return error;
			break;
		case MSR_LAPIC_DIVIDE_CONFIG_REG:
		case MSR_LAPIC_LVT_TIMER:
		case MSR_LAPIC_INITIAL_COUNT:
			apic_timer_write(vm_thread, gpci);
			break;
		default:
			((uint32_t *)(gpci->vapic_addr))[apic_offset] =
				(uint32_t)(vm_tf->tf_rax);
		}
	}
	return 0;
}

int msrio(struct guest_thread *vm_thread, struct vmm_gpcore_init *gpci,
          uint32_t opcode)
{
	int i;
	struct vm_trapframe *vm_tf = &(vm_thread->uthread.u_ctx.tf.vm_tf);

	if (vm_tf->tf_rcx >= MSR_LAPIC_ID && vm_tf->tf_rcx < MSR_LAPIC_END)
		return emsr_apic(vm_thread, gpci, opcode);

	for (i = 0; i < sizeof(emmsrs)/sizeof(emmsrs[0]); i++) {
		if (emmsrs[i].reg != vm_tf->tf_rcx)
			continue;
		return emmsrs[i].f(vm_thread, &emmsrs[i], opcode);
	}
	printd("msrio for 0x%lx failed\n", vm_tf->tf_rcx);
	return SHUTDOWN_UNHANDLED_EXIT_REASON;
}

