system.cc revision 8703:f2ac0bca75df
110206Sandreas.hansson@arm.com/*
29243SN/A * Copyright (c) 2011-2012 ARM Limited
39243SN/A * All rights reserved
49243SN/A *
59243SN/A * The license below extends only to copyright in the software and shall
69243SN/A * not be construed as granting a license to any other intellectual
79243SN/A * property including but not limited to intellectual property relating
89243SN/A * to a hardware implementation of the functionality of the software
99243SN/A * licensed hereunder.  You may use the software subject to the license
109243SN/A * terms below provided that you ensure that this notice is replicated
119243SN/A * unmodified and in its entirety in all distributions of the software,
129243SN/A * modified or unmodified, in source code or in binary form.
139831SN/A *
149831SN/A * Copyright (c) 2003-2006 The Regents of The University of Michigan
159831SN/A * Copyright (c) 2011 Regents of the University of California
169243SN/A * All rights reserved.
179243SN/A *
189243SN/A * Redistribution and use in source and binary forms, with or without
199243SN/A * modification, are permitted provided that the following conditions are
209243SN/A * met: redistributions of source code must retain the above copyright
219243SN/A * notice, this list of conditions and the following disclaimer;
229243SN/A * redistributions in binary form must reproduce the above copyright
239243SN/A * notice, this list of conditions and the following disclaimer in the
249243SN/A * documentation and/or other materials provided with the distribution;
259243SN/A * neither the name of the copyright holders nor the names of its
269243SN/A * contributors may be used to endorse or promote products derived from
279243SN/A * this software without specific prior written permission.
289243SN/A *
299243SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
309243SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
319243SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
329243SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
339243SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
349243SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
359243SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
369243SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
379243SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
389243SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
399243SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
409243SN/A *
419243SN/A * Authors: Steve Reinhardt
429243SN/A *          Lisa Hsu
439243SN/A *          Nathan Binkert
449243SN/A *          Ali Saidi
459243SN/A *          Rick Strong
469243SN/A */
479243SN/A
489243SN/A#include "arch/isa_traits.hh"
4910136SN/A#include "arch/remote_gdb.hh"
5010136SN/A#include "arch/utility.hh"
5110136SN/A#include "base/loader/object_file.hh"
5210136SN/A#include "base/loader/symtab.hh"
5310136SN/A#include "base/trace.hh"
5410136SN/A#include "config/full_system.hh"
5510136SN/A#include "config/the_isa.hh"
569243SN/A#include "cpu/thread_context.hh"
5710144SN/A#include "debug/Loader.hh"
5810144SN/A#include "debug/WorkItems.hh"
5910144SN/A#include "mem/mem_object.hh"
6010144SN/A#include "mem/physical.hh"
619243SN/A#include "sim/byteswap.hh"
6210146Sandreas.hansson@arm.com#include "sim/debug.hh"
639243SN/A#include "sim/system.hh"
649243SN/A
659243SN/A#if FULL_SYSTEM
6610146Sandreas.hansson@arm.com#include "arch/vtophys.hh"
6710146Sandreas.hansson@arm.com#include "kern/kernel_stats.hh"
6810146Sandreas.hansson@arm.com#include "mem/vport.hh"
699243SN/A#else
709243SN/A#include "params/System.hh"
719243SN/A#endif
729243SN/A
739243SN/Ausing namespace std;
749243SN/Ausing namespace TheISA;
7510145SN/A
769972SN/Avector<System *> System::systemList;
779243SN/A
7810140SN/Aint System::numSystemsRunning = 0;
7910140SN/A
8010140SN/ASystem::System(Params *p)
819972SN/A    : MemObject(p), _systemPort("system_port", this),
8210140SN/A      physmem(p->physmem),
8310140SN/A      _numContexts(0),
8410140SN/A#if FULL_SYSTEM
8510140SN/A      init_param(p->init_param),
8610140SN/A      loadAddrMask(p->load_addr_mask),
8710140SN/A#else
8810140SN/A      pagePtr(0),
899243SN/A      nextPID(0),
909243SN/A#endif
919489SN/A      memoryMode(p->mem_mode),
9210136SN/A      workItemsBegin(0),
9310145SN/A      workItemsEnd(0),
949243SN/A      numWorkIds(p->num_work_ids),
9510141SN/A      _params(p),
9610141SN/A      totalNumInsts(0),
9710141SN/A      instEventQueue("system instruction-based event queue")
9810141SN/A{
999726SN/A    // add self to global system list
1009726SN/A    systemList.push_back(this);
1019726SN/A
1029726SN/A    /** Keep track of all memories we can execute code out of
1039726SN/A     * in our system
1049726SN/A     */
1059726SN/A    for (int x = 0; x < p->memories.size(); x++) {
1069489SN/A        if (!p->memories[x])
1079831SN/A            continue;
1089831SN/A        memRanges.push_back(RangeSize(p->memories[x]->start(),
1099831SN/A                                      p->memories[x]->size()));
1109831SN/A    }
1119831SN/A
1129831SN/A#if FULL_SYSTEM
1139489SN/A    kernelSymtab = new SymbolTable;
1149489SN/A    if (!debugSymbolTable)
1159566SN/A        debugSymbolTable = new SymbolTable;
1169566SN/A
1179566SN/A
1189566SN/A    /**
1199489SN/A     * Get a functional port to memory
1209243SN/A     */
1219243SN/A    Port *mem_port;
1229243SN/A    functionalPort = new FunctionalPort(name() + "-fport");
1239243SN/A    mem_port = physmem->getPort("functional");
1249489SN/A    functionalPort->setPeer(mem_port);
1259243SN/A    mem_port->setPeer(functionalPort);
1269243SN/A
1279489SN/A    virtPort = new VirtualPort(name() + "-fport");
1289243SN/A    mem_port = physmem->getPort("functional");
1299243SN/A    virtPort->setPeer(mem_port);
1309489SN/A    mem_port->setPeer(virtPort);
1319243SN/A
1329963SN/A
1339963SN/A    /**
1349963SN/A     * Load the kernel code into memory
13510210Sandreas.hansson@arm.com     */
13610210Sandreas.hansson@arm.com    if (params()->kernel == "") {
13710210Sandreas.hansson@arm.com        inform("No kernel set for full system simulation. Assuming you know what"
13810212Sandreas.hansson@arm.com                " you're doing...\n");
13910212Sandreas.hansson@arm.com    } else {
14010212Sandreas.hansson@arm.com        // Load kernel code
1419243SN/A        kernel = createObjectFile(params()->kernel);
1429243SN/A        inform("kernel located at: %s", params()->kernel);
1439243SN/A
1449831SN/A        if (kernel == NULL)
1459831SN/A            fatal("Could not load kernel file %s", params()->kernel);
14610146Sandreas.hansson@arm.com
1479489SN/A        // Load program sections into memory
1489243SN/A        kernel->loadSections(functionalPort, loadAddrMask);
1499243SN/A
1509489SN/A        // setup entry points
1519243SN/A        kernelStart = kernel->textBase();
1529243SN/A        kernelEnd = kernel->bssBase() + kernel->bssSize();
1539243SN/A        kernelEntry = kernel->entryPoint();
1549489SN/A
1559243SN/A        // load symbols
15610206Sandreas.hansson@arm.com        if (!kernel->loadGlobalSymbols(kernelSymtab))
1579489SN/A            fatal("could not load kernel symbols\n");
1589243SN/A
15910206Sandreas.hansson@arm.com        if (!kernel->loadLocalSymbols(kernelSymtab))
16010206Sandreas.hansson@arm.com            fatal("could not load kernel local symbols\n");
16110206Sandreas.hansson@arm.com
1629971SN/A        if (!kernel->loadGlobalSymbols(debugSymbolTable))
1639971SN/A            fatal("could not load kernel symbols\n");
1649971SN/A
1659488SN/A        if (!kernel->loadLocalSymbols(debugSymbolTable))
1669488SN/A            fatal("could not load kernel local symbols\n");
1679489SN/A
1689489SN/A        DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
1699488SN/A        DPRINTF(Loader, "Kernel end   = %#x\n", kernelEnd);
1709488SN/A        DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
1719243SN/A        DPRINTF(Loader, "Kernel loaded...\n");
1729243SN/A    }
1739963SN/A#endif // FULL_SYSTEM
1749243SN/A
1759728SN/A    // increment the number of running systms
1769728SN/A    numSystemsRunning++;
1779728SN/A
17810146Sandreas.hansson@arm.com    activeCpus.clear();
1799831SN/A}
1809831SN/A
1819831SN/ASystem::~System()
1829831SN/A{
1839831SN/A#if FULL_SYSTEM
1849831SN/A    delete kernelSymtab;
1859831SN/A    delete kernel;
1869728SN/A#else
1879831SN/A    panic("System::fixFuncEventAddr needs to be rewritten "
1889831SN/A          "to work with syscall emulation");
1899831SN/A#endif // FULL_SYSTEM}
1909831SN/A
1919489SN/A    for (uint32_t j = 0; j < numWorkIds; j++)
1929489SN/A        delete workItemStats[j];
1939489SN/A}
1949489SN/A
1959489SN/APort*
1969489SN/ASystem::getPort(const std::string &if_name, int idx)
1979489SN/A{
1989970SN/A    // no need to distinguish at the moment (besides checking)
1999489SN/A    return &_systemPort;
2009489SN/A}
2019489SN/A
2029970SN/Avoid
20310210Sandreas.hansson@arm.comSystem::setMemoryMode(Enums::MemoryMode mode)
20410212Sandreas.hansson@arm.com{
2059489SN/A    assert(getState() == Drained);
2069831SN/A    memoryMode = mode;
2079831SN/A}
2089489SN/A
2099489SN/Abool System::breakpoint()
2109728SN/A{
2119489SN/A    if (remoteGDB.size())
2129489SN/A        return remoteGDB[0]->breakpoint();
2139489SN/A    return false;
2149489SN/A}
2159489SN/A
2169489SN/A/**
2179489SN/A * Setting rgdb_wait to a positive integer waits for a remote debugger to
2189489SN/A * connect to that context ID before continuing.  This should really
21910206Sandreas.hansson@arm.com   be a parameter on the CPU object or something...
22010206Sandreas.hansson@arm.com */
22110206Sandreas.hansson@arm.comint rgdb_wait = -1;
2229971SN/A
2239971SN/Aint
2249971SN/ASystem::registerThreadContext(ThreadContext *tc, int assigned)
2259489SN/A{
2269489SN/A    int id;
2279489SN/A    if (assigned == -1) {
2289489SN/A        for (id = 0; id < threadContexts.size(); id++) {
2299489SN/A            if (!threadContexts[id])
23010137SN/A                break;
23110137SN/A        }
23210137SN/A
23310137SN/A        if (threadContexts.size() <= id)
23410137SN/A            threadContexts.resize(id + 1);
23510137SN/A    } else {
23610137SN/A        if (threadContexts.size() <= assigned)
23710137SN/A            threadContexts.resize(assigned + 1);
23810137SN/A        id = assigned;
23910146Sandreas.hansson@arm.com    }
24010137SN/A
24110137SN/A    if (threadContexts[id])
24210137SN/A        fatal("Cannot have two CPUs with the same id (%d)\n", id);
24310137SN/A
24410137SN/A    threadContexts[id] = tc;
24510137SN/A    _numContexts++;
24610137SN/A
24710137SN/A    int port = getRemoteGDBPort();
24810137SN/A    if (port) {
24910137SN/A        RemoteGDB *rgdb = new RemoteGDB(this, tc);
25010137SN/A        GDBListener *gdbl = new GDBListener(rgdb, port + id);
25110137SN/A        gdbl->listen();
25210137SN/A
25310137SN/A        if (rgdb_wait != -1 && rgdb_wait == id)
25410137SN/A            gdbl->accept();
25510137SN/A
25610137SN/A        if (remoteGDB.size() <= id) {
25710137SN/A            remoteGDB.resize(id + 1);
25810137SN/A        }
25910137SN/A
26010137SN/A        remoteGDB[id] = rgdb;
26110137SN/A    }
26210137SN/A
26310210Sandreas.hansson@arm.com    activeCpus.push_back(false);
26410212Sandreas.hansson@arm.com
26510137SN/A    return id;
26610137SN/A}
26710137SN/A
26810137SN/Aint
26910137SN/ASystem::numRunningContexts()
27010137SN/A{
27110137SN/A    int running = 0;
27210137SN/A    for (int i = 0; i < _numContexts; ++i) {
27310137SN/A        if (threadContexts[i]->status() != ThreadContext::Halted)
27410137SN/A            ++running;
27510137SN/A    }
27610137SN/A    return running;
27710137SN/A}
27810206Sandreas.hansson@arm.com
27910206Sandreas.hansson@arm.comvoid
28010206Sandreas.hansson@arm.comSystem::initState()
28110137SN/A{
28210137SN/A#if FULL_SYSTEM
28310137SN/A    int i;
28410137SN/A    for (i = 0; i < threadContexts.size(); i++)
28510137SN/A        TheISA::startupCPU(threadContexts[i], i);
28610137SN/A#endif
2879728SN/A}
2889728SN/A
2899728SN/Avoid
29010146Sandreas.hansson@arm.comSystem::replaceThreadContext(ThreadContext *tc, int context_id)
2919831SN/A{
2929831SN/A    if (context_id >= threadContexts.size()) {
2939831SN/A        panic("replaceThreadContext: bad id, %d >= %d\n",
2949831SN/A              context_id, threadContexts.size());
2959831SN/A    }
2969831SN/A
2979831SN/A    threadContexts[context_id] = tc;
2989831SN/A    if (context_id < remoteGDB.size())
2999831SN/A        remoteGDB[context_id]->replaceThreadContext(tc);
3009831SN/A}
3019831SN/A
3029831SN/A#if !FULL_SYSTEM
3039489SN/AAddr
3049708SN/ASystem::allocPhysPages(int npages)
3059708SN/A{
3069489SN/A    Addr return_addr = pagePtr << LogVMPageSize;
3079489SN/A    pagePtr += npages;
3089489SN/A    if (return_addr >= physmem->size())
3099489SN/A        fatal("Out of memory, please increase size of physical memory.");
3109489SN/A    return return_addr;
3119489SN/A}
3129489SN/A
3139489SN/AAddr
3149489SN/ASystem::memSize()
3159489SN/A{
3169728SN/A    return physmem->size();
3179728SN/A}
3189489SN/A
3199970SN/AAddr
32010210Sandreas.hansson@arm.comSystem::freeMemSize()
3219963SN/A{
32210212Sandreas.hansson@arm.com   return physmem->size() - (pagePtr << LogVMPageSize);
32310212Sandreas.hansson@arm.com}
32410212Sandreas.hansson@arm.com
3259831SN/A#endif
3269831SN/A
3279831SN/Abool
32810146Sandreas.hansson@arm.comSystem::isMemory(const Addr addr) const
3299831SN/A{
3309489SN/A    std::list<Range<Addr> >::const_iterator i;
3319708SN/A    for (i = memRanges.begin(); i != memRanges.end(); i++) {
3329489SN/A        if (*i == addr)
3339489SN/A            return true;
3349489SN/A    }
3359489SN/A    return false;
3369489SN/A}
3379489SN/A
33810206Sandreas.hansson@arm.comvoid
33910206Sandreas.hansson@arm.comSystem::resume()
34010206Sandreas.hansson@arm.com{
3419971SN/A    SimObject::resume();
3429971SN/A    totalNumInsts = 0;
3439971SN/A}
3449708SN/A
3459489SN/Avoid
3469489SN/ASystem::serialize(ostream &os)
3479664SN/A{
3489728SN/A#if FULL_SYSTEM
3499728SN/A    kernelSymtab->serialize("kernel_symtab", os);
35010146Sandreas.hansson@arm.com#else // !FULL_SYSTEM
3519831SN/A    SERIALIZE_SCALAR(pagePtr);
3529831SN/A    SERIALIZE_SCALAR(nextPID);
3539831SN/A#endif
3549831SN/A}
3559831SN/A
3569831SN/A
3579831SN/Avoid
3589831SN/ASystem::unserialize(Checkpoint *cp, const string &section)
3599831SN/A{
3609831SN/A#if FULL_SYSTEM
3619831SN/A    kernelSymtab->unserialize("kernel_symtab", cp, section);
3629831SN/A#else // !FULL_SYSTEM
3639664SN/A    UNSERIALIZE_SCALAR(pagePtr);
3649664SN/A    UNSERIALIZE_SCALAR(nextPID);
3659664SN/A#endif
3669664SN/A}
3679664SN/A
3689664SN/Avoid
3699664SN/ASystem::regStats()
3709664SN/A{
3719664SN/A    for (uint32_t j = 0; j < numWorkIds ; j++) {
3729664SN/A        workItemStats[j] = new Stats::Histogram();
3739664SN/A        stringstream namestr;
3749970SN/A        ccprintf(namestr, "work_item_type%d", j);
37510210Sandreas.hansson@arm.com        workItemStats[j]->init(20)
37610212Sandreas.hansson@arm.com                         .name(name() + "." + namestr.str())
37710212Sandreas.hansson@arm.com                         .desc("Run time stat for" + namestr.str())
3789664SN/A                         .prereq(*workItemStats[j]);
3799831SN/A    }
3809831SN/A}
3819664SN/A
3829664SN/Avoid
3839664SN/ASystem::workItemEnd(uint32_t tid, uint32_t workid)
3849664SN/A{
3859664SN/A    std::pair<uint32_t,uint32_t> p(tid, workid);
3869664SN/A    if (!lastWorkItemStarted.count(p))
3879664SN/A        return;
3889664SN/A
3899664SN/A    Tick samp = curTick() - lastWorkItemStarted[p];
3909664SN/A    DPRINTF(WorkItems, "Work item end: %d\t%d\t%lld\n", tid, workid, samp);
3919664SN/A
39210206Sandreas.hansson@arm.com    if (workid >= numWorkIds)
39310206Sandreas.hansson@arm.com        fatal("Got workid greater than specified in system configuration\n");
39410206Sandreas.hansson@arm.com
3959971SN/A    workItemStats[workid]->sample(samp);
3969971SN/A    lastWorkItemStarted.erase(p);
3979971SN/A}
3989664SN/A
3999664SN/Avoid
4009664SN/ASystem::printSystems()
4019709SN/A{
4029728SN/A    vector<System *>::iterator i = systemList.begin();
4039728SN/A    vector<System *>::iterator end = systemList.end();
4049728SN/A    for (; i != end; ++i) {
40510146Sandreas.hansson@arm.com        System *sys = *i;
4069831SN/A        cerr << "System " << sys->name() << ": " << hex << sys << endl;
4079831SN/A    }
4089831SN/A}
4099831SN/A
4109831SN/Avoid
4119831SN/AprintSystems()
4129976SN/A{
4139976SN/A    System::printSystems();
4149831SN/A}
4159831SN/A
4169831SN/Aconst char *System::MemoryModeStrings[3] = {"invalid", "atomic",
4179709SN/A    "timing"};
4189709SN/A
4199709SN/A#if !FULL_SYSTEM
4209709SN/A
4219709SN/ASystem *
4229709SN/ASystemParams::create()
4239709SN/A{
4249709SN/A    return new System(this);
4259709SN/A}
4269709SN/A
4279709SN/A#endif
4289709SN/A