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

#include <parlib/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 (opcode == EXIT_REASON_MSR_READ) {
		if (!msr->written) {
			msr_val = read_msr(msr->reg);
			eax = low32(msr_val);
			edx = high32(msr_val);
		} else {
			eax = msr->eax;
			edx = msr->edx;
		}
		vm_tf->tf_rax = eax;
		vm_tf->tf_rdx = edx;
	} 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;
}

