/*
 * Copyright (c) 2014 Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Alexandru Dutu
 */

/**
 * @file
 * Definitions of page table
 */
#include <string>

#include "arch/isa_traits.hh"
#include "base/trace.hh"
#include "config/the_isa.hh"
#include "debug/MMU.hh"
#include "mem/multi_level_page_table.hh"
#include "mem/page_table.hh"

using namespace std;
using namespace TheISA;

template <class ISAOps>
MultiLevelPageTable<ISAOps>::MultiLevelPageTable(const std::string &__name,
                                                 uint64_t _pid, System *_sys,
                                                 Addr pageSize)
    : PageTableBase(__name, _pid, pageSize), system(_sys),
    logLevelSize(PageTableLayout),
    numLevels(logLevelSize.size())
{
}

template <class ISAOps>
MultiLevelPageTable<ISAOps>::~MultiLevelPageTable()
{
}

template <class ISAOps>
void
MultiLevelPageTable<ISAOps>::initState(ThreadContext* tc)
{
    basePtr = pTableISAOps.getBasePtr(tc);
    if (basePtr == 0) basePtr++;
    DPRINTF(MMU, "basePtr: %d\n", basePtr);

    system->pagePtr = basePtr;

    /* setting first level of the page table */
    uint64_t log_req_size = floorLog2(sizeof(PageTableEntry)) +
                            logLevelSize[numLevels-1];
    assert(log_req_size >= PageShift);
    uint64_t npages = 1 << (log_req_size - PageShift);

    Addr paddr = system->allocPhysPages(npages);

    PortProxy &p = system->physProxy;
    p.memsetBlob(paddr, 0, npages << PageShift);
}


template <class ISAOps>
bool
MultiLevelPageTable<ISAOps>::walk(Addr vaddr, bool allocate, Addr &PTE_addr)
{
    std::vector<uint64_t> offsets = pTableISAOps.getOffsets(vaddr);

    Addr level_base = basePtr;
    for (int i = numLevels - 1; i > 0; i--) {

        Addr entry_addr = (level_base<<PageShift) +
                          offsets[i] * sizeof(PageTableEntry);

        PortProxy &p = system->physProxy;
        PageTableEntry entry = p.read<PageTableEntry>(entry_addr);

        Addr next_entry_pnum = pTableISAOps.getPnum(entry);
        if (next_entry_pnum == 0) {

            if (!allocate) return false;

            uint64_t log_req_size = floorLog2(sizeof(PageTableEntry)) +
                                    logLevelSize[i-1];
            assert(log_req_size >= PageShift);
            uint64_t npages = 1 << (log_req_size - PageShift);

            DPRINTF(MMU, "Allocating %d pages needed for entry in level %d\n",
                    npages, i - 1);

            /* allocate new entry */
            Addr next_entry_paddr = system->allocPhysPages(npages);
            p.memsetBlob(next_entry_paddr, 0, npages << PageShift);

            next_entry_pnum = next_entry_paddr >> PageShift;
            pTableISAOps.setPnum(entry, next_entry_pnum);
            pTableISAOps.setPTEFields(entry);
            p.write<PageTableEntry>(entry_addr, entry);

        }
        DPRINTF(MMU, "Level %d base: %d offset: %d entry: %d\n",
                i, level_base, offsets[i], next_entry_pnum);
        level_base = next_entry_pnum;

    }
    PTE_addr = (level_base<<PageShift) +
        offsets[0] * sizeof(PageTableEntry);
    DPRINTF(MMU, "Returning PTE_addr: %x\n", PTE_addr);
    return true;
}

template <class ISAOps>
void
MultiLevelPageTable<ISAOps>::map(Addr vaddr, Addr paddr,
                                 int64_t size, uint64_t flags)
{
    bool clobber = flags & Clobber;
    // starting address must be page aligned
    assert(pageOffset(vaddr) == 0);

    DPRINTF(MMU, "Allocating Page: %#x-%#x\n", vaddr, vaddr + size);

    PortProxy &p = system->physProxy;

    for (; size > 0; size -= pageSize, vaddr += pageSize, paddr += pageSize) {
        Addr PTE_addr;
        if (walk(vaddr, true, PTE_addr)) {
            PageTableEntry PTE = p.read<PageTableEntry>(PTE_addr);
            Addr entry_paddr = pTableISAOps.getPnum(PTE);
            if (!clobber && entry_paddr != 0) {
                fatal("addr 0x%x already mapped to %x", vaddr, entry_paddr);
            }
            pTableISAOps.setPnum(PTE, paddr >> PageShift);
            uint64_t PTE_flags = 0;
            if (flags & NotPresent)
                PTE_flags |= TheISA::PTE_NotPresent;
            if (flags & Uncacheable)
                PTE_flags |= TheISA::PTE_Uncacheable;
            if (flags & ReadOnly)
                PTE_flags |= TheISA::PTE_ReadOnly;
            pTableISAOps.setPTEFields(PTE, PTE_flags);
            p.write<PageTableEntry>(PTE_addr, PTE);
            DPRINTF(MMU, "New mapping: %#x-%#x\n", vaddr, paddr);

            eraseCacheEntry(vaddr);
            updateCache(vaddr, TlbEntry(pid, vaddr, paddr,
                                        flags & Uncacheable,
                                        flags & ReadOnly));
        }

    }
}

template <class ISAOps>
void
MultiLevelPageTable<ISAOps>::remap(Addr vaddr, int64_t size, Addr new_vaddr)
{
    assert(pageOffset(vaddr) == 0);
    assert(pageOffset(new_vaddr) == 0);

    DPRINTF(MMU, "moving pages from vaddr %08p to %08p, size = %d\n", vaddr,
            new_vaddr, size);

    PortProxy &p = system->physProxy;

    for (; size > 0;
         size -= pageSize, vaddr += pageSize, new_vaddr += pageSize)
    {
        Addr PTE_addr;
        if (walk(vaddr, false, PTE_addr)) {
            PageTableEntry PTE = p.read<PageTableEntry>(PTE_addr);
            Addr paddr = pTableISAOps.getPnum(PTE);

            if (paddr == 0) {
                fatal("Page fault while remapping");
            } else {
                /* unmapping vaddr */
                pTableISAOps.setPnum(PTE, 0);
                p.write<PageTableEntry>(PTE_addr, PTE);

                /* maping new_vaddr */
                Addr new_PTE_addr;
                walk(new_vaddr, true, new_PTE_addr);
                PageTableEntry new_PTE = p.read<PageTableEntry>(new_PTE_addr);

                pTableISAOps.setPnum(new_PTE, paddr>>PageShift);
                pTableISAOps.setPTEFields(new_PTE);
                p.write<PageTableEntry>(new_PTE_addr, new_PTE);
                DPRINTF(MMU, "Remapping: %#x-%#x\n", vaddr, new_PTE_addr);
            }

            eraseCacheEntry(vaddr);
            updateCache(new_vaddr, TlbEntry(pid, new_vaddr, paddr,
                                            pTableISAOps.isUncacheable(PTE),
                                            pTableISAOps.isReadOnly(PTE)));
        } else {
            fatal("Page fault while remapping");
        }
    }
}

template <class ISAOps>
void
MultiLevelPageTable<ISAOps>::unmap(Addr vaddr, int64_t size)
{
    assert(pageOffset(vaddr) == 0);

    DPRINTF(MMU, "Unmapping page: %#x-%#x\n", vaddr, vaddr+ size);

    PortProxy &p = system->physProxy;

    for (; size > 0; size -= pageSize, vaddr += pageSize) {
        Addr PTE_addr;
        if (walk(vaddr, false, PTE_addr)) {
            PageTableEntry PTE = p.read<PageTableEntry>(PTE_addr);
            Addr paddr = pTableISAOps.getPnum(PTE);
            if (paddr == 0) {
                fatal("PageTable::allocate: address 0x%x not mapped", vaddr);
            } else {
                pTableISAOps.setPnum(PTE, 0);
                p.write<PageTableEntry>(PTE_addr, PTE);
                DPRINTF(MMU, "Unmapping: %#x\n", vaddr);
            }
           eraseCacheEntry(vaddr);
        } else {
            fatal("Page fault while unmapping");
        }
    }

}

template <class ISAOps>
bool
MultiLevelPageTable<ISAOps>::isUnmapped(Addr vaddr, int64_t size)
{
    // starting address must be page aligned
    assert(pageOffset(vaddr) == 0);
    PortProxy &p = system->physProxy;

    for (; size > 0; size -= pageSize, vaddr += pageSize) {
        Addr PTE_addr;
        if (walk(vaddr, false, PTE_addr)) {
            PageTableEntry PTE = p.read<PageTableEntry>(PTE_addr);
            if (pTableISAOps.getPnum(PTE) != 0)
                return false;
        }
    }

    return true;
}

template <class ISAOps>
bool
MultiLevelPageTable<ISAOps>::lookup(Addr vaddr, TlbEntry &entry)
{
    Addr page_addr = pageAlign(vaddr);

    if (pTableCache[0].valid && pTableCache[0].vaddr == page_addr) {
        entry = pTableCache[0].entry;
        return true;
    }
    if (pTableCache[1].valid && pTableCache[1].vaddr == page_addr) {
        entry = pTableCache[1].entry;
        return true;
    }
    if (pTableCache[2].valid && pTableCache[2].vaddr == page_addr) {
        entry = pTableCache[2].entry;
        return true;
    }

    DPRINTF(MMU, "lookup page_addr: %#x\n", page_addr);
    Addr PTE_addr;
    if (walk(page_addr, false, PTE_addr)) {
        PortProxy &p = system->physProxy;
        PageTableEntry PTE = p.read<PageTableEntry>(PTE_addr);
        Addr pnum = pTableISAOps.getPnum(PTE);
        if (pnum == 0)
            return false;

        entry = TlbEntry(pid, vaddr, pnum << PageShift,
                         pTableISAOps.isUncacheable(PTE),
                         pTableISAOps.isReadOnly(PTE));
        updateCache(page_addr, entry);
    } else {
        return false;
    }
    return true;
}

template <class ISAOps>
void
MultiLevelPageTable<ISAOps>::serialize(CheckpointOut &cp) const
{
    /** Since, the page table is stored in system memory
     * which is serialized separately, we will serialize
     * just the base pointer
     */
    paramOut(cp, "ptable.pointer", basePtr);
}

template <class ISAOps>
void
MultiLevelPageTable<ISAOps>::unserialize(CheckpointIn &cp)
{
    paramIn(cp, "ptable.pointer", basePtr);
}
