/*
 * 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) {
    LOG_INFO("Ignoring call of clts");

    return -1;
}

static int vmm_cr_lmsw(vmm_vcpu_t *vcpu, unsigned int value) {
    LOG_INFO("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;
}
