/*
 * Copyright (C) 2016 Veertu Inc,
 * Copyright (C) 2017 Google Inc,
 *
 * 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/>.
 */

#include "qemu/osdep.h"
#include "panic.h"
#include "cpu.h"
#include "x86.h"
#include "x86_mmu.h"
#include "vmcs.h"
#include "vmx.h"

#define pte_present(pte) (pte & PT_PRESENT)
#define pte_write_access(pte) (pte & PT_WRITE)
#define pte_user_access(pte) (pte & PT_USER)
#define pte_exec_access(pte) (!(pte & PT_NX))

#define pte_large_page(pte) (pte & PT_PS)
#define pte_global_access(pte) (pte & PT_GLOBAL)

#define PAE_CR3_MASK                (~0x1fllu)
#define LEGACY_CR3_MASK             (0xffffffff)

#define LEGACY_PTE_PAGE_MASK        (0xffffffffllu << 12)
#define PAE_PTE_PAGE_MASK           ((-1llu << 12) & ((1llu << 52) - 1))
#define PAE_PTE_LARGE_PAGE_MASK     ((-1llu << (21)) & ((1llu << 52) - 1))

struct gpt_translation {
    target_ulong  gva;
    uint64_t gpa;
    int    err_code;
    uint64_t pte[5];
    bool write_access;
    bool user_access;
    bool exec_access;
};

static int gpt_top_level(struct CPUState *cpu, bool pae)
{
    if (!pae) {
        return 2;
    }
    if (x86_is_long_mode(cpu)) {
        return 4;
    }

    return 3;
}

static inline int gpt_entry(target_ulong addr, int level, bool pae)
{
    int level_shift = pae ? 9 : 10;
    return (addr >> (level_shift * (level - 1) + 12)) & ((1 << level_shift) - 1);
}

static inline int pte_size(bool pae)
{
    return pae ? 8 : 4;
}


static bool get_pt_entry(struct CPUState *cpu, struct gpt_translation *pt,
                         int level, bool pae)
{
    int index;
    uint64_t pte = 0;
    uint64_t page_mask = pae ? PAE_PTE_PAGE_MASK : LEGACY_PTE_PAGE_MASK;
    uint64_t gpa = pt->pte[level] & page_mask;

    if (level == 3 && !x86_is_long_mode(cpu)) {
        gpa = pt->pte[level];
    }

    index = gpt_entry(pt->gva, level, pae);
    address_space_read(&address_space_memory, gpa + index * pte_size(pae),
                       MEMTXATTRS_UNSPECIFIED, &pte, pte_size(pae));

    pt->pte[level - 1] = pte;

    return true;
}

/* test page table entry */
static bool test_pt_entry(struct CPUState *cpu, struct gpt_translation *pt,
                          int level, bool *is_large, bool pae)
{
    uint64_t pte = pt->pte[level];

    if (pt->write_access) {
        pt->err_code |= MMU_PAGE_WT;
    }
    if (pt->user_access) {
        pt->err_code |= MMU_PAGE_US;
    }
    if (pt->exec_access) {
        pt->err_code |= MMU_PAGE_NX;
    }

    if (!pte_present(pte)) {
        return false;
    }

    if (pae && !x86_is_long_mode(cpu) && 2 == level) {
        goto exit;
    }

    if (1 == level && pte_large_page(pte)) {
        pt->err_code |= MMU_PAGE_PT;
        *is_large = true;
    }
    if (!level) {
        pt->err_code |= MMU_PAGE_PT;
    }

    uint32_t cr0 = rvmcs(cpu->hvf->fd, VMCS_GUEST_CR0);
    /* check protection */
    if (cr0 & CR0_WP_MASK) {
        if (pt->write_access && !pte_write_access(pte)) {
            return false;
        }
    }

    if (pt->user_access && !pte_user_access(pte)) {
        return false;
    }

    if (pae && pt->exec_access && !pte_exec_access(pte)) {
        return false;
    }
    
exit:
    /* TODO: check reserved bits */
    return true;
}

static inline uint64_t pse_pte_to_page(uint64_t pte)
{
    return ((pte & 0x1fe000) << 19) | (pte & 0xffc00000);
}

static inline uint64_t large_page_gpa(struct gpt_translation *pt, bool pae)
{
    VM_PANIC_ON(!pte_large_page(pt->pte[1]))
    /* 2Mb large page  */
    if (pae) {
        return (pt->pte[1] & PAE_PTE_LARGE_PAGE_MASK) | (pt->gva & 0x1fffff);
    }

    /* 4Mb large page */
    return pse_pte_to_page(pt->pte[1]) | (pt->gva & 0x3fffff);
}



static bool walk_gpt(struct CPUState *cpu, target_ulong addr, int err_code,
                     struct gpt_translation *pt, bool pae)
{
    int top_level, level;
    bool is_large = false;
    target_ulong cr3 = rvmcs(cpu->hvf->fd, VMCS_GUEST_CR3);
    uint64_t page_mask = pae ? PAE_PTE_PAGE_MASK : LEGACY_PTE_PAGE_MASK;
    
    memset(pt, 0, sizeof(*pt));
    top_level = gpt_top_level(cpu, pae);

    pt->pte[top_level] = pae ? (cr3 & PAE_CR3_MASK) : (cr3 & LEGACY_CR3_MASK);
    pt->gva = addr;
    pt->user_access = (err_code & MMU_PAGE_US);
    pt->write_access = (err_code & MMU_PAGE_WT);
    pt->exec_access = (err_code & MMU_PAGE_NX);
    
    for (level = top_level; level > 0; level--) {
        get_pt_entry(cpu, pt, level, pae);

        if (!test_pt_entry(cpu, pt, level - 1, &is_large, pae)) {
            return false;
        }

        if (is_large) {
            break;
        }
    }

    if (!is_large) {
        pt->gpa = (pt->pte[0] & page_mask) | (pt->gva & 0xfff);
    } else {
        pt->gpa = large_page_gpa(pt, pae);
    }

    return true;
}


bool mmu_gva_to_gpa(struct CPUState *cpu, target_ulong gva, uint64_t *gpa)
{
    bool res;
    struct gpt_translation pt;
    int err_code = 0;

    if (!x86_is_paging_mode(cpu)) {
        *gpa = gva;
        return true;
    }

    res = walk_gpt(cpu, gva, err_code, &pt, x86_is_pae_enabled(cpu));
    if (res) {
        *gpa = pt.gpa;
        return true;
    }

    return false;
}

void vmx_write_mem(struct CPUState *cpu, target_ulong gva, void *data, int bytes)
{
    uint64_t gpa;

    while (bytes > 0) {
        /* copy page */
        int copy = MIN(bytes, 0x1000 - (gva & 0xfff));

        if (!mmu_gva_to_gpa(cpu, gva, &gpa)) {
            VM_PANIC_EX("%s: mmu_gva_to_gpa %llx failed\n", __func__, gva);
        } else {
            address_space_write(&address_space_memory, gpa,
                                MEMTXATTRS_UNSPECIFIED, data, copy);
        }

        bytes -= copy;
        gva += copy;
        data += copy;
    }
}

void vmx_read_mem(struct CPUState *cpu, void *data, target_ulong gva, int bytes)
{
    uint64_t gpa;

    while (bytes > 0) {
        /* copy page */
        int copy = MIN(bytes, 0x1000 - (gva & 0xfff));

        if (!mmu_gva_to_gpa(cpu, gva, &gpa)) {
            VM_PANIC_EX("%s: mmu_gva_to_gpa %llx failed\n", __func__, gva);
        }
        address_space_read(&address_space_memory, gpa, MEMTXATTRS_UNSPECIFIED,
                           data, copy);

        bytes -= copy;
        gva += copy;
        data += copy;
    }
}
