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 §ion) 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