/*
 * Copyright (c) 2017-2020 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.
 */

#include "sim/mem_state.hh"

#include <cassert>

#include "arch/generic/tlb.hh"
#include "debug/Vma.hh"
#include "mem/se_translating_port_proxy.hh"
#include "sim/process.hh"
#include "sim/syscall_debug_macros.hh"
#include "sim/system.hh"
#include "sim/vma.hh"

MemState::MemState(Process *owner, Addr brk_point, Addr stack_base,
                   Addr max_stack_size, Addr next_thread_stack_base,
                   Addr mmap_end)
    : _ownerProcess(owner),
      _pageBytes(owner->system->getPageBytes()), _brkPoint(brk_point),
      _stackBase(stack_base), _maxStackSize(max_stack_size),
      _nextThreadStackBase(next_thread_stack_base),
      _mmapEnd(mmap_end), _endBrkPoint(brk_point)
{
}

MemState&
MemState::operator=(const MemState &in)
{
    if (this == &in)
        return *this;

    _pageBytes = in._pageBytes;
    _brkPoint = in._brkPoint;
    _stackBase = in._stackBase;
    _stackSize = in._stackSize;
    _maxStackSize = in._maxStackSize;
    _stackMin = in._stackMin;
    _nextThreadStackBase = in._nextThreadStackBase;
    _mmapEnd = in._mmapEnd;
    _endBrkPoint = in._endBrkPoint;
    _vmaList = in._vmaList; /* This assignment does a deep copy. */

    return *this;
}

void
MemState::resetOwner(Process *owner)
{
    _ownerProcess = owner;
}

bool
MemState::isUnmapped(Addr start_addr, Addr length)
{
    Addr end_addr = start_addr + length;
    const AddrRange range(start_addr, end_addr);
    for (const auto &vma : _vmaList) {
        if (vma.intersects(range))
            return false;
    }

    /**
     * In case someone skips the VMA interface and just directly maps memory
     * also consult the page tables to make sure that this memory isnt mapped.
     */
    for (auto start = start_addr; start < end_addr;
         start += _pageBytes) {
        if (_ownerProcess->pTable->lookup(start) != nullptr) {
            panic("Someone allocated physical memory at VA %p without "
                  "creating a VMA!\n", start);
            return false;
        }
    }
    return true;
}

void
MemState::updateBrkRegion(Addr old_brk, Addr new_brk)
{
    /**
     * To make this simple, avoid reducing the heap memory area if the
     * new_brk point is less than the old_brk; this occurs when the heap is
     * receding because the application has given back memory. The brk point
     * is still tracked in the MemState class as an independent field so that
     * it can be returned to the application; we just do not update the
     * region unless we expand it out.
     */
    if (new_brk < old_brk) {
        _brkPoint = new_brk;
        return;
    }

    /**
     * The regions must be page aligned but the break point can be set on
     * byte boundaries. Ensure that the restriction is maintained here by
     * extending the request out to the end of the page. (The roundUp
     * function will not round up an already aligned page.)
     */
    auto page_aligned_brk = roundUp(new_brk, _pageBytes);

    /**
     * Create a new mapping for the heap region. We only create a mapping
     * for the extra memory that is requested so we do not create a situation
     * where there can be overlapping mappings in the regions.
     *
     * Since we do not track the type of the region and we also do not
     * coalesce the regions together, we can create a fragmented set of
     * heap regions. To resolve this, we keep the furthest point ever mapped
     * by the _endBrkPoint field.
     */
    if (page_aligned_brk > _endBrkPoint) {
        auto length = page_aligned_brk - _endBrkPoint;
        /**
         * Check if existing mappings impede the expansion of brk expansion.
         * If brk cannot expand, it must return the original, unmodified brk
         * address and should not modify the mappings here.
         */
        if (!isUnmapped(_endBrkPoint, length)) {
            return;
        }

        /**
         * Note that the heap regions are always contiguous but there is
         * no mechanism right now to coalesce together memory that belongs
         * to the same region with similar access permissions. This could be
         * implemented if it actually becomes necessary; probably only
         * necessary if the list becomes too long to walk.
         */
        mapRegion(_endBrkPoint, length, "heap");
        _endBrkPoint = page_aligned_brk;
    }

    _brkPoint = new_brk;
}

void
MemState::mapRegion(Addr start_addr, Addr length,
                    const std::string& region_name, int sim_fd, Addr offset)
{
    DPRINTF(Vma, "memstate: creating vma (%s) [0x%x - 0x%x]\n",
            region_name.c_str(), start_addr, start_addr + length);

    /**
     * Avoid creating a region that has preexisting mappings. This should
     * not happen under normal circumstances so consider this to be a bug.
     */
    assert(isUnmapped(start_addr, length));

    /**
     * Record the region in our list structure.
     */
    _vmaList.emplace_back(AddrRange(start_addr, start_addr + length),
                          _pageBytes, region_name, sim_fd, offset);
}

void
MemState::unmapRegion(Addr start_addr, Addr length)
{
    Addr end_addr = start_addr + length;
    const AddrRange range(start_addr, end_addr);

    auto vma = std::begin(_vmaList);
    while (vma != std::end(_vmaList)) {
        if (vma->isStrictSuperset(range)) {
            DPRINTF(Vma, "memstate: split vma [0x%x - 0x%x] into "
                    "[0x%x - 0x%x] and [0x%x - 0x%x]\n",
                    vma->start(), vma->end(),
                    vma->start(), start_addr,
                    end_addr, vma->end());
            /**
             * Need to split into two smaller regions.
             * Create a clone of the old VMA and slice it to the right.
             */
            _vmaList.push_back(*vma);
            _vmaList.back().sliceRegionRight(start_addr);

            /**
             * Slice old VMA to encapsulate the left region.
             */
            vma->sliceRegionLeft(end_addr);

            /**
             * Region cannot be in any more VMA, because it is completely
             * contained in this one!
             */
            break;
        } else if (vma->isSubset(range)) {
            DPRINTF(Vma, "memstate: destroying vma [0x%x - 0x%x]\n",
                    vma->start(), vma->end());
            /**
             * Need to nuke the existing VMA.
             */
            vma = _vmaList.erase(vma);

            continue;

        } else if (vma->intersects(range)) {
            /**
             * Trim up the existing VMA.
             */
            if (vma->start() < start_addr) {
                DPRINTF(Vma, "memstate: resizing vma [0x%x - 0x%x] "
                        "into [0x%x - 0x%x]\n",
                        vma->start(), vma->end(),
                        vma->start(), start_addr);
                /**
                 * Overlaps from the right.
                 */
                vma->sliceRegionRight(start_addr);
            } else {
                DPRINTF(Vma, "memstate: resizing vma [0x%x - 0x%x] "
                        "into [0x%x - 0x%x]\n",
                        vma->start(), vma->end(),
                        end_addr, vma->end());
                /**
                 * Overlaps from the left.
                 */
                vma->sliceRegionLeft(end_addr);
            }
        }

        vma++;
    }

    /**
     * TLBs need to be flushed to remove any stale mappings from regions
     * which were unmapped. Currently the entire TLB is flushed. This results
     * in functionally correct execution, but real systems do not flush all
     * entries when a single mapping changes since it degrades performance.
     * There is currently no general method across all TLB implementations
     * that can flush just part of the address space.
     */
    for (auto tc : _ownerProcess->system->threadContexts) {
        tc->getDTBPtr()->flushAll();
        tc->getITBPtr()->flushAll();
    }

    do {
        if (!_ownerProcess->pTable->isUnmapped(start_addr, _pageBytes))
            _ownerProcess->pTable->unmap(start_addr, _pageBytes);

        start_addr += _pageBytes;

        /**
         * The regions need to always be page-aligned otherwise the while
         * condition will loop indefinitely. (The Addr type is currently
         * defined to be uint64_t in src/base/types.hh; it can underflow
         * since it is unsigned.)
         */
        length -= _pageBytes;
    } while (length > 0);
}

void
MemState::remapRegion(Addr start_addr, Addr new_start_addr, Addr length)
{
    Addr end_addr = start_addr + length;
    const AddrRange range(start_addr, end_addr);

    auto vma = std::begin(_vmaList);
    while (vma != std::end(_vmaList)) {
        if (vma->isStrictSuperset(range)) {
            /**
             * Create clone of the old VMA and slice right.
             */
            _vmaList.push_back(*vma);
            _vmaList.back().sliceRegionRight(start_addr);

            /**
             * Create clone of the old VMA and slice it left.
             */
            _vmaList.push_back(*vma);
            _vmaList.back().sliceRegionLeft(end_addr);

            /**
             * Slice the old VMA left and right to adjust the file backing,
             * then overwrite the virtual addresses!
             */
            vma->sliceRegionLeft(start_addr);
            vma->sliceRegionRight(end_addr);
            vma->remap(new_start_addr);

            /**
             * The region cannot be in any more VMAs, because it is
             * completely contained in this one!
             */
            break;
        } else if (vma->isSubset(range)) {
            /**
             * Just go ahead and remap it!
             */
            vma->remap(vma->start() - start_addr + new_start_addr);
        } else if (vma->intersects(range)) {
            /**
             * Create a clone of the old VMA.
             */
            _vmaList.push_back(*vma);

            if (vma->start() < start_addr) {
                /**
                 * Overlaps from the right.
                 */
                _vmaList.back().sliceRegionRight(start_addr);

                /**
                 * Remap the old region.
                 */
                vma->sliceRegionLeft(start_addr);
                vma->remap(new_start_addr);
            } else {
                /**
                 * Overlaps from the left.
                 */
                _vmaList.back().sliceRegionLeft(end_addr);

                /**
                 * Remap the old region.
                 */
                vma->sliceRegionRight(end_addr);
                vma->remap(new_start_addr + vma->start() - start_addr);
            }
        }

        vma++;
    }

    /**
     * TLBs need to be flushed to remove any stale mappings from regions
     * which were remapped. Currently the entire TLB is flushed. This results
     * in functionally correct execution, but real systems do not flush all
     * entries when a single mapping changes since it degrades performance.
     * There is currently no general method across all TLB implementations
     * that can flush just part of the address space.
     */
    for (auto tc : _ownerProcess->system->threadContexts) {
        tc->getDTBPtr()->flushAll();
        tc->getITBPtr()->flushAll();
    }

    do {
        if (!_ownerProcess->pTable->isUnmapped(start_addr, _pageBytes))
            _ownerProcess->pTable->remap(start_addr, _pageBytes,
                                         new_start_addr);

        start_addr += _pageBytes;

        /**
         * The regions need to always be page-aligned otherwise the while
         * condition will loop indefinitely. (The Addr type is currently
         * defined to be uint64_t in src/base/types.hh; it can underflow
         * since it is unsigned.)
         */
        length -= _pageBytes;
    } while (length > 0);
}

bool
MemState::fixupFault(Addr vaddr)
{
    /**
     * Check if we are accessing a mapped virtual address. If so then we
     * just haven't allocated it a physical page yet and can do so here.
     */
    for (const auto &vma : _vmaList) {
        if (vma.contains(vaddr)) {
            Addr vpage_start = roundDown(vaddr, _pageBytes);
            _ownerProcess->allocateMem(vpage_start, _pageBytes);

            /**
             * We are assuming that fresh pages are zero-filled, so there is
             * no need to zero them out when there is no backing file.
             * This assumption will not hold true if/when physical pages
             * are recycled.
             */
            if (vma.hasHostBuf()) {
                /**
                 * Write the memory for the host buffer contents for all
                 * ThreadContexts associated with this process.
                 */
                for (auto &cid : _ownerProcess->contextIds) {
                    ThreadContext *tc =
                        _ownerProcess->system->getThreadContext(cid);
                    SETranslatingPortProxy
                        virt_mem(tc, SETranslatingPortProxy::Always);
                    vma.fillMemPages(vpage_start, _pageBytes, virt_mem);
                }
            }
            return true;
        }
    }

    /**
     * Check if the stack needs to be grown in the case where the ISAs
     * process argsInit does not explicitly map the entire stack.
     *
     * Check if this is already on the stack and there's just no page there
     * yet.
     */
    if (vaddr >= _stackMin && vaddr < _stackBase) {
        _ownerProcess->allocateMem(roundDown(vaddr, _pageBytes), _pageBytes);
        return true;
    }

    /**
     * We've accessed the next page of the stack, so extend it to include
     * this address.
     */
    if (vaddr < _stackMin && vaddr >= _stackBase - _maxStackSize) {
        while (vaddr < _stackMin) {
            _stackMin -= _pageBytes;
            if (_stackBase - _stackMin > _maxStackSize) {
                fatal("Maximum stack size exceeded\n");
            }
            _ownerProcess->allocateMem(_stackMin, _pageBytes);
            inform("Increasing stack size by one page.");
        }
        return true;
    }

    return false;
}

Addr
MemState::extendMmap(Addr length)
{
    Addr start = _mmapEnd;

    if (_ownerProcess->mmapGrowsDown())
        start = _mmapEnd - length;

    // Look for a contiguous region of free virtual memory.  We can't assume
    // that the region beyond mmap_end is free because of fixed mappings from
    // the user.
    while (!isUnmapped(start, length)) {
        DPRINTF(Vma, "memstate: cannot extend vma for mmap region at %p. "
                "Virtual address range is already reserved! Skipping a page "
                "and trying again!\n", start);
        start = (_ownerProcess->mmapGrowsDown()) ? start - _pageBytes :
            start + _pageBytes;
    }

    DPRINTF(Vma, "memstate: extending mmap region (old %p) (new %p)\n",
            _mmapEnd,
            _ownerProcess->mmapGrowsDown() ? start : start + length);

    _mmapEnd = _ownerProcess->mmapGrowsDown() ? start : start + length;

    return start;
}

std::string
MemState::printVmaList()
{
    std::stringstream file_content;

    for (auto vma : _vmaList) {
        std::stringstream line;
        line << std::hex << vma.start() << "-";
        line << std::hex << vma.end() << " ";
        line << "r-xp 00000000 00:00 0 ";
        line << "[" << vma.getName() << "]" << std::endl;
        file_content << line.str();
    }

    return file_content.str();
}
