/*
 * Copyright (C) 2016 Veertu Inc,
 * Copyright (C) 2017 Google Inc,
 * Based on Veertu vddh/vmm/vmx.h
 *
 * Interfaces to Hypervisor.framework to read/write X86 registers and VMCS.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
 *
 * This file contain code under public domain from the hvdos project:
 * https://github.com/mist64/hvdos
 */

#ifndef VMX_H
#define VMX_H

#include <Hypervisor/hv.h>
#include <Hypervisor/hv_vmx.h>
#include "vmcs.h"
#include "cpu.h"
#include "x86.h"
#include "sysemu/hvf.h"
#include "sysemu/hvf_int.h"

#include "exec/address-spaces.h"

static inline uint64_t rreg(hv_vcpuid_t vcpu, hv_x86_reg_t reg)
{
    uint64_t v;

    if (hv_vcpu_read_register(vcpu, reg, &v)) {
        abort();
    }

    return v;
}

/* write GPR */
static inline void wreg(hv_vcpuid_t vcpu, hv_x86_reg_t reg, uint64_t v)
{
    if (hv_vcpu_write_register(vcpu, reg, v)) {
        abort();
    }
}

/* read VMCS field */
static inline uint64_t rvmcs(hv_vcpuid_t vcpu, uint32_t field)
{
    uint64_t v;

    hv_vmx_vcpu_read_vmcs(vcpu, field, &v);

    return v;
}

/* write VMCS field */
static inline void wvmcs(hv_vcpuid_t vcpu, uint32_t field, uint64_t v)
{
    hv_vmx_vcpu_write_vmcs(vcpu, field, v);
}

/* desired control word constrained by hardware/hypervisor capabilities */
static inline uint64_t cap2ctrl(uint64_t cap, uint64_t ctrl)
{
    return (ctrl | (cap & 0xffffffff)) & (cap >> 32);
}

#define VM_ENTRY_GUEST_LMA (1LL << 9)

#define AR_TYPE_ACCESSES_MASK 1
#define AR_TYPE_READABLE_MASK (1 << 1)
#define AR_TYPE_WRITABLE_MASK (1 << 2)
#define AR_TYPE_CODE_MASK (1 << 3)
#define AR_TYPE_MASK 0x0f
#define AR_TYPE_BUSY_64_TSS 11
#define AR_TYPE_BUSY_32_TSS 11
#define AR_TYPE_BUSY_16_TSS 3
#define AR_TYPE_LDT 2

static void enter_long_mode(hv_vcpuid_t vcpu, uint64_t cr0, uint64_t efer)
{
    uint64_t entry_ctls;

    efer |= MSR_EFER_LMA;
    wvmcs(vcpu, VMCS_GUEST_IA32_EFER, efer);
    entry_ctls = rvmcs(vcpu, VMCS_ENTRY_CTLS);
    wvmcs(vcpu, VMCS_ENTRY_CTLS, rvmcs(vcpu, VMCS_ENTRY_CTLS) |
          VM_ENTRY_GUEST_LMA);

    uint64_t guest_tr_ar = rvmcs(vcpu, VMCS_GUEST_TR_ACCESS_RIGHTS);
    if ((efer & MSR_EFER_LME) &&
        (guest_tr_ar & AR_TYPE_MASK) != AR_TYPE_BUSY_64_TSS) {
        wvmcs(vcpu, VMCS_GUEST_TR_ACCESS_RIGHTS,
              (guest_tr_ar & ~AR_TYPE_MASK) | AR_TYPE_BUSY_64_TSS);
    }
}

static void exit_long_mode(hv_vcpuid_t vcpu, uint64_t cr0, uint64_t efer)
{
    uint64_t entry_ctls;

    entry_ctls = rvmcs(vcpu, VMCS_ENTRY_CTLS);
    wvmcs(vcpu, VMCS_ENTRY_CTLS, entry_ctls & ~VM_ENTRY_GUEST_LMA);

    efer &= ~MSR_EFER_LMA;
    wvmcs(vcpu, VMCS_GUEST_IA32_EFER, efer);
}

static inline void macvm_set_cr0(hv_vcpuid_t vcpu, uint64_t cr0)
{
    int i;
    uint64_t pdpte[4] = {0, 0, 0, 0};
    uint64_t efer = rvmcs(vcpu, VMCS_GUEST_IA32_EFER);
    uint64_t old_cr0 = rvmcs(vcpu, VMCS_GUEST_CR0);
    uint64_t changed_cr0 = old_cr0 ^ cr0;
    uint64_t mask = CR0_PG_MASK | CR0_CD_MASK | CR0_NW_MASK |
                    CR0_NE_MASK | CR0_ET_MASK;
    uint64_t entry_ctls;

    if ((cr0 & CR0_PG_MASK) && (rvmcs(vcpu, VMCS_GUEST_CR4) & CR4_PAE_MASK) &&
        !(efer & MSR_EFER_LME)) {
        address_space_read(&address_space_memory,
                           rvmcs(vcpu, VMCS_GUEST_CR3) & ~0x1f,
                           MEMTXATTRS_UNSPECIFIED, pdpte, 32);
        /* Only set PDPTE when appropriate. */
        for (i = 0; i < 4; i++) {
            wvmcs(vcpu, VMCS_GUEST_PDPTE0 + i * 2, pdpte[i]);
        }
    }

    wvmcs(vcpu, VMCS_CR0_MASK, mask);
    wvmcs(vcpu, VMCS_CR0_SHADOW, cr0);

    if (efer & MSR_EFER_LME) {
        if (changed_cr0 & CR0_PG_MASK) {
            if (cr0 & CR0_PG_MASK) {
                enter_long_mode(vcpu, cr0, efer);
            } else {
                exit_long_mode(vcpu, cr0, efer);
            }
        }
    } else {
        entry_ctls = rvmcs(vcpu, VMCS_ENTRY_CTLS);
        wvmcs(vcpu, VMCS_ENTRY_CTLS, entry_ctls & ~VM_ENTRY_GUEST_LMA);
    }

    /* Filter new CR0 after we are finished examining it above. */
    cr0 = (cr0 & ~(mask & ~CR0_PG_MASK));
    wvmcs(vcpu, VMCS_GUEST_CR0, cr0 | CR0_NE_MASK | CR0_ET_MASK);

    hv_vcpu_invalidate_tlb(vcpu);
}

static inline void macvm_set_cr4(hv_vcpuid_t vcpu, uint64_t cr4)
{
    uint64_t guest_cr4 = cr4 | CR4_VMXE_MASK;

    wvmcs(vcpu, VMCS_GUEST_CR4, guest_cr4);
    wvmcs(vcpu, VMCS_CR4_SHADOW, cr4);
    wvmcs(vcpu, VMCS_CR4_MASK, CR4_VMXE_MASK);

    hv_vcpu_invalidate_tlb(vcpu);
}

static inline void macvm_set_rip(CPUState *cpu, uint64_t rip)
{
    X86CPU *x86_cpu = X86_CPU(cpu);
    CPUX86State *env = &x86_cpu->env;
    uint64_t val;

    /* BUG, should take considering overlap.. */
    wreg(cpu->accel->fd, HV_X86_RIP, rip);
    env->eip = rip;

    /* after moving forward in rip, we need to clean INTERRUPTABILITY */
   val = rvmcs(cpu->accel->fd, VMCS_GUEST_INTERRUPTIBILITY);
   if (val & (VMCS_INTERRUPTIBILITY_STI_BLOCKING |
               VMCS_INTERRUPTIBILITY_MOVSS_BLOCKING)) {
        env->hflags &= ~HF_INHIBIT_IRQ_MASK;
        wvmcs(cpu->accel->fd, VMCS_GUEST_INTERRUPTIBILITY,
               val & ~(VMCS_INTERRUPTIBILITY_STI_BLOCKING |
               VMCS_INTERRUPTIBILITY_MOVSS_BLOCKING));
   }
}

static inline void vmx_clear_nmi_blocking(CPUState *cpu)
{
    X86CPU *x86_cpu = X86_CPU(cpu);
    CPUX86State *env = &x86_cpu->env;

    env->hflags2 &= ~HF2_NMI_MASK;
    uint32_t gi = (uint32_t) rvmcs(cpu->accel->fd, VMCS_GUEST_INTERRUPTIBILITY);
    gi &= ~VMCS_INTERRUPTIBILITY_NMI_BLOCKING;
    wvmcs(cpu->accel->fd, VMCS_GUEST_INTERRUPTIBILITY, gi);
}

static inline void vmx_set_nmi_blocking(CPUState *cpu)
{
    X86CPU *x86_cpu = X86_CPU(cpu);
    CPUX86State *env = &x86_cpu->env;

    env->hflags2 |= HF2_NMI_MASK;
    uint32_t gi = (uint32_t)rvmcs(cpu->accel->fd, VMCS_GUEST_INTERRUPTIBILITY);
    gi |= VMCS_INTERRUPTIBILITY_NMI_BLOCKING;
    wvmcs(cpu->accel->fd, VMCS_GUEST_INTERRUPTIBILITY, gi);
}

static inline void vmx_set_nmi_window_exiting(CPUState *cpu)
{
    uint64_t val;
    val = rvmcs(cpu->accel->fd, VMCS_PRI_PROC_BASED_CTLS);
    wvmcs(cpu->accel->fd, VMCS_PRI_PROC_BASED_CTLS, val |
          VMCS_PRI_PROC_BASED_CTLS_NMI_WINDOW_EXITING);

}

static inline void vmx_clear_nmi_window_exiting(CPUState *cpu)
{

    uint64_t val;
    val = rvmcs(cpu->accel->fd, VMCS_PRI_PROC_BASED_CTLS);
    wvmcs(cpu->accel->fd, VMCS_PRI_PROC_BASED_CTLS, val &
          ~VMCS_PRI_PROC_BASED_CTLS_NMI_WINDOW_EXITING);
}

#endif
