/*
 * 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)
 */

/*vm exit handler for control register access*/

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

#include <sel4/sel4.h>
#include <utils/util.h>

#include "vmm/debug.h"
#include "vmm/processor/platfeature.h"
#include "vmm/platform/vmcs.h"

#include "vmm/vmm.h"

static int vmm_cr_set_cr0(vmm_vcpu_t *vcpu, unsigned int value) {

    if (value & CR0_RESERVED_BITS)
        return -1;

    /*read the cr0 value*/
    int set = vmm_guest_state_get_cr0(&vcpu->guest_state, vcpu->guest_vcpu);

    DPRINTF(4, "cr0 val 0x%x guest set 0x%x\n", set, value);

    /*set the cr0 value with the shadow value*/
    value |= (vcpu->guest_state.virt.cr.cr0_mask & vcpu->guest_state.virt.cr.cr0_shadow);

    if (value == set) 
        return 0;

    vmm_guest_state_set_cr0(&vcpu->guest_state, value);

    return 0;
}

static int vmm_cr_set_cr3(vmm_vcpu_t *vcpu, unsigned int value) {
    assert(!"Should not get cr3 access");
    return -1;
}

static int vmm_cr_get_cr3(vmm_vcpu_t *vcpu, unsigned int *value) {
    *value = vmm_guest_state_get_cr3(&vcpu->guest_state, vcpu->guest_vcpu);
    return 0;

}


static int vmm_cr_set_cr4(vmm_vcpu_t *vcpu, unsigned int value) {

    if (value & CR4_RESERVED_BITS)
        return -1;

    int set = vmm_guest_state_get_cr4(&vcpu->guest_state, vcpu->guest_vcpu);

    DPRINTF(4, "cr4 val 0x%x guest set 0x%x\n", set, value);

    /*set the cr0 value with the shadow value*/
    value |= (vcpu->guest_state.virt.cr.cr4_shadow & vcpu->guest_state.virt.cr.cr4_mask);

    if (set == value)
        return 0;

    vmm_guest_state_set_cr4(&vcpu->guest_state, value);

    return 0;
}


static int vmm_cr_clts(vmm_vcpu_t *vcpu) {
    ZF_LOGI("Ignoring call of clts");

    return -1;
}

static int vmm_cr_lmsw(vmm_vcpu_t *vcpu, unsigned int value) {
    ZF_LOGI("Ignoring call of lmsw");

    return -1;

}

/* Convert exit regs to seL4 user context */
static int crExitRegs[] = {
    USER_CONTEXT_EAX,
    USER_CONTEXT_ECX,
    USER_CONTEXT_EDX,
    USER_CONTEXT_EBX,
    /*USER_CONTEXT_ESP*/-1,
    USER_CONTEXT_EBP,
    USER_CONTEXT_ESI,
    USER_CONTEXT_EDI
};

int vmm_cr_access_handler(vmm_vcpu_t *vcpu) {

    unsigned int exit_qualification, val;
    int cr, reg, ret = -1;

    exit_qualification = vmm_guest_exit_get_qualification(&vcpu->guest_state);
    cr = exit_qualification & 15;
    reg = (exit_qualification >> 8) & 15;

    switch ((exit_qualification >> 4) & 3) {
        case 0: /* mov to cr */
            if (crExitRegs[reg] < 0) {
                return -1;
            }
            val = vmm_read_user_context(&vcpu->guest_state, crExitRegs[reg]);

            switch (cr) {
                case 0:
                    ret = vmm_cr_set_cr0(vcpu, val);
                    break;
                case 3:
                    ret = vmm_cr_set_cr3(vcpu, val);
                    break;
                case 4:
                    ret = vmm_cr_set_cr4(vcpu, val);
                    break;
                case 8: 

#if 0

                    u8 cr8_prev = kvm_get_cr8(vcpu);
                    u8 cr8 = kvm_register_read(vcpu, reg);
                    err = kvm_set_cr8(vcpu, cr8);
                    kvm_complete_insn_gp(vcpu, err);
                    if (irqchip_in_kernel(vcpu->kvm))
                        return 1;
                    if (cr8_prev <= cr8)
                        return 1;
                    vcpu->run->exit_reason = KVM_EXIT_SET_TPR;
                    return 0;
#endif

                default: 
                    DPRINTF(4, "unhandled control register: op %d cr %d\n",
                            (int)(exit_qualification >> 4) & 3, cr);
                    break;

            }
            break;

        case 1: /*mov from cr*/
            switch (cr) {
                case 3:

                    ret = vmm_cr_get_cr3(vcpu, &val);
                    if (!ret)
                        vmm_set_user_context(&vcpu->guest_state, crExitRegs[reg], val);

                    break;
                case 8:
#if 0
                    val = kvm_get_cr8(vcpu);
                    kvm_register_write(vcpu, reg, val);
                    trace_kvm_cr_read(cr, val);
                    skip_emulated_instruction(vcpu);
                    return 1;
#endif
                default:
                    DPRINTF(4, "unhandled control register: op %d cr %d\n",
                            (int)(exit_qualification >> 4) & 3, cr);
                    break;

            }
            break;
        case 2: /* clts */
            ret = vmm_cr_clts(vcpu);
            break;

        case 3: /* lmsw */
            val = (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f;
            ret = vmm_cr_lmsw(vcpu, val);
            break;
        
        default:
            DPRINTF(4, "unhandled control register: op %d cr %d\n",
                    (int)(exit_qualification >> 4) & 3, cr);
            break;
    }

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

    return ret;
}
