/*
 * Copyright 2014, NICTA
 *
 * This software may be distributed and modified according to the terms of
 * the GNU General Public License version 2. Note that NO WARRANTY is provided.
 * See "LICENSE_GPLv2.txt" for details.
 *
 * @TAG(NICTA_GPL)
 */

/*handling msr read & write exceptions*/

#include <stdio.h>
#include <stdlib.h>

#include <sel4/sel4.h>

#include "vmm/debug.h"
#include "vmm/vmm.h"
#include "vmm/processor/msr.h"


int vmm_rdmsr_handler(vmm_vcpu_t *vcpu) {

    int ret = 0;
    unsigned int msr_no = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_ECX);
    uint64_t data = 0;

    DPRINTF(4, "rdmsr ecx 0x%x\n", msr_no);

    // src reference: Linux kernel 3.11 kvm arch/x86/kvm/x86.c
    switch (msr_no) {
        case MSR_IA32_PLATFORM_ID:
        case MSR_IA32_EBL_CR_POWERON:
        case MSR_IA32_DEBUGCTLMSR:
        case MSR_IA32_LASTBRANCHFROMIP:
        case MSR_IA32_LASTBRANCHTOIP:
        case MSR_IA32_LASTINTFROMIP:
        case MSR_IA32_LASTINTTOIP:
        case MSR_IA32_MISC_ENABLE:
            data = 0;
            break;

        case MSR_IA32_UCODE_REV: 
            data = 0x100000000ULL;
            break;

        case MSR_P6_PERFCTR0:
        case MSR_P6_PERFCTR1:
        case MSR_P6_EVNTSEL0:
        case MSR_P6_EVNTSEL1:
            /* performance counters not supported. */
            data = 0;
            break;
            
        case 0xcd: /* fsb frequency */
            data = 3;
            break;
        
        case MSR_EBC_FREQUENCY_ID:
            data = 1 << 24;
            break;

        case MSR_IA32_APICBASE:
            data = vmm_lapic_get_base_msr(vcpu);
            break;

        default:
            DPRINTF(1, "rdmsr WARNING unsupported msr_no 0x%x\n", msr_no);
	    data = 0; /* should raise exception */
            break;

   }

    if (!ret) {
        vmm_set_user_context(&vcpu->guest_state, USER_CONTEXT_EAX, (uint32_t)(data & 0xffffffff));
        vmm_set_user_context(&vcpu->guest_state, USER_CONTEXT_EDX, (uint32_t)(data >> 32));
        vmm_guest_exit_next_instruction(&vcpu->guest_state, vcpu->guest_vcpu);
    }

    return ret;
}


int vmm_wrmsr_handler(vmm_vcpu_t *vcpu) {

    int ret = 0;

    unsigned int msr_no = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_ECX);
    unsigned int val_high = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EDX);
    unsigned int val_low = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EAX);
    
    DPRINTF(4, "wrmsr ecx 0x%x   value: 0x%x  0x%x\n", msr_no, val_high, val_low);

    // src reference: Linux kernel 3.11 kvm arch/x86/kvm/x86.c
    switch (msr_no) {
        case MSR_IA32_UCODE_REV:
        case MSR_IA32_UCODE_WRITE:
            break;

        case MSR_P6_PERFCTR0:
        case MSR_P6_PERFCTR1:
        case MSR_P6_EVNTSEL0:
        case MSR_P6_EVNTSEL1:
            /* performance counters not supported. */
            break;
        
        case MSR_IA32_APICBASE:
            vmm_lapic_set_base_msr(vcpu, val_low);
            break;

        default:
            DPRINTF(1, "wrmsr WARNING unsupported msr_no 0x%x\n", msr_no);
            ret = -1;
            break;
    }

    if (!ret)
        vmm_guest_exit_next_instruction(&vcpu->guest_state, vcpu->guest_vcpu);

    return ret;
}
