system.cc revision 8795:0909f8ed7aa0
12SN/A/*
213610Sgiacomo.gabrielli@arm.com * Copyright (c) 2003-2006 The Regents of The University of Michigan
39920Syasuko.eckert@amd.com * Copyright (c) 2011 Regents of the University of California
48733Sgeoffrey.blake@arm.com * All rights reserved.
58733Sgeoffrey.blake@arm.com *
68733Sgeoffrey.blake@arm.com * Redistribution and use in source and binary forms, with or without
78733Sgeoffrey.blake@arm.com * modification, are permitted provided that the following conditions are
88733Sgeoffrey.blake@arm.com * met: redistributions of source code must retain the above copyright
98733Sgeoffrey.blake@arm.com * notice, this list of conditions and the following disclaimer;
108733Sgeoffrey.blake@arm.com * redistributions in binary form must reproduce the above copyright
118733Sgeoffrey.blake@arm.com * notice, this list of conditions and the following disclaimer in the
128733Sgeoffrey.blake@arm.com * documentation and/or other materials provided with the distribution;
138733Sgeoffrey.blake@arm.com * neither the name of the copyright holders nor the names of its
148733Sgeoffrey.blake@arm.com * contributors may be used to endorse or promote products derived from
152190SN/A * this software without specific prior written permission.
162SN/A *
172SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
182SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
192SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
202SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
212SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
222SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
232SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
242SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
252SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
262SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
272SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282SN/A *
292SN/A * Authors: Steve Reinhardt
302SN/A *          Lisa Hsu
312SN/A *          Nathan Binkert
322SN/A *          Ali Saidi
332SN/A *          Rick Strong
342SN/A */
352SN/A
362SN/A#include "arch/isa_traits.hh"
372SN/A#include "arch/remote_gdb.hh"
382SN/A#include "arch/utility.hh"
392SN/A#include "arch/vtophys.hh"
402665SN/A#include "base/loader/object_file.hh"
412665SN/A#include "base/loader/symtab.hh"
422SN/A#include "base/trace.hh"
432SN/A#include "config/the_isa.hh"
442680Sktlim@umich.edu#include "cpu/thread_context.hh"
452680Sktlim@umich.edu#include "debug/Loader.hh"
462SN/A#include "kern/kernel_stats.hh"
478229Snate@binkert.org#include "mem/mem_object.hh"
487680Sgblack@eecs.umich.edu#include "mem/physical.hh"
497680Sgblack@eecs.umich.edu#include "mem/vport.hh"
506329Sgblack@eecs.umich.edu#include "params/System.hh"
513453Sgblack@eecs.umich.edu#include "sim/byteswap.hh"
526216Snate@binkert.org#include "sim/debug.hh"
536658Snate@binkert.org#include "sim/full_system.hh"
5412104Snathanael.premillieu@arm.com#include "sim/system.hh"
552SN/A
562190SN/Ausing namespace std;
572190SN/Ausing namespace TheISA;
583453Sgblack@eecs.umich.edu
593453Sgblack@eecs.umich.eduvector<System *> System::systemList;
6013693Sgiacomo.gabrielli@arm.com
619020Sgblack@eecs.umich.eduint System::numSystemsRunning = 0;
623453Sgblack@eecs.umich.edu
632190SN/ASystem::System(Params *p)
6412406Sgabeblack@google.com    : SimObject(p), physmem(p->physmem), _numContexts(0), pagePtr(0),
658887Sgeoffrey.blake@arm.com      init_param(p->init_param),
667680Sgblack@eecs.umich.edu      loadAddrMask(p->load_addr_mask),
672313SN/A      nextPID(0),
688706Sandreas.hansson@arm.com      memoryMode(p->mem_mode),
692190SN/A      workItemsBegin(0),
702190SN/A      workItemsEnd(0),
7113905Sgabeblack@google.com      _params(p),
7213905Sgabeblack@google.com      totalNumInsts(0),
738902Sandreas.hansson@arm.com      instEventQueue("system instruction-based event queue")
742SN/A{
752680Sktlim@umich.edu    // add self to global system list
762680Sktlim@umich.edu    systemList.push_back(this);
772680Sktlim@umich.edu
782680Sktlim@umich.edu    /** Keep track of all memories we can execute code out of
792680Sktlim@umich.edu     * in our system
8013865Sgabeblack@google.com     */
8113865Sgabeblack@google.com    for (int x = 0; x < p->memories.size(); x++) {
822680Sktlim@umich.edu        if (!p->memories[x])
832680Sktlim@umich.edu            continue;
842680Sktlim@umich.edu        memRanges.push_back(RangeSize(p->memories[x]->start(),
852680Sktlim@umich.edu                                      p->memories[x]->size()));
862682Sktlim@umich.edu    }
872680Sktlim@umich.edu
882680Sktlim@umich.edu    if (FullSystem) {
892680Sktlim@umich.edu        kernelSymtab = new SymbolTable;
902680Sktlim@umich.edu        if (!debugSymbolTable)
912680Sktlim@umich.edu            debugSymbolTable = new SymbolTable;
922SN/A
932107SN/A
942107SN/A        /**
9512109SRekai.GonzalezAlberquilla@arm.com         * Get a functional port to memory
9612109SRekai.GonzalezAlberquilla@arm.com         */
9713610Sgiacomo.gabrielli@arm.com        Port *mem_port;
9813610Sgiacomo.gabrielli@arm.com        functionalPort = new FunctionalPort(name() + "-fport");
992SN/A        mem_port = physmem->getPort("functional");
1006029Ssteve.reinhardt@amd.com        functionalPort->setPeer(mem_port);
101246SN/A        mem_port->setPeer(functionalPort);
102246SN/A
103246SN/A        virtPort = new VirtualPort(name() + "-fport");
104246SN/A        mem_port = physmem->getPort("functional");
105246SN/A        virtPort->setPeer(mem_port);
106246SN/A        mem_port->setPeer(virtPort);
107246SN/A
1082190SN/A
109246SN/A        /**
110246SN/A         * Load the kernel code into memory
11113641Sqtt2@cornell.edu         */
11213641Sqtt2@cornell.edu        if (params()->kernel == "") {
11313641Sqtt2@cornell.edu            inform("No kernel set for full system simulation. "
11413641Sqtt2@cornell.edu                    "Assuming you know what you're doing...\n");
115246SN/A        } else {
116246SN/A            // Load kernel code
117246SN/A            kernel = createObjectFile(params()->kernel);
118246SN/A            inform("kernel located at: %s", params()->kernel);
119246SN/A
1202SN/A            if (kernel == NULL)
1212680Sktlim@umich.edu                fatal("Could not load kernel file %s", params()->kernel);
1222423SN/A
1232190SN/A            // Load program sections into memory
124180SN/A            kernel->loadSections(functionalPort, loadAddrMask);
12510110Sandreas.hansson@arm.com
1262190SN/A            // setup entry points
12710190Sakash.bagdia@arm.com            kernelStart = kernel->textBase();
12810190Sakash.bagdia@arm.com            kernelEnd = kernel->bssBase() + kernel->bssSize();
12910110Sandreas.hansson@arm.com            kernelEntry = kernel->entryPoint();
1305715Shsul@eecs.umich.edu
1315715Shsul@eecs.umich.edu            // load symbols
1325714Shsul@eecs.umich.edu            if (!kernel->loadGlobalSymbols(kernelSymtab))
13313865Sgabeblack@google.com                fatal("could not load kernel symbols\n");
1345714Shsul@eecs.umich.edu
13513865Sgabeblack@google.com            if (!kernel->loadLocalSymbols(kernelSymtab))
1365714Shsul@eecs.umich.edu                fatal("could not load kernel local symbols\n");
13712406Sgabeblack@google.com
1382190SN/A            if (!kernel->loadGlobalSymbols(debugSymbolTable))
13912406Sgabeblack@google.com                fatal("could not load kernel symbols\n");
1402521SN/A
1418887Sgeoffrey.blake@arm.com            if (!kernel->loadLocalSymbols(debugSymbolTable))
1428733Sgeoffrey.blake@arm.com                fatal("could not load kernel local symbols\n");
14313693Sgiacomo.gabrielli@arm.com
14413693Sgiacomo.gabrielli@arm.com            DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
1459020Sgblack@eecs.umich.edu            DPRINTF(Loader, "Kernel end   = %#x\n", kernelEnd);
1468541Sgblack@eecs.umich.edu            DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
1474997Sgblack@eecs.umich.edu            DPRINTF(Loader, "Kernel loaded...\n");
1484997Sgblack@eecs.umich.edu        }
14913905Sgabeblack@google.com    }
1502654SN/A
1518852Sandreas.hansson@arm.com    // increment the number of running systms
1522521SN/A    numSystemsRunning++;
15314022Sgabeblack@google.com
1543673Srdreslin@umich.edu    activeCpus.clear();
1558706Sandreas.hansson@arm.com}
1568706Sandreas.hansson@arm.com
1578706Sandreas.hansson@arm.comSystem::~System()
1588706Sandreas.hansson@arm.com{
1598706Sandreas.hansson@arm.com    delete kernelSymtab;
1608706Sandreas.hansson@arm.com    delete kernel;
1618706Sandreas.hansson@arm.com}
1628799Sgblack@eecs.umich.edu
16314022Sgabeblack@google.comvoid
1642518SN/ASystem::setMemoryMode(Enums::MemoryMode mode)
1652190SN/A{
1662190SN/A    assert(getState() == Drained);
16711886Sbrandon.potter@amd.com    memoryMode = mode;
16811886Sbrandon.potter@amd.com}
1692190SN/A
1702159SN/Abool System::breakpoint()
1712235SN/A{
1722103SN/A    if (remoteGDB.size())
17310407Smitch.hayenga@arm.com        return remoteGDB[0]->breakpoint();
17410407Smitch.hayenga@arm.com    return false;
175393SN/A}
176393SN/A
17710407Smitch.hayenga@arm.com/**
178393SN/A * Setting rgdb_wait to a positive integer waits for a remote debugger to
179393SN/A * connect to that context ID before continuing.  This should really
18010407Smitch.hayenga@arm.com   be a parameter on the CPU object or something...
1812159SN/A */
18211627Smichael.lebeane@amd.comint rgdb_wait = -1;
18311627Smichael.lebeane@amd.com
18411627Smichael.lebeane@amd.comint
18511627Smichael.lebeane@amd.comSystem::registerThreadContext(ThreadContext *tc, int assigned)
18611627Smichael.lebeane@amd.com{
18711627Smichael.lebeane@amd.com    int id;
1882190SN/A    if (assigned == -1) {
1892159SN/A        for (id = 0; id < threadContexts.size(); id++) {
1902680Sktlim@umich.edu            if (!threadContexts[id])
1912159SN/A                break;
1922190SN/A        }
1932159SN/A
1942313SN/A        if (threadContexts.size() <= id)
1952235SN/A            threadContexts.resize(id + 1);
1962235SN/A    } else {
1972235SN/A        if (threadContexts.size() <= assigned)
1982235SN/A            threadContexts.resize(assigned + 1);
1992235SN/A        id = assigned;
2002254SN/A    }
2012254SN/A
2022254SN/A    if (threadContexts[id])
2032235SN/A        fatal("Cannot have two CPUs with the same id (%d)\n", id);
2042680Sktlim@umich.edu
2052159SN/A    threadContexts[id] = tc;
2062190SN/A    _numContexts++;
2072159SN/A
2082159SN/A    int port = getRemoteGDBPort();
2092159SN/A    if (port) {
2102159SN/A        RemoteGDB *rgdb = new RemoteGDB(this, tc);
21113865Sgabeblack@google.com        GDBListener *gdbl = new GDBListener(rgdb, port + id);
2122159SN/A        gdbl->listen();
21313865Sgabeblack@google.com
2142159SN/A        if (rgdb_wait != -1 && rgdb_wait == id)
21512109SRekai.GonzalezAlberquilla@arm.com            gdbl->accept();
21612109SRekai.GonzalezAlberquilla@arm.com
21712109SRekai.GonzalezAlberquilla@arm.com        if (remoteGDB.size() <= id) {
21812109SRekai.GonzalezAlberquilla@arm.com            remoteGDB.resize(id + 1);
21912109SRekai.GonzalezAlberquilla@arm.com        }
22012109SRekai.GonzalezAlberquilla@arm.com
22112109SRekai.GonzalezAlberquilla@arm.com        remoteGDB[id] = rgdb;
22212109SRekai.GonzalezAlberquilla@arm.com    }
22312109SRekai.GonzalezAlberquilla@arm.com
22412109SRekai.GonzalezAlberquilla@arm.com    activeCpus.push_back(false);
22512109SRekai.GonzalezAlberquilla@arm.com
22612109SRekai.GonzalezAlberquilla@arm.com    return id;
22712109SRekai.GonzalezAlberquilla@arm.com}
22812109SRekai.GonzalezAlberquilla@arm.com
22912109SRekai.GonzalezAlberquilla@arm.comint
23012109SRekai.GonzalezAlberquilla@arm.comSystem::numRunningContexts()
23112109SRekai.GonzalezAlberquilla@arm.com{
23212109SRekai.GonzalezAlberquilla@arm.com    int running = 0;
23312109SRekai.GonzalezAlberquilla@arm.com    for (int i = 0; i < _numContexts; ++i) {
23412109SRekai.GonzalezAlberquilla@arm.com        if (threadContexts[i]->status() != ThreadContext::Halted)
23512109SRekai.GonzalezAlberquilla@arm.com            ++running;
23612109SRekai.GonzalezAlberquilla@arm.com    }
23712109SRekai.GonzalezAlberquilla@arm.com    return running;
23812109SRekai.GonzalezAlberquilla@arm.com}
23912109SRekai.GonzalezAlberquilla@arm.com
24012109SRekai.GonzalezAlberquilla@arm.comvoid
24112109SRekai.GonzalezAlberquilla@arm.comSystem::initState()
24212109SRekai.GonzalezAlberquilla@arm.com{
24312109SRekai.GonzalezAlberquilla@arm.com    if (FullSystem) {
24412109SRekai.GonzalezAlberquilla@arm.com        int i;
24512109SRekai.GonzalezAlberquilla@arm.com        for (i = 0; i < threadContexts.size(); i++)
24612109SRekai.GonzalezAlberquilla@arm.com            TheISA::startupCPU(threadContexts[i], i);
24712109SRekai.GonzalezAlberquilla@arm.com    }
24812109SRekai.GonzalezAlberquilla@arm.com}
24913610Sgiacomo.gabrielli@arm.com
25013610Sgiacomo.gabrielli@arm.comvoid
25113610Sgiacomo.gabrielli@arm.comSystem::replaceThreadContext(ThreadContext *tc, int context_id)
25213610Sgiacomo.gabrielli@arm.com{
25313865Sgabeblack@google.com    if (context_id >= threadContexts.size()) {
2549920Syasuko.eckert@amd.com        panic("replaceThreadContext: bad id, %d >= %d\n",
25513865Sgabeblack@google.com              context_id, threadContexts.size());
2562159SN/A    }
25713865Sgabeblack@google.com
2582455SN/A    threadContexts[context_id] = tc;
25912109SRekai.GonzalezAlberquilla@arm.com    if (context_id < remoteGDB.size())
26012109SRekai.GonzalezAlberquilla@arm.com        remoteGDB[context_id]->replaceThreadContext(tc);
26112109SRekai.GonzalezAlberquilla@arm.com}
26212109SRekai.GonzalezAlberquilla@arm.com
26313610Sgiacomo.gabrielli@arm.comAddr
26413610Sgiacomo.gabrielli@arm.comSystem::allocPhysPages(int npages)
26513610Sgiacomo.gabrielli@arm.com{
26613865Sgabeblack@google.com    Addr return_addr = pagePtr << LogVMPageSize;
2679920Syasuko.eckert@amd.com    pagePtr += npages;
26813865Sgabeblack@google.com    if (return_addr >= physmem->size())
2692159SN/A        fatal("Out of memory, please increase size of physical memory.");
2707720Sgblack@eecs.umich.edu    return return_addr;
2712159SN/A}
27211886Sbrandon.potter@amd.com
27311886Sbrandon.potter@amd.comAddr
27411886Sbrandon.potter@amd.comSystem::memSize()
27511886Sbrandon.potter@amd.com{
27611886Sbrandon.potter@amd.com    return physmem->size();
27711886Sbrandon.potter@amd.com}
27811886Sbrandon.potter@amd.com
27911886Sbrandon.potter@amd.comAddr
2808733Sgeoffrey.blake@arm.comSystem::freeMemSize()
2818733Sgeoffrey.blake@arm.com{
28213865Sgabeblack@google.com   return physmem->size() - (pagePtr << LogVMPageSize);
2832159SN/A}
28413865Sgabeblack@google.com
2852159SN/Abool
28613865Sgabeblack@google.comSystem::isMemory(const Addr addr) const
2875260Sksewell@umich.edu{
28813865Sgabeblack@google.com    std::list<Range<Addr> >::const_iterator i;
2894172Ssaidi@eecs.umich.edu    for (i = memRanges.begin(); i != memRanges.end(); i++) {
29013865Sgabeblack@google.com        if (*i == addr)
2912159SN/A            return true;
29213865Sgabeblack@google.com    }
2932190SN/A    return false;
29413865Sgabeblack@google.com}
2952190SN/A
29612106SRekai.GonzalezAlberquilla@arm.comvoid
2976313Sgblack@eecs.umich.eduSystem::resume()
2982235SN/A{
2992235SN/A    SimObject::resume();
30013865Sgabeblack@google.com    totalNumInsts = 0;
3012190SN/A}
3022190SN/A
3032159SN/Avoid
3042235SN/ASystem::serialize(ostream &os)
30513865Sgabeblack@google.com{
3062834Sksewell@umich.edu    if (FullSystem)
30711877Sbrandon.potter@amd.com        kernelSymtab->serialize("kernel_symtab", os);
3084111Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(pagePtr);
3092834Sksewell@umich.edu    SERIALIZE_SCALAR(nextPID);
3102834Sksewell@umich.edu}
3112834Sksewell@umich.edu
3122834Sksewell@umich.edu
3132525SN/Avoid
3145217Ssaidi@eecs.umich.eduSystem::unserialize(Checkpoint *cp, const string &section)
3155217Ssaidi@eecs.umich.edu{
3169426SAndreas.Sandberg@ARM.com    if (FullSystem)
3179426SAndreas.Sandberg@ARM.com        kernelSymtab->unserialize("kernel_symtab", cp, section);
3189426SAndreas.Sandberg@ARM.com    UNSERIALIZE_SCALAR(pagePtr);
3199426SAndreas.Sandberg@ARM.com    UNSERIALIZE_SCALAR(nextPID);
3209426SAndreas.Sandberg@ARM.com}
3219426SAndreas.Sandberg@ARM.com
3229426SAndreas.Sandberg@ARM.comvoid
32312106SRekai.GonzalezAlberquilla@arm.comSystem::printSystems()
3249426SAndreas.Sandberg@ARM.com{
3259426SAndreas.Sandberg@ARM.com    vector<System *>::iterator i = systemList.begin();
3269426SAndreas.Sandberg@ARM.com    vector<System *>::iterator end = systemList.end();
3279426SAndreas.Sandberg@ARM.com    for (; i != end; ++i) {
3289426SAndreas.Sandberg@ARM.com        System *sys = *i;
32913865Sgabeblack@google.com        cerr << "System " << sys->name() << ": " << hex << sys << endl;
33013865Sgabeblack@google.com    }
3319426SAndreas.Sandberg@ARM.com}
33213865Sgabeblack@google.com
33313865Sgabeblack@google.comvoid
3349426SAndreas.Sandberg@ARM.comprintSystems()
33513865Sgabeblack@google.com{
33613865Sgabeblack@google.com    System::printSystems();
33713865Sgabeblack@google.com}
33812109SRekai.GonzalezAlberquilla@arm.com
33913865Sgabeblack@google.comconst char *System::MemoryModeStrings[3] = {"invalid", "atomic",
34012109SRekai.GonzalezAlberquilla@arm.com    "timing"};
34113865Sgabeblack@google.com
34212109SRekai.GonzalezAlberquilla@arm.comSystem *
34312109SRekai.GonzalezAlberquilla@arm.comSystemParams::create()
34413865Sgabeblack@google.com{
34513865Sgabeblack@google.com    return new System(this);
34613865Sgabeblack@google.com}
34713865Sgabeblack@google.com