/*
 * 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(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(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(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->accel->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(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->accel->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(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(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(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;
    }
}
