system.cc revision 12272:bcc67ee98e6d
113558Snikos.nikoleris@arm.com/*
28839Sandreas.hansson@arm.com * Copyright (c) 2011-2014,2017 ARM Limited
38839Sandreas.hansson@arm.com * All rights reserved
48839Sandreas.hansson@arm.com *
58839Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
68839Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
78839Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
88839Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
98839Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
108839Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
118839Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
128839Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
133101Sstever@eecs.umich.edu *
148579Ssteve.reinhardt@amd.com * Copyright (c) 2003-2006 The Regents of The University of Michigan
153101Sstever@eecs.umich.edu * Copyright (c) 2011 Regents of the University of California
163101Sstever@eecs.umich.edu * All rights reserved.
173101Sstever@eecs.umich.edu *
183101Sstever@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
193101Sstever@eecs.umich.edu * modification, are permitted provided that the following conditions are
203101Sstever@eecs.umich.edu * met: redistributions of source code must retain the above copyright
213101Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
223101Sstever@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
233101Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
243101Sstever@eecs.umich.edu * documentation and/or other materials provided with the distribution;
253101Sstever@eecs.umich.edu * neither the name of the copyright holders nor the names of its
263101Sstever@eecs.umich.edu * contributors may be used to endorse or promote products derived from
273101Sstever@eecs.umich.edu * this software without specific prior written permission.
283101Sstever@eecs.umich.edu *
293101Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
303101Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
313101Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
323101Sstever@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
333101Sstever@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
343101Sstever@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
353101Sstever@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
363101Sstever@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
373101Sstever@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
383101Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
393101Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
403101Sstever@eecs.umich.edu *
413101Sstever@eecs.umich.edu * Authors: Steve Reinhardt
427778Sgblack@eecs.umich.edu *          Lisa Hsu
438839Sandreas.hansson@arm.com *          Nathan Binkert
443101Sstever@eecs.umich.edu *          Ali Saidi
453101Sstever@eecs.umich.edu *          Rick Strong
463101Sstever@eecs.umich.edu */
473101Sstever@eecs.umich.edu
483101Sstever@eecs.umich.edu#include "sim/system.hh"
493101Sstever@eecs.umich.edu
503101Sstever@eecs.umich.edu#include "arch/remote_gdb.hh"
513101Sstever@eecs.umich.edu#include "arch/utility.hh"
523101Sstever@eecs.umich.edu#include "base/loader/object_file.hh"
533101Sstever@eecs.umich.edu#include "base/loader/symtab.hh"
543101Sstever@eecs.umich.edu#include "base/str.hh"
553101Sstever@eecs.umich.edu#include "base/trace.hh"
563101Sstever@eecs.umich.edu#include "config/use_kvm.hh"
573101Sstever@eecs.umich.edu#if USE_KVM
583101Sstever@eecs.umich.edu#include "cpu/kvm/base.hh"
593101Sstever@eecs.umich.edu#include "cpu/kvm/vm.hh"
603101Sstever@eecs.umich.edu#endif
613101Sstever@eecs.umich.edu#include "cpu/base.hh"
6212563Sgabeblack@google.com#include "cpu/thread_context.hh"
6312563Sgabeblack@google.com#include "debug/Loader.hh"
643885Sbinkertn@umich.edu#include "debug/WorkItems.hh"
653885Sbinkertn@umich.edu#include "mem/abstract_mem.hh"
664762Snate@binkert.org#include "mem/physical.hh"
673885Sbinkertn@umich.edu#include "params/System.hh"
683885Sbinkertn@umich.edu#include "sim/byteswap.hh"
697528Ssteve.reinhardt@amd.com#include "sim/debug.hh"
703885Sbinkertn@umich.edu#include "sim/full_system.hh"
714380Sbinkertn@umich.edu
724167Sbinkertn@umich.edu/**
733102Sstever@eecs.umich.edu * To avoid linking errors with LTO, only include the header if we
743101Sstever@eecs.umich.edu * actually have a definition.
754762Snate@binkert.org */
764762Snate@binkert.org#if THE_ISA != NULL_ISA
774762Snate@binkert.org#include "kern/kernel_stats.hh"
784762Snate@binkert.org
794762Snate@binkert.org#endif
804762Snate@binkert.org
814762Snate@binkert.orgusing namespace std;
824762Snate@binkert.orgusing namespace TheISA;
834762Snate@binkert.org
845033Smilesck@eecs.umich.eduvector<System *> System::systemList;
855033Smilesck@eecs.umich.edu
865033Smilesck@eecs.umich.eduint System::numSystemsRunning = 0;
875033Smilesck@eecs.umich.edu
885033Smilesck@eecs.umich.eduSystem::System(Params *p)
895033Smilesck@eecs.umich.edu    : MemObject(p), _systemPort("system_port", this),
905033Smilesck@eecs.umich.edu      _numContexts(0),
915033Smilesck@eecs.umich.edu      multiThread(p->multi_thread),
925033Smilesck@eecs.umich.edu      pagePtr(0),
935033Smilesck@eecs.umich.edu      init_param(p->init_param),
943101Sstever@eecs.umich.edu      physProxy(_systemPort, p->cache_line_size),
953101Sstever@eecs.umich.edu      kernelSymtab(nullptr),
963101Sstever@eecs.umich.edu      kernel(nullptr),
975033Smilesck@eecs.umich.edu      loadAddrMask(p->load_addr_mask),
9810267SGeoffrey.Blake@arm.com      loadAddrOffset(p->load_offset),
998596Ssteve.reinhardt@amd.com#if USE_KVM
1008596Ssteve.reinhardt@amd.com      kvmVM(p->kvm_vm),
1018596Ssteve.reinhardt@amd.com#else
1028596Ssteve.reinhardt@amd.com      kvmVM(nullptr),
1037673Snate@binkert.org#endif
1047673Snate@binkert.org      physmem(name() + ".physmem", p->memories, p->mmap_using_noreserve),
1057673Snate@binkert.org      memoryMode(p->mem_mode),
1067673Snate@binkert.org      _cacheLineSize(p->cache_line_size),
10711988Sandreas.sandberg@arm.com      workItemsBegin(0),
10811988Sandreas.sandberg@arm.com      workItemsEnd(0),
10911988Sandreas.sandberg@arm.com      numWorkIds(p->num_work_ids),
11011988Sandreas.sandberg@arm.com      thermalModel(p->thermal_model),
1113101Sstever@eecs.umich.edu      _params(p),
1123101Sstever@eecs.umich.edu      totalNumInsts(0),
1133101Sstever@eecs.umich.edu      instEventQueue("system instruction-based event queue")
1143101Sstever@eecs.umich.edu{
1153101Sstever@eecs.umich.edu    // add self to global system list
11610380SAndrew.Bardsley@arm.com    systemList.push_back(this);
11710380SAndrew.Bardsley@arm.com
11810380SAndrew.Bardsley@arm.com#if USE_KVM
11910380SAndrew.Bardsley@arm.com    if (kvmVM) {
12010380SAndrew.Bardsley@arm.com        kvmVM->setSystem(this);
12110380SAndrew.Bardsley@arm.com    }
12210458Sandreas.hansson@arm.com#endif
12310458Sandreas.hansson@arm.com
12410458Sandreas.hansson@arm.com    if (FullSystem) {
12510458Sandreas.hansson@arm.com        kernelSymtab = new SymbolTable;
12610458Sandreas.hansson@arm.com        if (!debugSymbolTable)
12710458Sandreas.hansson@arm.com            debugSymbolTable = new SymbolTable;
12810458Sandreas.hansson@arm.com    }
12910458Sandreas.hansson@arm.com
13010458Sandreas.hansson@arm.com    // check if the cache line size is a value known to work
13110458Sandreas.hansson@arm.com    if (!(_cacheLineSize == 16 || _cacheLineSize == 32 ||
13210458Sandreas.hansson@arm.com          _cacheLineSize == 64 || _cacheLineSize == 128))
13310458Sandreas.hansson@arm.com        warn_once("Cache line size is neither 16, 32, 64 nor 128 bytes.\n");
1343101Sstever@eecs.umich.edu
1353101Sstever@eecs.umich.edu    // Get the generic system master IDs
1363101Sstever@eecs.umich.edu    MasterID tmp_id M5_VAR_USED;
1373101Sstever@eecs.umich.edu    tmp_id = getMasterId("writebacks");
1383101Sstever@eecs.umich.edu    assert(tmp_id == Request::wbMasterId);
13910267SGeoffrey.Blake@arm.com    tmp_id = getMasterId("functional");
14010267SGeoffrey.Blake@arm.com    assert(tmp_id == Request::funcMasterId);
14110267SGeoffrey.Blake@arm.com    tmp_id = getMasterId("interrupt");
14210267SGeoffrey.Blake@arm.com    assert(tmp_id == Request::intMasterId);
1433101Sstever@eecs.umich.edu
1443101Sstever@eecs.umich.edu    if (FullSystem) {
1453101Sstever@eecs.umich.edu        if (params()->kernel == "") {
1463101Sstever@eecs.umich.edu            inform("No kernel set for full system simulation. "
1473101Sstever@eecs.umich.edu                   "Assuming you know what you're doing\n");
1483101Sstever@eecs.umich.edu        } else {
1493101Sstever@eecs.umich.edu            // Get the kernel code
1503101Sstever@eecs.umich.edu            kernel = createObjectFile(params()->kernel);
1513101Sstever@eecs.umich.edu            inform("kernel located at: %s", params()->kernel);
1523101Sstever@eecs.umich.edu
1533101Sstever@eecs.umich.edu            if (kernel == NULL)
1543101Sstever@eecs.umich.edu                fatal("Could not load kernel file %s", params()->kernel);
1553101Sstever@eecs.umich.edu
1563101Sstever@eecs.umich.edu            // setup entry points
1573101Sstever@eecs.umich.edu            kernelStart = kernel->textBase();
15813663Sandreas.sandberg@arm.com            kernelEnd = kernel->bssBase() + kernel->bssSize();
1593101Sstever@eecs.umich.edu            kernelEntry = kernel->entryPoint();
16013675Sandreas.sandberg@arm.com
1613101Sstever@eecs.umich.edu            // If load_addr_mask is set to 0x0, then auto-calculate
1623101Sstever@eecs.umich.edu            // the smallest mask to cover all kernel addresses so gem5
1633101Sstever@eecs.umich.edu            // can relocate the kernel to a new offset.
1643101Sstever@eecs.umich.edu            if (loadAddrMask == 0) {
16513675Sandreas.sandberg@arm.com                Addr shift_amt = findMsbSet(kernelEnd - kernelStart) + 1;
1663101Sstever@eecs.umich.edu                loadAddrMask = ((Addr)1 << shift_amt) - 1;
1673101Sstever@eecs.umich.edu            }
1683101Sstever@eecs.umich.edu
1693101Sstever@eecs.umich.edu            // load symbols
1703101Sstever@eecs.umich.edu            if (!kernel->loadGlobalSymbols(kernelSymtab))
17113663Sandreas.sandberg@arm.com                fatal("could not load kernel symbols\n");
1723101Sstever@eecs.umich.edu
1733101Sstever@eecs.umich.edu            if (!kernel->loadLocalSymbols(kernelSymtab))
17413663Sandreas.sandberg@arm.com                fatal("could not load kernel local symbols\n");
1753101Sstever@eecs.umich.edu
1763101Sstever@eecs.umich.edu            if (!kernel->loadGlobalSymbols(debugSymbolTable))
1773101Sstever@eecs.umich.edu                fatal("could not load kernel symbols\n");
1785033Smilesck@eecs.umich.edu
1796656Snate@binkert.org            if (!kernel->loadLocalSymbols(debugSymbolTable))
1805033Smilesck@eecs.umich.edu                fatal("could not load kernel local symbols\n");
1815033Smilesck@eecs.umich.edu
1825033Smilesck@eecs.umich.edu            // Loading only needs to happen once and after memory system is
18313663Sandreas.sandberg@arm.com            // connected so it will happen in initState()
18413663Sandreas.sandberg@arm.com        }
1853101Sstever@eecs.umich.edu
18610267SGeoffrey.Blake@arm.com        for (const auto &obj_name : p->kernel_extras) {
18710267SGeoffrey.Blake@arm.com            inform("Loading additional kernel object: %s", obj_name);
18810267SGeoffrey.Blake@arm.com            ObjectFile *obj = createObjectFile(obj_name);
18910267SGeoffrey.Blake@arm.com            fatal_if(!obj, "Failed to additional kernel object '%s'.\n",
19010267SGeoffrey.Blake@arm.com                     obj_name);
19110267SGeoffrey.Blake@arm.com            kernelExtras.push_back(obj);
19210267SGeoffrey.Blake@arm.com        }
19310267SGeoffrey.Blake@arm.com    }
19410267SGeoffrey.Blake@arm.com
19510267SGeoffrey.Blake@arm.com    // increment the number of running systems
19610267SGeoffrey.Blake@arm.com    numSystemsRunning++;
19710267SGeoffrey.Blake@arm.com
19810267SGeoffrey.Blake@arm.com    // Set back pointers to the system in all memories
1993101Sstever@eecs.umich.edu    for (int x = 0; x < params()->memories.size(); x++)
2003101Sstever@eecs.umich.edu        params()->memories[x]->system(this);
2013101Sstever@eecs.umich.edu}
2023101Sstever@eecs.umich.edu
20313699Sandreas.sandberg@arm.comSystem::~System()
2043101Sstever@eecs.umich.edu{
2053101Sstever@eecs.umich.edu    delete kernelSymtab;
2063101Sstever@eecs.umich.edu    delete kernel;
2073101Sstever@eecs.umich.edu
2083101Sstever@eecs.umich.edu    for (uint32_t j = 0; j < numWorkIds; j++)
2093102Sstever@eecs.umich.edu        delete workItemStats[j];
2103101Sstever@eecs.umich.edu}
2113101Sstever@eecs.umich.edu
2123101Sstever@eecs.umich.eduvoid
21310267SGeoffrey.Blake@arm.comSystem::init()
21410267SGeoffrey.Blake@arm.com{
21510267SGeoffrey.Blake@arm.com    // check that the system port is connected
21610267SGeoffrey.Blake@arm.com    if (!_systemPort.isConnected())
21710267SGeoffrey.Blake@arm.com        panic("System port on %s is not connected.\n", name());
21810267SGeoffrey.Blake@arm.com}
21910267SGeoffrey.Blake@arm.com
2207673Snate@binkert.orgBaseMasterPort&
2218607Sgblack@eecs.umich.eduSystem::getMasterPort(const std::string &if_name, PortID idx)
2227673Snate@binkert.org{
2233101Sstever@eecs.umich.edu    // no need to distinguish at the moment (besides checking)
22411988Sandreas.sandberg@arm.com    return _systemPort;
22511988Sandreas.sandberg@arm.com}
22611988Sandreas.sandberg@arm.com
2277673Snate@binkert.orgvoid
2287673Snate@binkert.orgSystem::setMemoryMode(Enums::MemoryMode mode)
2293101Sstever@eecs.umich.edu{
2303101Sstever@eecs.umich.edu    assert(drainState() == DrainState::Drained);
2313101Sstever@eecs.umich.edu    memoryMode = mode;
2323101Sstever@eecs.umich.edu}
2333101Sstever@eecs.umich.edu
2343101Sstever@eecs.umich.edubool System::breakpoint()
2355033Smilesck@eecs.umich.edu{
2365475Snate@binkert.org    if (remoteGDB.size())
23713663Sandreas.sandberg@arm.com        return remoteGDB[0]->breakpoint();
23813663Sandreas.sandberg@arm.com    return false;
2395475Snate@binkert.org}
24010380SAndrew.Bardsley@arm.com
24110380SAndrew.Bardsley@arm.comContextID
24210380SAndrew.Bardsley@arm.comSystem::registerThreadContext(ThreadContext *tc, ContextID assigned)
2433101Sstever@eecs.umich.edu{
2443101Sstever@eecs.umich.edu    int id;
2453101Sstever@eecs.umich.edu    if (assigned == InvalidContextID) {
2464762Snate@binkert.org        for (id = 0; id < threadContexts.size(); id++) {
2474762Snate@binkert.org            if (!threadContexts[id])
2484762Snate@binkert.org                break;
2493101Sstever@eecs.umich.edu        }
25012050Snikos.nikoleris@arm.com
25112050Snikos.nikoleris@arm.com        if (threadContexts.size() <= id)
25212050Snikos.nikoleris@arm.com            threadContexts.resize(id + 1);
2538459SAli.Saidi@ARM.com    } else {
2548459SAli.Saidi@ARM.com        if (threadContexts.size() <= assigned)
25512050Snikos.nikoleris@arm.com            threadContexts.resize(assigned + 1);
2563101Sstever@eecs.umich.edu        id = assigned;
2577528Ssteve.reinhardt@amd.com    }
2587528Ssteve.reinhardt@amd.com
2597528Ssteve.reinhardt@amd.com    if (threadContexts[id])
2607528Ssteve.reinhardt@amd.com        fatal("Cannot have two CPUs with the same id (%d)\n", id);
2617528Ssteve.reinhardt@amd.com
2627528Ssteve.reinhardt@amd.com    threadContexts[id] = tc;
2633101Sstever@eecs.umich.edu    _numContexts++;
2647528Ssteve.reinhardt@amd.com
2657528Ssteve.reinhardt@amd.com#if THE_ISA != NULL_ISA
2667528Ssteve.reinhardt@amd.com    int port = getRemoteGDBPort();
2677528Ssteve.reinhardt@amd.com    if (port) {
2687528Ssteve.reinhardt@amd.com        RemoteGDB *rgdb = new RemoteGDB(this, tc);
2697528Ssteve.reinhardt@amd.com        GDBListener *gdbl = new GDBListener(rgdb, port + id);
2707528Ssteve.reinhardt@amd.com        gdbl->listen();
2717528Ssteve.reinhardt@amd.com
2727528Ssteve.reinhardt@amd.com        BaseCPU *cpu = tc->getCpuPtr();
2737528Ssteve.reinhardt@amd.com        if (cpu->waitForRemoteGDB()) {
2748321Ssteve.reinhardt@amd.com            inform("%s: Waiting for a remote GDB connection on port %d.\n",
27512194Sgabeblack@google.com                   cpu->name(), gdbl->getPort());
2767528Ssteve.reinhardt@amd.com
2777528Ssteve.reinhardt@amd.com            gdbl->accept();
2787528Ssteve.reinhardt@amd.com        }
2797528Ssteve.reinhardt@amd.com        if (remoteGDB.size() <= id) {
2807528Ssteve.reinhardt@amd.com            remoteGDB.resize(id + 1);
2817528Ssteve.reinhardt@amd.com        }
2827528Ssteve.reinhardt@amd.com
2837528Ssteve.reinhardt@amd.com        remoteGDB[id] = rgdb;
2847528Ssteve.reinhardt@amd.com    }
2857528Ssteve.reinhardt@amd.com#endif
2867528Ssteve.reinhardt@amd.com
2877528Ssteve.reinhardt@amd.com    activeCpus.push_back(false);
2887528Ssteve.reinhardt@amd.com
2893101Sstever@eecs.umich.edu    return id;
2908664SAli.Saidi@ARM.com}
2918664SAli.Saidi@ARM.com
2928664SAli.Saidi@ARM.comint
2938664SAli.Saidi@ARM.comSystem::numRunningContexts()
2948664SAli.Saidi@ARM.com{
2958664SAli.Saidi@ARM.com    int running = 0;
2969953Sgeoffrey.blake@arm.com    for (int i = 0; i < _numContexts; ++i) {
2979953Sgeoffrey.blake@arm.com        if (threadContexts[i]->status() != ThreadContext::Halted)
2989953Sgeoffrey.blake@arm.com            ++running;
2999953Sgeoffrey.blake@arm.com    }
3009953Sgeoffrey.blake@arm.com    return running;
3019953Sgeoffrey.blake@arm.com}
3029953Sgeoffrey.blake@arm.com
3039953Sgeoffrey.blake@arm.comvoid
3049953Sgeoffrey.blake@arm.comSystem::initState()
3059953Sgeoffrey.blake@arm.com{
3069953Sgeoffrey.blake@arm.com    if (FullSystem) {
3079953Sgeoffrey.blake@arm.com        for (int i = 0; i < threadContexts.size(); i++)
3089953Sgeoffrey.blake@arm.com            TheISA::startupCPU(threadContexts[i], i);
30910267SGeoffrey.Blake@arm.com        // Moved from the constructor to here since it relies on the
31010267SGeoffrey.Blake@arm.com        // address map being resolved in the interconnect
31110267SGeoffrey.Blake@arm.com        /**
31210267SGeoffrey.Blake@arm.com         * Load the kernel code into memory
31310267SGeoffrey.Blake@arm.com         */
31410267SGeoffrey.Blake@arm.com        if (params()->kernel != "")  {
31510267SGeoffrey.Blake@arm.com            if (params()->kernel_addr_check) {
31612563Sgabeblack@google.com                // Validate kernel mapping before loading binary
31710267SGeoffrey.Blake@arm.com                if (!(isMemAddr((kernelStart & loadAddrMask) +
31810267SGeoffrey.Blake@arm.com                                loadAddrOffset) &&
31910267SGeoffrey.Blake@arm.com                      isMemAddr((kernelEnd & loadAddrMask) +
32010267SGeoffrey.Blake@arm.com                                loadAddrOffset))) {
32110267SGeoffrey.Blake@arm.com                    fatal("Kernel is mapped to invalid location (not memory). "
32210267SGeoffrey.Blake@arm.com                          "kernelStart 0x(%x) - kernelEnd 0x(%x) %#x:%#x\n",
32310267SGeoffrey.Blake@arm.com                          kernelStart,
32410267SGeoffrey.Blake@arm.com                          kernelEnd, (kernelStart & loadAddrMask) +
32510267SGeoffrey.Blake@arm.com                          loadAddrOffset,
32610267SGeoffrey.Blake@arm.com                          (kernelEnd & loadAddrMask) + loadAddrOffset);
32710267SGeoffrey.Blake@arm.com                }
32810267SGeoffrey.Blake@arm.com            }
3293101Sstever@eecs.umich.edu            // Load program sections into memory
3303101Sstever@eecs.umich.edu            kernel->loadSections(physProxy, loadAddrMask, loadAddrOffset);
3313101Sstever@eecs.umich.edu            for (const auto &extra_kernel : kernelExtras) {
3323101Sstever@eecs.umich.edu                extra_kernel->loadSections(physProxy, loadAddrMask,
3333101Sstever@eecs.umich.edu                                           loadAddrOffset);
3343101Sstever@eecs.umich.edu            }
3353101Sstever@eecs.umich.edu
33610364SGeoffrey.Blake@arm.com            DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
33710364SGeoffrey.Blake@arm.com            DPRINTF(Loader, "Kernel end   = %#x\n", kernelEnd);
33810364SGeoffrey.Blake@arm.com            DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
33910364SGeoffrey.Blake@arm.com            DPRINTF(Loader, "Kernel loaded...\n");
3403101Sstever@eecs.umich.edu        }
3414762Snate@binkert.org    }
3424762Snate@binkert.org}
3434762Snate@binkert.org
3444762Snate@binkert.orgvoid
3457528Ssteve.reinhardt@amd.comSystem::replaceThreadContext(ThreadContext *tc, ContextID context_id)
3464762Snate@binkert.org{
3474762Snate@binkert.org    if (context_id >= threadContexts.size()) {
3484762Snate@binkert.org        panic("replaceThreadContext: bad id, %d >= %d\n",
34910267SGeoffrey.Blake@arm.com              context_id, threadContexts.size());
35010267SGeoffrey.Blake@arm.com    }
35110267SGeoffrey.Blake@arm.com
35210267SGeoffrey.Blake@arm.com    threadContexts[context_id] = tc;
35310267SGeoffrey.Blake@arm.com    if (context_id < remoteGDB.size())
35410267SGeoffrey.Blake@arm.com        remoteGDB[context_id]->replaceThreadContext(tc);
35510267SGeoffrey.Blake@arm.com}
35610267SGeoffrey.Blake@arm.com
35710267SGeoffrey.Blake@arm.combool
35810267SGeoffrey.Blake@arm.comSystem::validKvmEnvironment() const
35910267SGeoffrey.Blake@arm.com{
36010267SGeoffrey.Blake@arm.com#if USE_KVM
36110267SGeoffrey.Blake@arm.com    if (threadContexts.empty())
36210267SGeoffrey.Blake@arm.com        return false;
36310267SGeoffrey.Blake@arm.com
36410267SGeoffrey.Blake@arm.com    for (auto tc : threadContexts) {
36510267SGeoffrey.Blake@arm.com        if (dynamic_cast<BaseKvmCPU*>(tc->getCpuPtr()) == nullptr) {
36610267SGeoffrey.Blake@arm.com            return false;
36710267SGeoffrey.Blake@arm.com        }
36810267SGeoffrey.Blake@arm.com    }
36910267SGeoffrey.Blake@arm.com    return true;
37010267SGeoffrey.Blake@arm.com#else
37110267SGeoffrey.Blake@arm.com    return false;
37210267SGeoffrey.Blake@arm.com#endif
37310267SGeoffrey.Blake@arm.com}
37410267SGeoffrey.Blake@arm.com
37510364SGeoffrey.Blake@arm.comAddr
37610364SGeoffrey.Blake@arm.comSystem::allocPhysPages(int npages)
37710267SGeoffrey.Blake@arm.com{
37810267SGeoffrey.Blake@arm.com    Addr return_addr = pagePtr << PageShift;
37910267SGeoffrey.Blake@arm.com    pagePtr += npages;
38010267SGeoffrey.Blake@arm.com
38110267SGeoffrey.Blake@arm.com    Addr next_return_addr = pagePtr << PageShift;
38210267SGeoffrey.Blake@arm.com
3837673Snate@binkert.org    AddrRange m5opRange(0xffff0000, 0xffffffff);
3847673Snate@binkert.org    if (m5opRange.contains(next_return_addr)) {
3857673Snate@binkert.org        warn("Reached m5ops MMIO region\n");
3863101Sstever@eecs.umich.edu        return_addr = 0xffffffff;
38711988Sandreas.sandberg@arm.com        pagePtr = 0xffffffff >> PageShift;
38811988Sandreas.sandberg@arm.com    }
38911988Sandreas.sandberg@arm.com
39011988Sandreas.sandberg@arm.com    if ((pagePtr << PageShift) > physmem.totalSize())
3917673Snate@binkert.org        fatal("Out of memory, please increase size of physical memory.");
3927673Snate@binkert.org    return return_addr;
3933101Sstever@eecs.umich.edu}
3943101Sstever@eecs.umich.edu
3953101Sstever@eecs.umich.eduAddr
3963101Sstever@eecs.umich.eduSystem::memSize() const
3973101Sstever@eecs.umich.edu{
3983101Sstever@eecs.umich.edu    return physmem.totalSize();
3993101Sstever@eecs.umich.edu}
4003101Sstever@eecs.umich.edu
4013101Sstever@eecs.umich.eduAddr
4023101Sstever@eecs.umich.eduSystem::freeMemSize() const
4033101Sstever@eecs.umich.edu{
4043101Sstever@eecs.umich.edu   return physmem.totalSize() - (pagePtr << PageShift);
4053101Sstever@eecs.umich.edu}
4063101Sstever@eecs.umich.edu
4073101Sstever@eecs.umich.edubool
4085033Smilesck@eecs.umich.eduSystem::isMemAddr(Addr addr) const
4095033Smilesck@eecs.umich.edu{
4103101Sstever@eecs.umich.edu    return physmem.isMemAddr(addr);
4113101Sstever@eecs.umich.edu}
4123101Sstever@eecs.umich.edu
4133101Sstever@eecs.umich.eduvoid
4143101Sstever@eecs.umich.eduSystem::drainResume()
4153101Sstever@eecs.umich.edu{
4163101Sstever@eecs.umich.edu    totalNumInsts = 0;
4173101Sstever@eecs.umich.edu}
4183101Sstever@eecs.umich.edu
4193101Sstever@eecs.umich.eduvoid
4203101Sstever@eecs.umich.eduSystem::serialize(CheckpointOut &cp) const
4213101Sstever@eecs.umich.edu{
4223101Sstever@eecs.umich.edu    if (FullSystem)
4233101Sstever@eecs.umich.edu        kernelSymtab->serialize("kernel_symtab", cp);
4243101Sstever@eecs.umich.edu    SERIALIZE_SCALAR(pagePtr);
4253101Sstever@eecs.umich.edu    serializeSymtab(cp);
4263101Sstever@eecs.umich.edu
4273101Sstever@eecs.umich.edu    // also serialize the memories in the system
4283101Sstever@eecs.umich.edu    physmem.serializeSection(cp, "physmem");
4293101Sstever@eecs.umich.edu}
4303101Sstever@eecs.umich.edu
4313101Sstever@eecs.umich.edu
4323101Sstever@eecs.umich.eduvoid
4333101Sstever@eecs.umich.eduSystem::unserialize(CheckpointIn &cp)
4343101Sstever@eecs.umich.edu{
43510267SGeoffrey.Blake@arm.com    if (FullSystem)
4367673Snate@binkert.org        kernelSymtab->unserialize("kernel_symtab", cp);
4377673Snate@binkert.org    UNSERIALIZE_SCALAR(pagePtr);
4387673Snate@binkert.org    unserializeSymtab(cp);
4397673Snate@binkert.org
4407673Snate@binkert.org    // also unserialize the memories in the system
44110267SGeoffrey.Blake@arm.com    physmem.unserializeSection(cp, "physmem");
44210267SGeoffrey.Blake@arm.com}
44310267SGeoffrey.Blake@arm.com
44410267SGeoffrey.Blake@arm.comvoid
44510458Sandreas.hansson@arm.comSystem::regStats()
44610458Sandreas.hansson@arm.com{
44710458Sandreas.hansson@arm.com    MemObject::regStats();
44810458Sandreas.hansson@arm.com
44910458Sandreas.hansson@arm.com    for (uint32_t j = 0; j < numWorkIds ; j++) {
4504762Snate@binkert.org        workItemStats[j] = new Stats::Histogram();
4514762Snate@binkert.org        stringstream namestr;
4523101Sstever@eecs.umich.edu        ccprintf(namestr, "work_item_type%d", j);
4533101Sstever@eecs.umich.edu        workItemStats[j]->init(20)
4543101Sstever@eecs.umich.edu                         .name(name() + "." + namestr.str())
4553101Sstever@eecs.umich.edu                         .desc("Run time stat for" + namestr.str())
4563101Sstever@eecs.umich.edu                         .prereq(*workItemStats[j]);
4573101Sstever@eecs.umich.edu    }
4583101Sstever@eecs.umich.edu}
4593101Sstever@eecs.umich.edu
4603101Sstever@eecs.umich.eduvoid
4613101Sstever@eecs.umich.eduSystem::workItemEnd(uint32_t tid, uint32_t workid)
4623101Sstever@eecs.umich.edu{
4633714Sstever@eecs.umich.edu    std::pair<uint32_t,uint32_t> p(tid, workid);
4643714Sstever@eecs.umich.edu    if (!lastWorkItemStarted.count(p))
4653714Sstever@eecs.umich.edu        return;
4663714Sstever@eecs.umich.edu
4673714Sstever@eecs.umich.edu    Tick samp = curTick() - lastWorkItemStarted[p];
4683714Sstever@eecs.umich.edu    DPRINTF(WorkItems, "Work item end: %d\t%d\t%lld\n", tid, workid, samp);
4693101Sstever@eecs.umich.edu
4703101Sstever@eecs.umich.edu    if (workid >= numWorkIds)
4713101Sstever@eecs.umich.edu        fatal("Got workid greater than specified in system configuration\n");
4723101Sstever@eecs.umich.edu
4733101Sstever@eecs.umich.edu    workItemStats[workid]->sample(samp);
4743101Sstever@eecs.umich.edu    lastWorkItemStarted.erase(p);
4753101Sstever@eecs.umich.edu}
4763101Sstever@eecs.umich.edu
4773101Sstever@eecs.umich.eduvoid
4783101Sstever@eecs.umich.eduSystem::printSystems()
4793101Sstever@eecs.umich.edu{
4803101Sstever@eecs.umich.edu    ios::fmtflags flags(cerr.flags());
4813101Sstever@eecs.umich.edu
4823101Sstever@eecs.umich.edu    vector<System *>::iterator i = systemList.begin();
4833101Sstever@eecs.umich.edu    vector<System *>::iterator end = systemList.end();
4843101Sstever@eecs.umich.edu    for (; i != end; ++i) {
4853101Sstever@eecs.umich.edu        System *sys = *i;
4863101Sstever@eecs.umich.edu        cerr << "System " << sys->name() << ": " << hex << sys << endl;
4873101Sstever@eecs.umich.edu    }
4883101Sstever@eecs.umich.edu
4893101Sstever@eecs.umich.edu    cerr.flags(flags);
4903101Sstever@eecs.umich.edu}
4913101Sstever@eecs.umich.edu
4923101Sstever@eecs.umich.eduvoid
49310380SAndrew.Bardsley@arm.comprintSystems()
49410380SAndrew.Bardsley@arm.com{
49510380SAndrew.Bardsley@arm.com    System::printSystems();
49610458Sandreas.hansson@arm.com}
49710458Sandreas.hansson@arm.com
49810458Sandreas.hansson@arm.comMasterID
49910458Sandreas.hansson@arm.comSystem::getMasterId(std::string master_name)
50010458Sandreas.hansson@arm.com{
50110458Sandreas.hansson@arm.com    // strip off system name if the string starts with it
50210458Sandreas.hansson@arm.com    if (startswith(master_name, name()))
50310458Sandreas.hansson@arm.com        master_name = master_name.erase(0, name().size() + 1);
50410458Sandreas.hansson@arm.com
50510458Sandreas.hansson@arm.com    // CPUs in switch_cpus ask for ids again after switching
50610458Sandreas.hansson@arm.com    for (int i = 0; i < masterIds.size(); i++) {
50710458Sandreas.hansson@arm.com        if (masterIds[i] == master_name) {
50810458Sandreas.hansson@arm.com            return i;
5093101Sstever@eecs.umich.edu        }
5105033Smilesck@eecs.umich.edu    }
5113101Sstever@eecs.umich.edu
5123101Sstever@eecs.umich.edu    // Verify that the statistics haven't been enabled yet
5133101Sstever@eecs.umich.edu    // Otherwise objects will have sized their stat buckets and
5143101Sstever@eecs.umich.edu    // they will be too small
5153101Sstever@eecs.umich.edu
5163101Sstever@eecs.umich.edu    if (Stats::enabled()) {
5173101Sstever@eecs.umich.edu        fatal("Can't request a masterId after regStats(). "
5183101Sstever@eecs.umich.edu                "You must do so in init().\n");
5193101Sstever@eecs.umich.edu    }
5203101Sstever@eecs.umich.edu
5213101Sstever@eecs.umich.edu    masterIds.push_back(master_name);
5223101Sstever@eecs.umich.edu
5235822Ssaidi@eecs.umich.edu    return masterIds.size() - 1;
5245822Ssaidi@eecs.umich.edu}
5253101Sstever@eecs.umich.edu
5263101Sstever@eecs.umich.edustd::string
5273101Sstever@eecs.umich.eduSystem::getMasterName(MasterID master_id)
5283101Sstever@eecs.umich.edu{
5293101Sstever@eecs.umich.edu    if (master_id >= masterIds.size())
5303101Sstever@eecs.umich.edu        fatal("Invalid master_id passed to getMasterName()\n");
5313101Sstever@eecs.umich.edu
5323101Sstever@eecs.umich.edu    return masterIds[master_id];
5333101Sstever@eecs.umich.edu}
5343101Sstever@eecs.umich.edu
5353101Sstever@eecs.umich.eduSystem *
5363101Sstever@eecs.umich.eduSystemParams::create()
5373101Sstever@eecs.umich.edu{
53810267SGeoffrey.Blake@arm.com    return new System(this);
5393101Sstever@eecs.umich.edu}
5403101Sstever@eecs.umich.edu