system.cc revision 12531:3141027bd11a
17405SAli.Saidi@ARM.com/*
212667Schuan.zhu@arm.com * Copyright (c) 2010, 2012-2013, 2015,2017-2018 ARM Limited
37405SAli.Saidi@ARM.com * All rights reserved
47405SAli.Saidi@ARM.com *
57405SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall
67405SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual
77405SAli.Saidi@ARM.com * property including but not limited to intellectual property relating
87405SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software
97405SAli.Saidi@ARM.com * licensed hereunder.  You may use the software subject to the license
107405SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated
117405SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software,
127405SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form.
137405SAli.Saidi@ARM.com *
147405SAli.Saidi@ARM.com * Copyright (c) 2002-2006 The Regents of The University of Michigan
157405SAli.Saidi@ARM.com * All rights reserved.
167405SAli.Saidi@ARM.com *
177405SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
187405SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
197405SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
207405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
217405SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
227405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
237405SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
247405SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
257405SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
267405SAli.Saidi@ARM.com * this software without specific prior written permission.
277405SAli.Saidi@ARM.com *
287405SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
297405SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
307405SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
317405SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
327405SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
337405SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
347405SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
357405SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
367405SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
377405SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
387405SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
397405SAli.Saidi@ARM.com *
407405SAli.Saidi@ARM.com * Authors: Ali Saidi
417405SAli.Saidi@ARM.com */
4210461SAndreas.Sandberg@ARM.com
439050Schander.sudanthi@arm.com#include "arch/arm/system.hh"
4412406Sgabeblack@google.com
4512605Sgiacomo.travaglini@arm.com#include <iostream>
4611793Sbrandon.potter@amd.com
478887Sgeoffrey.blake@arm.com#include "arch/arm/semihosting.hh"
488232Snate@binkert.org#include "base/loader/object_file.hh"
498232Snate@binkert.org#include "base/loader/symtab.hh"
5010844Sandreas.sandberg@arm.com#include "cpu/thread_context.hh"
5113531Sjairo.balart@metempsy.com#include "mem/fs_translating_port_proxy.hh"
5213531Sjairo.balart@metempsy.com#include "mem/physical.hh"
539384SAndreas.Sandberg@arm.com#include "sim/full_system.hh"
547678Sgblack@eecs.umich.edu
558059SAli.Saidi@ARM.comusing namespace std;
568284SAli.Saidi@ARM.comusing namespace Linux;
577405SAli.Saidi@ARM.com
587405SAli.Saidi@ARM.comArmSystem::ArmSystem(Params *p)
597405SAli.Saidi@ARM.com    : System(p),
607405SAli.Saidi@ARM.com      bootLoaders(), bootldr(nullptr),
619384SAndreas.Sandberg@arm.com      _haveSecurity(p->have_security),
6210461SAndreas.Sandberg@ARM.com      _haveLPAE(p->have_lpae),
6310461SAndreas.Sandberg@ARM.com      _haveVirtualization(p->have_virtualization),
6411165SRekai.GonzalezAlberquilla@arm.com      _genericTimer(nullptr),
6512109SRekai.GonzalezAlberquilla@arm.com      _highestELIs64(p->highest_el_is_64),
6612714Sgiacomo.travaglini@arm.com      _resetAddr64(p->auto_reset_addr_64 ?
6712714Sgiacomo.travaglini@arm.com                   (kernelEntry & loadAddrMask) + loadAddrOffset :
689384SAndreas.Sandberg@arm.com                   p->reset_addr_64),
6911770SCurtis.Dunham@arm.com      _physAddrRange64(p->phys_addr_range_64),
7010037SARM gem5 Developers      _haveLargeAsid64(p->have_large_asid_64),
7110461SAndreas.Sandberg@ARM.com      _m5opRange(p->m5ops_base ?
7210461SAndreas.Sandberg@ARM.com                 RangeSize(p->m5ops_base, 0x10000) :
7310461SAndreas.Sandberg@ARM.com                 AddrRange(1, 0)), // Create an empty range if disabled
7410461SAndreas.Sandberg@ARM.com      semihosting(p->semihosting),
7510461SAndreas.Sandberg@ARM.com      multiProc(p->multi_proc)
7610461SAndreas.Sandberg@ARM.com{
7710609Sandreas.sandberg@arm.com    // Check if the physical address range is valid
7810609Sandreas.sandberg@arm.com    if (_highestELIs64 && (
7910609Sandreas.sandberg@arm.com            _physAddrRange64 < 32 ||
8010037SARM gem5 Developers            _physAddrRange64 > 48 ||
8110037SARM gem5 Developers            (_physAddrRange64 % 4 != 0 && _physAddrRange64 != 42))) {
8210037SARM gem5 Developers        fatal("Invalid physical address range (%d)\n", _physAddrRange64);
8310037SARM gem5 Developers    }
8411771SCurtis.Dunham@arm.com
8510037SARM gem5 Developers    bootLoaders.reserve(p->boot_loader.size());
8610037SARM gem5 Developers    for (const auto &bl : p->boot_loader) {
8713173Sgiacomo.travaglini@arm.com        std::unique_ptr<ObjectFile> obj;
8810037SARM gem5 Developers        obj.reset(createObjectFile(bl));
8910037SARM gem5 Developers
9013114Sgiacomo.travaglini@arm.com        fatal_if(!obj, "Could not read bootloader: %s\n", bl);
9110037SARM gem5 Developers        bootLoaders.emplace_back(std::move(obj));
9211771SCurtis.Dunham@arm.com    }
9310037SARM gem5 Developers
9413499Sgiacomo.travaglini@arm.com    if (kernel) {
9510037SARM gem5 Developers        bootldr = getBootLoader(kernel);
9613114Sgiacomo.travaglini@arm.com    } else if (!bootLoaders.empty()) {
9710037SARM gem5 Developers        // No kernel specified, default to the first boot loader
9810037SARM gem5 Developers        bootldr = bootLoaders[0].get();
9913531Sjairo.balart@metempsy.com    }
10013531Sjairo.balart@metempsy.com
10113531Sjairo.balart@metempsy.com    if (!bootLoaders.empty() && !bootldr)
10213531Sjairo.balart@metempsy.com        fatal("Can't find a matching boot loader / kernel combination!");
10313531Sjairo.balart@metempsy.com
10413531Sjairo.balart@metempsy.com    if (bootldr) {
10513531Sjairo.balart@metempsy.com        bootldr->loadGlobalSymbols(debugSymbolTable);
10612477SCurtis.Dunham@arm.com        if ((bootldr->getArch() == ObjectFile::Arm64) && !_highestELIs64) {
10710037SARM gem5 Developers            warn("Highest ARM exception-level set to AArch32 but bootloader "
10810037SARM gem5 Developers                  "is for AArch64. Assuming you wanted these to match.\n");
1099384SAndreas.Sandberg@arm.com            _highestELIs64 = true;
1109384SAndreas.Sandberg@arm.com        } else if ((bootldr->getArch() == ObjectFile::Arm) && _highestELIs64) {
1119384SAndreas.Sandberg@arm.com            warn("Highest ARM exception-level set to AArch64 but bootloader "
11212479SCurtis.Dunham@arm.com                  "is for AArch32. Assuming you wanted these to match.\n");
11312479SCurtis.Dunham@arm.com            _highestELIs64 = false;
1149384SAndreas.Sandberg@arm.com        }
1159384SAndreas.Sandberg@arm.com    }
1169384SAndreas.Sandberg@arm.com
1179384SAndreas.Sandberg@arm.com    debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
1189384SAndreas.Sandberg@arm.com}
1199384SAndreas.Sandberg@arm.com
1207427Sgblack@eecs.umich.eduvoid
1217427Sgblack@eecs.umich.eduArmSystem::initState()
1227427Sgblack@eecs.umich.edu{
1239385SAndreas.Sandberg@arm.com    // Moved from the constructor to here since it relies on the
1249385SAndreas.Sandberg@arm.com    // address map being resolved in the interconnect
1257427Sgblack@eecs.umich.edu
1267427Sgblack@eecs.umich.edu    // Call the initialisation of the super class
12710037SARM gem5 Developers    System::initState();
12813114Sgiacomo.travaglini@arm.com
12910037SARM gem5 Developers    const Params* p = params();
13013114Sgiacomo.travaglini@arm.com
13113114Sgiacomo.travaglini@arm.com    if (bootldr) {
13213114Sgiacomo.travaglini@arm.com        bootldr->loadSections(physProxy);
13313114Sgiacomo.travaglini@arm.com
13413114Sgiacomo.travaglini@arm.com        uint8_t jump_to_bl_32[] =
13512690Sgiacomo.travaglini@arm.com        {
13610037SARM gem5 Developers            0x07, 0xf0, 0xa0, 0xe1  // branch to r7 in aarch32
1377427Sgblack@eecs.umich.edu        };
1387427Sgblack@eecs.umich.edu
13910037SARM gem5 Developers        uint8_t jump_to_bl_64[] =
1407427Sgblack@eecs.umich.edu        {
1417427Sgblack@eecs.umich.edu            0xe0, 0x00, 0x1f, 0xd6  // instruction "br x7" in aarch64
1427427Sgblack@eecs.umich.edu        };
1437427Sgblack@eecs.umich.edu
1447427Sgblack@eecs.umich.edu        // write the jump to branch table into address 0
1457427Sgblack@eecs.umich.edu        if (!_highestELIs64)
1467427Sgblack@eecs.umich.edu            physProxy.writeBlob(0x0, jump_to_bl_32, sizeof(jump_to_bl_32));
1477427Sgblack@eecs.umich.edu        else
1487427Sgblack@eecs.umich.edu            physProxy.writeBlob(0x0, jump_to_bl_64, sizeof(jump_to_bl_64));
1497427Sgblack@eecs.umich.edu
1507427Sgblack@eecs.umich.edu        inform("Using bootloader at address %#x\n", bootldr->entryPoint());
1517427Sgblack@eecs.umich.edu
1527427Sgblack@eecs.umich.edu        // Put the address of the boot loader into r7 so we know
1537427Sgblack@eecs.umich.edu        // where to branch to after the reset fault
1547427Sgblack@eecs.umich.edu        // All other values needed by the boot loader to know what to do
1557427Sgblack@eecs.umich.edu        if (!p->gic_cpu_addr || !p->flags_addr)
1567427Sgblack@eecs.umich.edu            fatal("gic_cpu_addr && flags_addr must be set with bootloader\n");
1577427Sgblack@eecs.umich.edu
1587427Sgblack@eecs.umich.edu        for (int i = 0; i < threadContexts.size(); i++) {
1597427Sgblack@eecs.umich.edu            if (!_highestELIs64)
1607427Sgblack@eecs.umich.edu                threadContexts[i]->setIntReg(3, (kernelEntry & loadAddrMask) +
1617427Sgblack@eecs.umich.edu                        loadAddrOffset);
1627427Sgblack@eecs.umich.edu            threadContexts[i]->setIntReg(4, params()->gic_cpu_addr);
1637436Sdam.sunwoo@arm.com            threadContexts[i]->setIntReg(5, params()->flags_addr);
1647436Sdam.sunwoo@arm.com            threadContexts[i]->setIntReg(7, bootldr->entryPoint());
16510037SARM gem5 Developers        }
16610037SARM gem5 Developers        inform("Using kernel entry physical address at %#x\n",
1677436Sdam.sunwoo@arm.com               (kernelEntry & loadAddrMask) + loadAddrOffset);
1687436Sdam.sunwoo@arm.com    } else {
1697436Sdam.sunwoo@arm.com        // Set the initial PC to be at start of the kernel code
1707436Sdam.sunwoo@arm.com        if (!_highestELIs64)
1717436Sdam.sunwoo@arm.com            threadContexts[0]->pcState((kernelEntry & loadAddrMask) +
1727436Sdam.sunwoo@arm.com                    loadAddrOffset);
1737436Sdam.sunwoo@arm.com    }
1747436Sdam.sunwoo@arm.com}
1757436Sdam.sunwoo@arm.com
1767436Sdam.sunwoo@arm.comArmSystem*
1777436Sdam.sunwoo@arm.comArmSystem::getArmSystem(ThreadContext *tc)
1787436Sdam.sunwoo@arm.com{
17913393Sgiacomo.travaglini@arm.com    ArmSystem *a_sys = dynamic_cast<ArmSystem *>(tc->getSystemPtr());
18010037SARM gem5 Developers    assert(a_sys);
1817436Sdam.sunwoo@arm.com    return a_sys;
1827436Sdam.sunwoo@arm.com}
1837436Sdam.sunwoo@arm.com
1847436Sdam.sunwoo@arm.combool
1857436Sdam.sunwoo@arm.comArmSystem::haveSecurity(ThreadContext *tc)
1867436Sdam.sunwoo@arm.com{
1877436Sdam.sunwoo@arm.com    return FullSystem? getArmSystem(tc)->haveSecurity() : false;
1887436Sdam.sunwoo@arm.com}
1897436Sdam.sunwoo@arm.com
1907436Sdam.sunwoo@arm.com
1917436Sdam.sunwoo@arm.comArmSystem::~ArmSystem()
1927436Sdam.sunwoo@arm.com{
1937436Sdam.sunwoo@arm.com    if (debugPrintkEvent)
1947436Sdam.sunwoo@arm.com        delete debugPrintkEvent;
1957436Sdam.sunwoo@arm.com}
1967436Sdam.sunwoo@arm.com
19713393Sgiacomo.travaglini@arm.comObjectFile *
19813393Sgiacomo.travaglini@arm.comArmSystem::getBootLoader(ObjectFile *const obj)
19913393Sgiacomo.travaglini@arm.com{
20013393Sgiacomo.travaglini@arm.com    for (auto &bl : bootLoaders) {
20113393Sgiacomo.travaglini@arm.com        if (bl->getArch() == obj->getArch())
20213393Sgiacomo.travaglini@arm.com            return bl.get();
20313393Sgiacomo.travaglini@arm.com    }
20413393Sgiacomo.travaglini@arm.com
20513393Sgiacomo.travaglini@arm.com    return nullptr;
20613393Sgiacomo.travaglini@arm.com}
20713393Sgiacomo.travaglini@arm.com
20813393Sgiacomo.travaglini@arm.combool
20913393Sgiacomo.travaglini@arm.comArmSystem::haveLPAE(ThreadContext *tc)
21013393Sgiacomo.travaglini@arm.com{
21113393Sgiacomo.travaglini@arm.com    return FullSystem? getArmSystem(tc)->haveLPAE() : false;
21213393Sgiacomo.travaglini@arm.com}
21313396Sgiacomo.travaglini@arm.com
21413396Sgiacomo.travaglini@arm.combool
21513396Sgiacomo.travaglini@arm.comArmSystem::haveVirtualization(ThreadContext *tc)
21613396Sgiacomo.travaglini@arm.com{
21713393Sgiacomo.travaglini@arm.com    return FullSystem? getArmSystem(tc)->haveVirtualization() : false;
21813393Sgiacomo.travaglini@arm.com}
21913393Sgiacomo.travaglini@arm.com
22013393Sgiacomo.travaglini@arm.combool
22113393Sgiacomo.travaglini@arm.comArmSystem::highestELIs64(ThreadContext *tc)
22213393Sgiacomo.travaglini@arm.com{
22313393Sgiacomo.travaglini@arm.com    return FullSystem? getArmSystem(tc)->highestELIs64() : true;
22413393Sgiacomo.travaglini@arm.com}
22513393Sgiacomo.travaglini@arm.com
22613393Sgiacomo.travaglini@arm.comExceptionLevel
22713393Sgiacomo.travaglini@arm.comArmSystem::highestEL(ThreadContext *tc)
22813393Sgiacomo.travaglini@arm.com{
22913393Sgiacomo.travaglini@arm.com    return FullSystem? getArmSystem(tc)->highestEL() : EL1;
23013393Sgiacomo.travaglini@arm.com}
23113393Sgiacomo.travaglini@arm.com
23213393Sgiacomo.travaglini@arm.combool
23313393Sgiacomo.travaglini@arm.comArmSystem::haveEL(ThreadContext *tc, ExceptionLevel el)
23413393Sgiacomo.travaglini@arm.com{
2357644Sali.saidi@arm.com    switch (el) {
2368147SAli.Saidi@ARM.com      case EL0:
2379385SAndreas.Sandberg@arm.com      case EL1:
2389385SAndreas.Sandberg@arm.com        return true;
23910037SARM gem5 Developers      case EL2:
24010037SARM gem5 Developers        return haveVirtualization(tc);
24110037SARM gem5 Developers      case EL3:
24210037SARM gem5 Developers        return haveSecurity(tc);
24310037SARM gem5 Developers      default:
24410037SARM gem5 Developers        warn("Unimplemented Exception Level\n");
24510037SARM gem5 Developers        return false;
24610037SARM gem5 Developers    }
24710037SARM gem5 Developers}
24810037SARM gem5 Developers
24910037SARM gem5 DevelopersAddr
25010037SARM gem5 DevelopersArmSystem::resetAddr64(ThreadContext *tc)
25110037SARM gem5 Developers{
25210037SARM gem5 Developers    return getArmSystem(tc)->resetAddr64();
25310037SARM gem5 Developers}
25410037SARM gem5 Developers
2558147SAli.Saidi@ARM.comuint8_t
2567427Sgblack@eecs.umich.eduArmSystem::physAddrRange(ThreadContext *tc)
2577427Sgblack@eecs.umich.edu{
2587427Sgblack@eecs.umich.edu    return getArmSystem(tc)->physAddrRange();
25910037SARM gem5 Developers}
26010037SARM gem5 Developers
26110037SARM gem5 DevelopersAddr
26210037SARM gem5 DevelopersArmSystem::physAddrMask(ThreadContext *tc)
26313396Sgiacomo.travaglini@arm.com{
26410037SARM gem5 Developers    return getArmSystem(tc)->physAddrMask();
26510037SARM gem5 Developers}
26610037SARM gem5 Developers
26710037SARM gem5 Developersbool
26810037SARM gem5 DevelopersArmSystem::haveLargeAsid64(ThreadContext *tc)
26910037SARM gem5 Developers{
27010037SARM gem5 Developers    return getArmSystem(tc)->haveLargeAsid64();
27110037SARM gem5 Developers}
27210037SARM gem5 Developers
27310037SARM gem5 Developersbool
27410037SARM gem5 DevelopersArmSystem::haveSemihosting(ThreadContext *tc)
27510037SARM gem5 Developers{
27610037SARM gem5 Developers    return getArmSystem(tc)->haveSemihosting();
27710037SARM gem5 Developers}
27810037SARM gem5 Developers
27910037SARM gem5 Developersuint64_t
28010037SARM gem5 DevelopersArmSystem::callSemihosting64(ThreadContext *tc,
28110037SARM gem5 Developers                             uint32_t op, uint64_t param)
28210037SARM gem5 Developers{
28310037SARM gem5 Developers    ArmSystem *sys = getArmSystem(tc);
28410037SARM gem5 Developers    return sys->semihosting->call64(tc, op, param);
28510037SARM gem5 Developers}
28610037SARM gem5 Developers
28710037SARM gem5 Developersuint32_t
28810037SARM gem5 DevelopersArmSystem::callSemihosting32(ThreadContext *tc,
28910037SARM gem5 Developers                             uint32_t op, uint32_t param)
29010037SARM gem5 Developers{
29110037SARM gem5 Developers    ArmSystem *sys = getArmSystem(tc);
29210037SARM gem5 Developers    return sys->semihosting->call32(tc, op, param);
29310037SARM gem5 Developers}
29410037SARM gem5 Developers
29511770SCurtis.Dunham@arm.comArmSystem *
29610037SARM gem5 DevelopersArmSystemParams::create()
29711574SCurtis.Dunham@arm.com{
29811770SCurtis.Dunham@arm.com    return new ArmSystem(this);
29911770SCurtis.Dunham@arm.com}
30010037SARM gem5 Developers
30111770SCurtis.Dunham@arm.comvoid
30211770SCurtis.Dunham@arm.comGenericArmSystem::initState()
30310037SARM gem5 Developers{
30410037SARM gem5 Developers    // Moved from the constructor to here since it relies on the
30510037SARM gem5 Developers    // address map being resolved in the interconnect
30613114Sgiacomo.travaglini@arm.com
30710037SARM gem5 Developers    // Call the initialisation of the super class
30813114Sgiacomo.travaglini@arm.com    ArmSystem::initState();
30913114Sgiacomo.travaglini@arm.com}
31013114Sgiacomo.travaglini@arm.com
31113114Sgiacomo.travaglini@arm.comGenericArmSystem *
31213114Sgiacomo.travaglini@arm.comGenericArmSystemParams::create()
31313114Sgiacomo.travaglini@arm.com{
31413114Sgiacomo.travaglini@arm.com
31513114Sgiacomo.travaglini@arm.com    return new GenericArmSystem(this);
31613114Sgiacomo.travaglini@arm.com}
31713114Sgiacomo.travaglini@arm.com