/*
 * Copyright (c) 2021 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:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. Neither the name of the copyright holder 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 HOLDER 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 "arch/amdgpu/vega/pagetable_walker.hh"

#include <memory>

#include "arch/amdgpu/vega/faults.hh"
#include "mem/abstract_mem.hh"
#include "mem/packet_access.hh"

namespace gem5
{
namespace VegaISA
{

/*
 * Functional/atomic mode methods
 */
Fault
Walker::startFunctional(Addr base, Addr &addr, unsigned &logBytes,
                        BaseMMU::Mode mode, bool &isSystem)
{
    PageTableEntry pte;
    Addr vaddr = addr;
    Fault fault = startFunctional(base, vaddr, pte, logBytes, mode);
    isSystem = pte.s;
    addr = ((pte.ppn << PageShift) + (vaddr & mask(logBytes)));

    return fault;
}

Fault
Walker::startFunctional(Addr base, Addr vaddr, PageTableEntry &pte,
                        unsigned &logBytes, BaseMMU::Mode mode)
{
    DPRINTF(GPUPTWalker, "Vega walker walker: %p funcState: %p "
            "funcState->walker %p\n",
            this, &funcState, funcState.getWalker());
    funcState.initState(mode, base, vaddr, true);
    return funcState.startFunctional(base, vaddr, pte, logBytes);
}

Fault
Walker::WalkerState::startFunctional(Addr base, Addr vaddr,
                                     PageTableEntry &pte, unsigned &logBytes)
{
    Fault fault = NoFault;
    DPRINTF(GPUPTWalker, "Vega walker starting with addr: %#lx "
            "logical: %#lx\n", vaddr, vaddr >> PageShift);

    assert(!started);
    started = true;

    do {
        DPRINTF(GPUPTWalker, "Sending functional read to %#lx\n",
                read->getAddr());

        auto devmem = walker->system->getDeviceMemory(read);
        assert(devmem);
        devmem->access(read);

        fault = stepWalk();
        assert(fault == NoFault || read == NULL);

        state = nextState;
    } while (read);

    logBytes = entry.logBytes;
    pte = entry.pte;

    return fault;
}


/*
 * Timing mode methods
 */
void
Walker::startTiming(PacketPtr pkt, Addr base, Addr vaddr, BaseMMU::Mode mode)
{
    DPRINTF(GPUPTWalker, "Vega walker starting with addr: %#lx "
            "logical: %#lx\n", vaddr, vaddr >> PageShift);

    WalkerState *newState = new WalkerState(this, pkt);

    newState->initState(mode, base, vaddr);
    currStates.push_back(newState);
    DPRINTF(GPUPTWalker, "There are %ld walker states\n", currStates.size());

    newState->startWalk();
}

void
Walker::WalkerState::initState(BaseMMU::Mode _mode, Addr baseAddr, Addr vaddr,
                               bool is_functional)
{
    DPRINTF(GPUPTWalker, "Walker::WalkerState::initState\n");
    DPRINTF(GPUPTWalker, "Walker::WalkerState::initState %p\n", this);
    DPRINTF(GPUPTWalker, "Walker::WalkerState::initState %d\n", state);
    assert(state == Ready);

    started = false;
    mode = _mode;
    timing = !is_functional;
    enableNX = true;
    dataSize = 8; // 64-bit PDEs / PTEs
    nextState = PDE2;

    DPRINTF(GPUPTWalker, "Setup walk with base %#lx\n", baseAddr);

    // First level in Vega is PDE2. Calculate the address for that PDE using
    // baseAddr and vaddr.
    state = PDE2;
    Addr logical_addr = vaddr >> PageShift;
    Addr pde2Addr = (((baseAddr >> 6) << 3) + (logical_addr >> 3*9)) << 3;
    DPRINTF(GPUPTWalker, "Walk PDE2 address is %#lx\n", pde2Addr);

    // Start populating the VegaTlbEntry response
    entry.vaddr = logical_addr;

    // Prepare the read packet that will be used at each level
    Request::Flags flags = Request::PHYSICAL;

    RequestPtr request = std::make_shared<Request>(
        pde2Addr, dataSize, flags, walker->deviceRequestorId);

    read = new Packet(request, MemCmd::ReadReq);
    read->allocate();
}

void
Walker::WalkerState::startWalk()
{
    if (!started) {
        // Read the first PDE to begin
        DPRINTF(GPUPTWalker, "Sending timing read to %#lx\n",
                read->getAddr());

        sendPackets();
        started = true;
    } else {
        // This is mostly the same as stepWalk except we update the state and
        // send the new timing read request.
        timingFault = stepWalk();
        assert(timingFault == NoFault || read == NULL);

        state = nextState;

        if (read) {
            DPRINTF(GPUPTWalker, "Sending timing read to %#lx\n",
                    read->getAddr());
            sendPackets();
        } else {
            // Set physical page address in entry
            entry.paddr = entry.pte.ppn << PageShift;
            entry.paddr += entry.vaddr & mask(entry.logBytes);

            // Insert to TLB
            assert(walker);
            assert(walker->tlb);
            walker->tlb->insert(entry.vaddr, entry);

            // Send translation return event
            walker->walkerResponse(this, entry, tlbPkt);
        }
    }
}

Fault
Walker::WalkerState::stepWalk()
{
    assert(state != Ready && state != Waiting && read);
    Fault fault = NoFault;
    PageTableEntry pte = read->getLE<uint64_t>();

    bool uncacheable = !pte.c;
    Addr nextRead = 0;
    bool doEndWalk = false;

    walkStateMachine(pte, nextRead, doEndWalk, fault);

    if (doEndWalk) {
        DPRINTF(GPUPTWalker, "ending walk\n");
        endWalk();
    } else {
        PacketPtr oldRead = read;

        //If we didn't return, we're setting up another read.
        Request::Flags flags = oldRead->req->getFlags();
        flags.set(Request::UNCACHEABLE, uncacheable);
        RequestPtr request = std::make_shared<Request>(
            nextRead, oldRead->getSize(), flags, walker->deviceRequestorId);

        read = new Packet(request, MemCmd::ReadReq);
        read->allocate();

        delete oldRead;
    }

    return fault;
}

void
Walker::WalkerState::walkStateMachine(PageTableEntry &pte, Addr &nextRead,
                                      bool &doEndWalk, Fault &fault)
{
    Addr vaddr = entry.vaddr;
    bool badNX = pte.x && mode == BaseMMU::Execute && enableNX;
    Addr part1 = 0;
    Addr part2 = 0;
    PageDirectoryEntry pde = static_cast<PageDirectoryEntry>(pte);

    // For a four level page table block fragment size should not be needed.
    // For now issue a panic to prevent strange behavior if it is non-zero.
    panic_if(pde.blockFragmentSize, "PDE blockFragmentSize must be 0");

    switch(state) {
      case PDE2:
        fatal_if(pde.p, "Fragment in PDE2 not implemented");

        // Read the pde1Addr
        part1 = ((((uint64_t)pte) >> 6) << 3);
        part2 = offsetFunc(vaddr, 3*9, 2*9);
        nextRead = ((part1 + part2) << 3) & mask(48);
        DPRINTF(GPUPTWalker,
                "Got PDE2 entry %#016x. write:%s->%#016x va:%#016x\n",
                (uint64_t)pte, pte.w == 0 ? "yes" : "no", nextRead, vaddr);
        nextState = PDE1;
        break;
      case PDE1:
        fatal_if(pde.p, "Fragment in PDE1 not implemented");

        // Read the pde0Addr
        part1 = ((((uint64_t)pte) >> 6) << 3);
        part2 = offsetFunc(vaddr, 2*9, 9);
        nextRead = ((part1 + part2) << 3) & mask(48);
        DPRINTF(GPUPTWalker,
                "Got PDE1 entry %#016x. write:%s->%#016x va: %#016x\n",
                (uint64_t)pte, pte.w == 0 ? "yes" : "no", nextRead, vaddr);
        nextState = PDE0;
        break;
      case PDE0:
        if (pde.p) {
            DPRINTF(GPUPTWalker, "Treating PDE0 as PTE: %#016x frag: %d\n",
                    (uint64_t)pte, pte.fragment);
            entry.pte = pte;
            int fragment = pte.fragment;
            entry.logBytes = PageShift + std::min(9, fragment);
            entry.vaddr <<= PageShift;
            entry.vaddr = entry.vaddr & ~mask(entry.logBytes);
            doEndWalk = true;
        }
        // Read the PteAddr
        part1 = ((((uint64_t)pte) >> 6) << 3);
        part2 = offsetFunc(vaddr, 9, 0);
        nextRead = ((part1 + part2) << 3) & mask(48);
        DPRINTF(GPUPTWalker,
                "Got PDE0 entry %#016x. write:%s->%#016x va:%#016x\n",
                (uint64_t)pte, pte.w == 0 ? "yes" : "no", nextRead, vaddr);
        nextState = PTE;
        break;
      case PTE:
        DPRINTF(GPUPTWalker,
                " PTE entry %#016x. write: %s va: %#016x\n",
                (uint64_t)pte, pte.w == 0 ? "yes" : "no", vaddr);
        entry.pte = pte;
        entry.logBytes = PageShift;
        entry.vaddr <<= PageShift;
        entry.vaddr = entry.vaddr & ~mask(entry.logBytes);
        doEndWalk = true;
        break;
      default:
        panic("Unknown page table walker state %d!\n");
    }

    if (badNX || !pte.v) {
        doEndWalk = true;
        fault = pageFault(pte.v);
        nextState = state;
    }
}

void
Walker::WalkerState::endWalk()
{
    nextState = Ready;
    delete read;
    read = NULL;
    walker->currStates.remove(this);
}

/**
 * Port related methods
 */
void
Walker::WalkerState::sendPackets()
{
    // If we're already waiting for the port to become available, just return.
    if (retrying)
        return;

    if (!walker->sendTiming(this, read)) {
        DPRINTF(GPUPTWalker, "Timing request for %#lx failed\n",
                read->getAddr());

        retrying = true;
    } else {
        DPRINTF(GPUPTWalker, "Timing request for %#lx successful\n",
                read->getAddr());
    }
}

bool Walker::sendTiming(WalkerState* sending_walker, PacketPtr pkt)
{
    auto walker_state = new WalkerSenderState(sending_walker);
    pkt->pushSenderState(walker_state);

    if (port.sendTimingReq(pkt)) {
        DPRINTF(GPUPTWalker, "Sending timing read to %#lx from walker %p\n",
                pkt->getAddr(), sending_walker);

        return true;
    } else {
        (void)pkt->popSenderState();
    }

    return false;
}

bool
Walker::WalkerPort::recvTimingResp(PacketPtr pkt)
{
    walker->recvTimingResp(pkt);

    return true;
}

void
Walker::recvTimingResp(PacketPtr pkt)
{
    WalkerSenderState * senderState =
        safe_cast<WalkerSenderState *>(pkt->popSenderState());

    DPRINTF(GPUPTWalker, "Got response for %#lx from walker %p -- %#lx\n",
            pkt->getAddr(), senderState->senderWalk, pkt->getLE<uint64_t>());
    senderState->senderWalk->startWalk();

    delete senderState;
}

void
Walker::WalkerPort::recvReqRetry()
{
    walker->recvReqRetry();
}

void
Walker::recvReqRetry()
{
    std::list<WalkerState *>::iterator iter;
    for (iter = currStates.begin(); iter != currStates.end(); iter++) {
        WalkerState * walkerState = *(iter);
        if (walkerState->isRetrying()) {
            walkerState->retry();
        }
    }
}

void
Walker::walkerResponse(WalkerState *state, VegaTlbEntry& entry, PacketPtr pkt)
{
    tlb->walkerResponse(entry, pkt);

    delete state;
}


/*
 *  Helper methods
 */
bool
Walker::WalkerState::isRetrying()
{
    return retrying;
}

void
Walker::WalkerState::retry()
{
    retrying = false;
    sendPackets();
}

Fault
Walker::WalkerState::pageFault(bool present)
{
    DPRINTF(GPUPTWalker, "Raising page fault.\n");
    ExceptionCode code;
    if (mode == BaseMMU::Read)
        code = ExceptionCode::LOAD_PAGE;
    else if (mode == BaseMMU::Write)
        code = ExceptionCode::STORE_PAGE;
    else
        code = ExceptionCode::INST_PAGE;
    if (mode == BaseMMU::Execute && !enableNX)
        mode = BaseMMU::Read;
    return std::make_shared<PageFault>(entry.vaddr, code, present, mode, true);
}

uint64_t
Walker::WalkerState::offsetFunc(Addr logicalAddr, int top, int lsb)
{
    assert(top < 32);
    assert(lsb < 32);
    return ((logicalAddr & ((1 << top) - 1)) >> lsb);
}


/**
 * gem5 methods
 */
Port &
Walker::getPort(const std::string &if_name, PortID idx)
{
    if (if_name == "port")
        return port;
    else
        return ClockedObject::getPort(if_name, idx);
}

} // namespace VegaISA
} // namespace gem5
