/*
 * Copyright (c) 2010, 2012-2013, 2015,2017-2019 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2002-2006 The Regents of The University of Michigan
 * 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: Ali Saidi
 */

#include "arch/arm/system.hh"

#include <iostream>

#include "arch/arm/semihosting.hh"
#include "base/loader/object_file.hh"
#include "base/loader/symtab.hh"
#include "cpu/thread_context.hh"
#include "dev/arm/gic_v3.hh"
#include "mem/fs_translating_port_proxy.hh"
#include "mem/physical.hh"
#include "sim/full_system.hh"

using namespace std;
using namespace Linux;

ArmSystem::ArmSystem(Params *p)
    : System(p),
      bootLoaders(), bootldr(nullptr),
      _haveSecurity(p->have_security),
      _haveLPAE(p->have_lpae),
      _haveVirtualization(p->have_virtualization),
      _haveCrypto(p->have_crypto),
      _genericTimer(nullptr),
      _gic(nullptr),
      _resetAddr(p->auto_reset_addr ?
                 (kernelEntry & loadAddrMask) + loadAddrOffset :
                 p->reset_addr),
      _highestELIs64(p->highest_el_is_64),
      _physAddrRange64(p->phys_addr_range_64),
      _haveLargeAsid64(p->have_large_asid_64),
      _haveSVE(p->have_sve),
      _sveVL(p->sve_vl),
      _havePAN(p->have_pan),
      _m5opRange(p->m5ops_base ?
                 RangeSize(p->m5ops_base, 0x10000) :
                 AddrRange(1, 0)), // Create an empty range if disabled
      semihosting(p->semihosting),
      multiProc(p->multi_proc)
{
    // Check if the physical address range is valid
    if (_highestELIs64 && (
            _physAddrRange64 < 32 ||
            _physAddrRange64 > 48 ||
            (_physAddrRange64 % 4 != 0 && _physAddrRange64 != 42))) {
        fatal("Invalid physical address range (%d)\n", _physAddrRange64);
    }

    bootLoaders.reserve(p->boot_loader.size());
    for (const auto &bl : p->boot_loader) {
        std::unique_ptr<ObjectFile> obj;
        obj.reset(createObjectFile(bl));

        fatal_if(!obj, "Could not read bootloader: %s\n", bl);
        bootLoaders.emplace_back(std::move(obj));
    }

    if (kernel) {
        bootldr = getBootLoader(kernel);
    } else if (!bootLoaders.empty()) {
        // No kernel specified, default to the first boot loader
        bootldr = bootLoaders[0].get();
    }

    if (!bootLoaders.empty() && !bootldr)
        fatal("Can't find a matching boot loader / kernel combination!");

    if (bootldr) {
        bootldr->loadGlobalSymbols(debugSymbolTable);

        warn_if(bootldr->entryPoint() != _resetAddr,
                "Bootloader entry point %#x overriding reset address %#x",
                bootldr->entryPoint(), _resetAddr);
        const_cast<Addr&>(_resetAddr) = bootldr->entryPoint();

        if ((bootldr->getArch() == ObjectFile::Arm64) && !_highestELIs64) {
            warn("Highest ARM exception-level set to AArch32 but bootloader "
                  "is for AArch64. Assuming you wanted these to match.\n");
            _highestELIs64 = true;
        } else if ((bootldr->getArch() == ObjectFile::Arm) && _highestELIs64) {
            warn("Highest ARM exception-level set to AArch64 but bootloader "
                  "is for AArch32. Assuming you wanted these to match.\n");
            _highestELIs64 = false;
        }
    }

    debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
}

void
ArmSystem::initState()
{
    // Moved from the constructor to here since it relies on the
    // address map being resolved in the interconnect

    // Call the initialisation of the super class
    System::initState();

    const Params* p = params();

    if (bootldr) {
        bool isGICv3System = dynamic_cast<Gicv3 *>(getGIC()) != nullptr;
        bootldr->loadSections(physProxy);

        inform("Using bootloader at address %#x\n", bootldr->entryPoint());

        // Put the address of the boot loader into r7 so we know
        // where to branch to after the reset fault
        // All other values needed by the boot loader to know what to do
        if (!p->flags_addr)
           fatal("flags_addr must be set with bootloader\n");

        if (!p->gic_cpu_addr && !isGICv3System)
            fatal("gic_cpu_addr must be set with bootloader\n");

        for (int i = 0; i < threadContexts.size(); i++) {
            if (!_highestELIs64)
                threadContexts[i]->setIntReg(3, (kernelEntry & loadAddrMask) +
                        loadAddrOffset);
            if (!isGICv3System)
                threadContexts[i]->setIntReg(4, params()->gic_cpu_addr);
            threadContexts[i]->setIntReg(5, params()->flags_addr);
        }
        inform("Using kernel entry physical address at %#x\n",
               (kernelEntry & loadAddrMask) + loadAddrOffset);
    } else {
        // Set the initial PC to be at start of the kernel code
        if (!_highestELIs64)
            threadContexts[0]->pcState((kernelEntry & loadAddrMask) +
                    loadAddrOffset);
    }
}

ArmSystem*
ArmSystem::getArmSystem(ThreadContext *tc)
{
    ArmSystem *a_sys = dynamic_cast<ArmSystem *>(tc->getSystemPtr());
    assert(a_sys);
    return a_sys;
}

bool
ArmSystem::haveSecurity(ThreadContext *tc)
{
    return FullSystem? getArmSystem(tc)->haveSecurity() : false;
}


ArmSystem::~ArmSystem()
{
    if (debugPrintkEvent)
        delete debugPrintkEvent;
}

ObjectFile *
ArmSystem::getBootLoader(ObjectFile *const obj)
{
    for (auto &bl : bootLoaders) {
        if (bl->getArch() == obj->getArch())
            return bl.get();
    }

    return nullptr;
}

bool
ArmSystem::haveLPAE(ThreadContext *tc)
{
    return FullSystem? getArmSystem(tc)->haveLPAE() : false;
}

bool
ArmSystem::haveVirtualization(ThreadContext *tc)
{
    return FullSystem? getArmSystem(tc)->haveVirtualization() : false;
}

bool
ArmSystem::highestELIs64(ThreadContext *tc)
{
    return FullSystem? getArmSystem(tc)->highestELIs64() : true;
}

ExceptionLevel
ArmSystem::highestEL(ThreadContext *tc)
{
    return FullSystem? getArmSystem(tc)->highestEL() : EL1;
}

bool
ArmSystem::haveEL(ThreadContext *tc, ExceptionLevel el)
{
    switch (el) {
      case EL0:
      case EL1:
        return true;
      case EL2:
        return haveVirtualization(tc);
      case EL3:
        return haveSecurity(tc);
      default:
        warn("Unimplemented Exception Level\n");
        return false;
    }
}

Addr
ArmSystem::resetAddr(ThreadContext *tc)
{
    return getArmSystem(tc)->resetAddr();
}

uint8_t
ArmSystem::physAddrRange(ThreadContext *tc)
{
    return getArmSystem(tc)->physAddrRange();
}

Addr
ArmSystem::physAddrMask(ThreadContext *tc)
{
    return getArmSystem(tc)->physAddrMask();
}

bool
ArmSystem::haveLargeAsid64(ThreadContext *tc)
{
    return getArmSystem(tc)->haveLargeAsid64();
}

bool
ArmSystem::haveSemihosting(ThreadContext *tc)
{
    return FullSystem && getArmSystem(tc)->haveSemihosting();
}

uint64_t
ArmSystem::callSemihosting64(ThreadContext *tc,
                             uint32_t op, uint64_t param)
{
    ArmSystem *sys = getArmSystem(tc);
    return sys->semihosting->call64(tc, op, param);
}

uint32_t
ArmSystem::callSemihosting32(ThreadContext *tc,
                             uint32_t op, uint32_t param)
{
    ArmSystem *sys = getArmSystem(tc);
    return sys->semihosting->call32(tc, op, param);
}

ArmSystem *
ArmSystemParams::create()
{
    return new ArmSystem(this);
}

void
GenericArmSystem::initState()
{
    // Moved from the constructor to here since it relies on the
    // address map being resolved in the interconnect

    // Call the initialisation of the super class
    ArmSystem::initState();
}

GenericArmSystem *
GenericArmSystemParams::create()
{

    return new GenericArmSystem(this);
}
