/*
 * Copyright 2017, Data61
 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
 * ABN 41 687 119 230.
 *
 * 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(DATA61_GPL)
 */

/* vm exits and general handling of interrupt injection */

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

#include <sel4/sel4.h>

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

#define TRAMPOLINE_LENGTH (100)

static void resume_guest(vmm_vcpu_t *vcpu) {
    /* Disable exit-for-interrupt in guest state to allow the guest to resume. */
    uint32_t state = vmm_guest_state_get_control_ppc(&vcpu->guest_state);
    state &= ~BIT(2); /* clear the exit for interrupt flag */
    vmm_guest_state_set_control_ppc(&vcpu->guest_state, state);
}

static void inject_irq(vmm_vcpu_t *vcpu, int irq) {
    /* Inject a vectored exception into the guest */
    assert(irq >= 16);
    vmm_guest_state_set_control_entry(&vcpu->guest_state, BIT(31) | irq);
}

void wait_for_guest_ready(vmm_vcpu_t *vcpu) {
    /* Request that the guest exit at the earliest point that we can inject an interrupt. */
    uint32_t state = vmm_guest_state_get_control_ppc(&vcpu->guest_state);
    state |= BIT(2); /* set the exit for interrupt flag */
    vmm_guest_state_set_control_ppc(&vcpu->guest_state, state);
}

int can_inject(vmm_vcpu_t *vcpu) {
    uint32_t rflags = vmm_guest_state_get_rflags(&vcpu->guest_state, vcpu->guest_vcpu);
    uint32_t guest_int = vmm_guest_state_get_interruptibility(&vcpu->guest_state, vcpu->guest_vcpu);
    uint32_t int_control = vmm_guest_state_get_control_entry(&vcpu->guest_state);

    /* we can only inject if the interrupt mask flag is not set in flags,
       guest is not in an uninterruptable state and we are not already trying to
       inject an interrupt */

    if ( (rflags & BIT(9)) && (guest_int & 0xF) == 0 && (int_control & BIT(31)) == 0) {
        return 1;
    }
    return 0;
}

/* This function is called by the local apic when a new interrupt has occured. */
void vmm_have_pending_interrupt(vmm_vcpu_t *vcpu) {
    if (vmm_apic_has_interrupt(vcpu) >= 0) {
        /* there is actually an interrupt to inject */
        if (can_inject(vcpu)) {
            if (vcpu->guest_state.virt.interrupt_halt) {
                /* currently halted. need to put the guest
                 * in a state where it can inject again */
                wait_for_guest_ready(vcpu);
                vcpu->guest_state.virt.interrupt_halt = 0;
                vmm_sync_guest_state(vcpu);
                vmm_reply_vm_exit(vcpu); /* unblock the guest */
            } else {
                int irq = vmm_apic_get_interrupt(vcpu);
                inject_irq(vcpu, irq);
                /* see if there are more */
                if (vmm_apic_has_interrupt(vcpu) >= 0) {
                    wait_for_guest_ready(vcpu);
                }
            }
        } else {
            wait_for_guest_ready(vcpu);
            if (vcpu->guest_state.virt.interrupt_halt) {
                vcpu->guest_state.virt.interrupt_halt = 0;
                vmm_sync_guest_state(vcpu);
                vmm_reply_vm_exit(vcpu); /* unblock the guest */
            }
        }
    }
}

int vmm_pending_interrupt_handler(vmm_vcpu_t *vcpu) {
    /* see if there is actually a pending interrupt */
    assert(can_inject(vcpu));
    int irq = vmm_apic_get_interrupt(vcpu);
    if (irq == -1) {
        resume_guest(vcpu);
    } else {
        /* inject the interrupt */
        inject_irq(vcpu, irq);
        if (!(vmm_apic_has_interrupt(vcpu) >= 0)) {
            resume_guest(vcpu);
        }
        vcpu->guest_state.virt.interrupt_halt = 0;
    }
    return 0;
}

/* Start an AP vcpu after a sipi with the requested vector */
void vmm_start_ap_vcpu(vmm_vcpu_t *vcpu, unsigned int sipi_vector)
{
    DPRINTF(1, "trying to start vcpu %d\n", vcpu->vcpu_id);

    uint16_t segment = sipi_vector * 0x100;
    uintptr_t eip = sipi_vector * 0x1000;
    guest_state_t *gs = &vcpu->guest_state;

    /* Emulate up to 100 bytes of trampoline code */
    uint8_t instr[TRAMPOLINE_LENGTH];
    vmm_fetch_instruction(vcpu, eip, vmm_guest_state_get_cr3(gs, vcpu->guest_vcpu),
            TRAMPOLINE_LENGTH, instr);

    eip = vmm_emulate_realmode(&vcpu->vmm->guest_mem, instr, &segment, eip,
            TRAMPOLINE_LENGTH, gs);

    vmm_guest_state_set_eip(&vcpu->guest_state, eip);

    vmm_sync_guest_context(vcpu);
    vmm_sync_guest_state(vcpu);

    assert(!"no tcb");
//    seL4_TCB_Resume(vcpu->guest_tcb);
}

/* Got interrupt(s) from PIC, propagate to relevant vcpu lapic */
void vmm_check_external_interrupt(vmm_t *vmm)
{
    /* TODO if all lapics are enabled, store which lapic
       (only one allowed) receives extints, and short circuit this */
    if (vmm->plat_callbacks.has_interrupt() != -1) {
        for (int i = 0; i < vmm->num_vcpus; i++) {
            vmm_vcpu_t *vcpu = &vmm->vcpus[i];
            if (vmm_apic_accept_pic_intr(vcpu)) {
                vmm_vcpu_accept_interrupt(vcpu);
                break; /* Only one VCPU can take a PIC interrupt */
            }
        }
    }
}

void vmm_vcpu_accept_interrupt(vmm_vcpu_t *vcpu)
{
    if (vmm_apic_has_interrupt(vcpu) == -1) {
        return;
    }

    /* in an exit, can call the regular injection method */
    vmm_have_pending_interrupt(vcpu);
}
