system.cc revision 9053:9cad1c26c3b3
12SN/A/* 22190SN/A * Copyright (c) 2011-2012 ARM Limited 32SN/A * All rights reserved 42SN/A * 52SN/A * The license below extends only to copyright in the software and shall 62SN/A * not be construed as granting a license to any other intellectual 72SN/A * property including but not limited to intellectual property relating 82SN/A * to a hardware implementation of the functionality of the software 92SN/A * licensed hereunder. You may use the software subject to the license 102SN/A * terms below provided that you ensure that this notice is replicated 112SN/A * unmodified and in its entirety in all distributions of the software, 122SN/A * modified or unmodified, in source code or in binary form. 132SN/A * 142SN/A * Copyright (c) 2003-2006 The Regents of The University of Michigan 152SN/A * Copyright (c) 2011 Regents of the University of California 162SN/A * All rights reserved. 172SN/A * 182SN/A * Redistribution and use in source and binary forms, with or without 192SN/A * modification, are permitted provided that the following conditions are 202SN/A * met: redistributions of source code must retain the above copyright 212SN/A * notice, this list of conditions and the following disclaimer; 222SN/A * redistributions in binary form must reproduce the above copyright 232SN/A * notice, this list of conditions and the following disclaimer in the 242SN/A * documentation and/or other materials provided with the distribution; 252SN/A * neither the name of the copyright holders nor the names of its 262SN/A * contributors may be used to endorse or promote products derived from 272665SN/A * this software without specific prior written permission. 282665SN/A * 292SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 302SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 312680Sktlim@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 322680Sktlim@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 332SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 341858SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 352423SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 362190SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3756SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38217SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 392036SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 402SN/A * 412190SN/A * Authors: Steve Reinhardt 422190SN/A * Lisa Hsu 432190SN/A * Nathan Binkert 442190SN/A * Ali Saidi 452190SN/A * Rick Strong 462313SN/A */ 472235SN/A 482423SN/A#include "arch/isa_traits.hh" 492521SN/A#include "arch/remote_gdb.hh" 502521SN/A#include "arch/utility.hh" 512190SN/A#include "arch/vtophys.hh" 522190SN/A#include "base/loader/object_file.hh" 532330SN/A#include "base/loader/symtab.hh" 542330SN/A#include "base/trace.hh" 552330SN/A#include "config/the_isa.hh" 562SN/A#include "cpu/thread_context.hh" 572680Sktlim@umich.edu#include "debug/Loader.hh" 582680Sktlim@umich.edu#include "debug/WorkItems.hh" 592680Sktlim@umich.edu#include "kern/kernel_stats.hh" 602680Sktlim@umich.edu#include "mem/physical.hh" 612680Sktlim@umich.edu#include "params/System.hh" 622680Sktlim@umich.edu#include "sim/byteswap.hh" 632680Sktlim@umich.edu#include "sim/debug.hh" 642680Sktlim@umich.edu#include "sim/full_system.hh" 652680Sktlim@umich.edu#include "sim/system.hh" 662680Sktlim@umich.edu 672680Sktlim@umich.eduusing namespace std; 682682Sktlim@umich.eduusing namespace TheISA; 692680Sktlim@umich.edu 702680Sktlim@umich.eduvector<System *> System::systemList; 712680Sktlim@umich.edu 722680Sktlim@umich.eduint System::numSystemsRunning = 0; 732680Sktlim@umich.edu 742SN/ASystem::System(Params *p) 752107SN/A : MemObject(p), _systemPort("system_port", this), 762107SN/A _numContexts(0), 772107SN/A pagePtr(0), 782190SN/A init_param(p->init_param), 792455SN/A physProxy(_systemPort), 802455SN/A virtProxy(_systemPort), 812107SN/A loadAddrMask(p->load_addr_mask), 822159SN/A nextPID(0), 832SN/A physmem(p->memories), 84246SN/A memoryMode(p->mem_mode), 85246SN/A workItemsBegin(0), 86246SN/A workItemsEnd(0), 87246SN/A numWorkIds(p->num_work_ids), 88246SN/A _params(p), 89246SN/A totalNumInsts(0), 90246SN/A instEventQueue("system instruction-based event queue") 91246SN/A{ 92246SN/A // add self to global system list 93246SN/A systemList.push_back(this); 94246SN/A 95246SN/A if (FullSystem) { 96246SN/A kernelSymtab = new SymbolTable; 972190SN/A if (!debugSymbolTable) 98246SN/A debugSymbolTable = new SymbolTable; 99246SN/A } 100246SN/A 101246SN/A // Get the generic system master IDs 102246SN/A MasterID tmp_id M5_VAR_USED; 103246SN/A tmp_id = getMasterId("writebacks"); 104246SN/A assert(tmp_id == Request::wbMasterId); 1052SN/A tmp_id = getMasterId("functional"); 1062680Sktlim@umich.edu assert(tmp_id == Request::funcMasterId); 1072423SN/A tmp_id = getMasterId("interrupt"); 1082190SN/A assert(tmp_id == Request::intMasterId); 109180SN/A 1102190SN/A if (FullSystem) { 1112190SN/A if (params()->kernel == "") { 1122190SN/A inform("No kernel set for full system simulation. " 1132190SN/A "Assuming you know what you're doing if not SPARC ISA\n"); 1142190SN/A } else { 1152190SN/A // Get the kernel code 1162190SN/A kernel = createObjectFile(params()->kernel); 1172190SN/A inform("kernel located at: %s", params()->kernel); 1182190SN/A 1192190SN/A if (kernel == NULL) 1202521SN/A fatal("Could not load kernel file %s", params()->kernel); 1212330SN/A 1222654SN/A // setup entry points 1232521SN/A kernelStart = kernel->textBase(); 1242521SN/A kernelEnd = kernel->bssBase() + kernel->bssSize(); 1252680Sktlim@umich.edu kernelEntry = kernel->entryPoint(); 1262521SN/A 1272521SN/A // load symbols 1282190SN/A if (!kernel->loadGlobalSymbols(kernelSymtab)) 1292518SN/A fatal("could not load kernel symbols\n"); 1302518SN/A 1312190SN/A if (!kernel->loadLocalSymbols(kernelSymtab)) 1322190SN/A fatal("could not load kernel local symbols\n"); 1332190SN/A 1342190SN/A if (!kernel->loadGlobalSymbols(debugSymbolTable)) 1352159SN/A fatal("could not load kernel symbols\n"); 1362235SN/A 1372103SN/A if (!kernel->loadLocalSymbols(debugSymbolTable)) 138393SN/A fatal("could not load kernel local symbols\n"); 139393SN/A 1402190SN/A // Loading only needs to happen once and after memory system is 141393SN/A // connected so it will happen in initState() 142393SN/A } 1432190SN/A } 144393SN/A 145393SN/A // increment the number of running systms 1462190SN/A numSystemsRunning++; 147393SN/A 148393SN/A // Set back pointers to the system in all memories 1492190SN/A for (int x = 0; x < params()->memories.size(); x++) 1502159SN/A params()->memories[x]->system(this); 1512159SN/A} 1522190SN/A 1532159SN/ASystem::~System() 1542159SN/A{ 1552680Sktlim@umich.edu delete kernelSymtab; 1562159SN/A delete kernel; 1572190SN/A 1582159SN/A for (uint32_t j = 0; j < numWorkIds; j++) 1592190SN/A delete workItemStats[j]; 1602190SN/A} 1612159SN/A 1622235SN/Avoid 1632313SN/ASystem::init() 1642235SN/A{ 1652235SN/A // check that the system port is connected 1662235SN/A if (!_systemPort.isConnected()) 1672235SN/A panic("System port on %s is not connected.\n", name()); 1682235SN/A} 1692254SN/A 1702254SN/AMasterPort& 1712254SN/ASystem::getMasterPort(const std::string &if_name, int idx) 1722235SN/A{ 1732235SN/A // no need to distinguish at the moment (besides checking) 1742190SN/A return _systemPort; 1752159SN/A} 1762235SN/A 1772254SN/Avoid 1782190SN/ASystem::setMemoryMode(Enums::MemoryMode mode) 1792159SN/A{ 1802680Sktlim@umich.edu assert(getState() == Drained); 1812159SN/A memoryMode = mode; 1822190SN/A} 1832159SN/A 1842159SN/Abool System::breakpoint() 1852159SN/A{ 1862159SN/A if (remoteGDB.size()) 1872190SN/A return remoteGDB[0]->breakpoint(); 1882159SN/A return false; 1892455SN/A} 1902159SN/A 1912455SN/A/** 1922159SN/A * Setting rgdb_wait to a positive integer waits for a remote debugger to 1932455SN/A * connect to that context ID before continuing. This should really 1942455SN/A be a parameter on the CPU object or something... 1952455SN/A */ 1962159SN/Aint rgdb_wait = -1; 1972190SN/A 1982159SN/Aint 1992455SN/ASystem::registerThreadContext(ThreadContext *tc, int assigned) 2002159SN/A{ 2012455SN/A int id; 2022159SN/A if (assigned == -1) { 2032455SN/A for (id = 0; id < threadContexts.size(); id++) { 2042455SN/A if (!threadContexts[id]) 2052455SN/A break; 2062159SN/A } 2072190SN/A 2082159SN/A if (threadContexts.size() <= id) 2092190SN/A threadContexts.resize(id + 1); 2102159SN/A } else { 2112190SN/A if (threadContexts.size() <= assigned) 2122159SN/A threadContexts.resize(assigned + 1); 2132190SN/A id = assigned; 2142159SN/A } 2152447SN/A 2162447SN/A if (threadContexts[id]) 2172447SN/A fatal("Cannot have two CPUs with the same id (%d)\n", id); 2182447SN/A 2192190SN/A threadContexts[id] = tc; 2202159SN/A _numContexts++; 2212190SN/A 2222190SN/A int port = getRemoteGDBPort(); 2232190SN/A if (port) { 2242190SN/A RemoteGDB *rgdb = new RemoteGDB(this, tc); 2252190SN/A GDBListener *gdbl = new GDBListener(rgdb, port + id); 2262190SN/A gdbl->listen(); 2272235SN/A 2282235SN/A if (rgdb_wait != -1 && rgdb_wait == id) 2292190SN/A gdbl->accept(); 2302190SN/A 2312190SN/A if (remoteGDB.size() <= id) { 2322159SN/A remoteGDB.resize(id + 1); 2332159SN/A } 2342190SN/A 2352159SN/A remoteGDB[id] = rgdb; 2362159SN/A } 2372235SN/A 2382190SN/A activeCpus.push_back(false); 2392190SN/A 2402159SN/A return id; 2412190SN/A} 2422159SN/A 2432159SN/Aint 2442190SN/ASystem::numRunningContexts() 2452159SN/A{ 2462190SN/A int running = 0; 2472159SN/A for (int i = 0; i < _numContexts; ++i) { 2482190SN/A if (threadContexts[i]->status() != ThreadContext::Halted) 2492235SN/A ++running; 2502190SN/A } 2512159SN/A return running; 2522525SN/A} 2532525SN/A 2542525SN/Avoid 2552159SN/ASystem::initState() 2562159SN/A{ 2572682Sktlim@umich.edu int i; 2582682Sktlim@umich.edu if (FullSystem) { 2592682Sktlim@umich.edu for (i = 0; i < threadContexts.size(); i++) 2602682Sktlim@umich.edu TheISA::startupCPU(threadContexts[i], i); 2612682Sktlim@umich.edu // Moved from the constructor to here since it relies on the 2622682Sktlim@umich.edu // address map being resolved in the interconnect 2632682Sktlim@umich.edu /** 2642682Sktlim@umich.edu * Load the kernel code into memory 2652682Sktlim@umich.edu */ 2662682Sktlim@umich.edu if (params()->kernel != "") { 2672680Sktlim@umich.edu // Load program sections into memory 2682680Sktlim@umich.edu kernel->loadSections(physProxy, loadAddrMask); 2692190SN/A 2702190SN/A DPRINTF(Loader, "Kernel start = %#x\n", kernelStart); 2712680Sktlim@umich.edu DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd); 2722680Sktlim@umich.edu DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry); 2732159SN/A DPRINTF(Loader, "Kernel loaded...\n"); 2742190SN/A } 2752680Sktlim@umich.edu } 2762SN/A 2772SN/A activeCpus.clear(); 2782SN/A 2792680Sktlim@umich.edu if (!FullSystem) 2802SN/A return; 2812680Sktlim@umich.edu 282716SN/A for (i = 0; i < threadContexts.size(); i++) 2832680Sktlim@umich.edu TheISA::startupCPU(threadContexts[i], i); 2842SN/A} 2851858SN/A 2862680Sktlim@umich.eduvoid 2872SN/ASystem::replaceThreadContext(ThreadContext *tc, int context_id) 2882680Sktlim@umich.edu{ 2891917SN/A if (context_id >= threadContexts.size()) { 2902680Sktlim@umich.edu panic("replaceThreadContext: bad id, %d >= %d\n", 2912521SN/A context_id, threadContexts.size()); 2922680Sktlim@umich.edu } 2932654SN/A 2942680Sktlim@umich.edu threadContexts[context_id] = tc; 2952521SN/A if (context_id < remoteGDB.size()) 2962680Sktlim@umich.edu remoteGDB[context_id]->replaceThreadContext(tc); 2972521SN/A} 2982680Sktlim@umich.edu 2992SN/AAddr 3002680Sktlim@umich.eduSystem::allocPhysPages(int npages) 3012518SN/A{ 3022680Sktlim@umich.edu Addr return_addr = pagePtr << LogVMPageSize; 3032SN/A pagePtr += npages; 3042SN/A if ((pagePtr << LogVMPageSize) > physmem.totalSize()) 3052680Sktlim@umich.edu fatal("Out of memory, please increase size of physical memory."); 306595SN/A return return_addr; 3072680Sktlim@umich.edu} 3082SN/A 3092190SN/AAddr 3102190SN/ASystem::memSize() const 3112680Sktlim@umich.edu{ 3122SN/A return physmem.totalSize(); 3132190SN/A} 3142680Sktlim@umich.edu 3152SN/AAddr 3162190SN/ASystem::freeMemSize() const 3172680Sktlim@umich.edu{ 3182SN/A return physmem.totalSize() - (pagePtr << LogVMPageSize); 3192190SN/A} 3202680Sktlim@umich.edu 321217SN/Abool 3221858SN/ASystem::isMemAddr(Addr addr) const 3232680Sktlim@umich.edu{ 3242190SN/A return physmem.isMemAddr(addr); 3252190SN/A} 3262680Sktlim@umich.edu 3272680Sktlim@umich.eduvoid 3282190SN/ASystem::resume() 3292680Sktlim@umich.edu{ 3302190SN/A SimObject::resume(); 3312680Sktlim@umich.edu totalNumInsts = 0; 3322190SN/A} 3332680Sktlim@umich.edu 3342190SN/Avoid 3352235SN/ASystem::serialize(ostream &os) 3362680Sktlim@umich.edu{ 3372235SN/A if (FullSystem) 3382680Sktlim@umich.edu kernelSymtab->serialize("kernel_symtab", os); 3392680Sktlim@umich.edu SERIALIZE_SCALAR(pagePtr); 3402254SN/A SERIALIZE_SCALAR(nextPID); 3412680Sktlim@umich.edu} 3422680Sktlim@umich.edu 3432235SN/A 3442235SN/Avoid 3452680Sktlim@umich.eduSystem::unserialize(Checkpoint *cp, const string §ion) 3462190SN/A{ 3472190SN/A if (FullSystem) 3482680Sktlim@umich.edu kernelSymtab->unserialize("kernel_symtab", cp, section); 3492SN/A UNSERIALIZE_SCALAR(pagePtr); 3502190SN/A UNSERIALIZE_SCALAR(nextPID); 3512680Sktlim@umich.edu} 3522SN/A 3532680Sktlim@umich.eduvoid 354716SN/ASystem::regStats() 3552SN/A{ 3562SN/A for (uint32_t j = 0; j < numWorkIds ; j++) { 3572SN/A workItemStats[j] = new Stats::Histogram(); 3582SN/A stringstream namestr; 3592680Sktlim@umich.edu ccprintf(namestr, "work_item_type%d", j); 3602SN/A workItemStats[j]->init(20) 3612455SN/A .name(name() + "." + namestr.str()) 3622680Sktlim@umich.edu .desc("Run time stat for" + namestr.str()) 3632SN/A .prereq(*workItemStats[j]); 3642455SN/A } 3652680Sktlim@umich.edu} 3662SN/A 3672455SN/Avoid 3682680Sktlim@umich.eduSystem::workItemEnd(uint32_t tid, uint32_t workid) 3692455SN/A{ 3702455SN/A std::pair<uint32_t,uint32_t> p(tid, workid); 3712680Sktlim@umich.edu if (!lastWorkItemStarted.count(p)) 3722SN/A return; 3732SN/A 3742680Sktlim@umich.edu Tick samp = curTick() - lastWorkItemStarted[p]; 3752SN/A DPRINTF(WorkItems, "Work item end: %d\t%d\t%lld\n", tid, workid, samp); 3762455SN/A 3772680Sktlim@umich.edu if (workid >= numWorkIds) 3782SN/A fatal("Got workid greater than specified in system configuration\n"); 3792455SN/A 3802680Sktlim@umich.edu workItemStats[workid]->sample(samp); 3812SN/A lastWorkItemStarted.erase(p); 3822455SN/A} 3832680Sktlim@umich.edu 3842455SN/Avoid 3852455SN/ASystem::printSystems() 3862680Sktlim@umich.edu{ 3872SN/A vector<System *>::iterator i = systemList.begin(); 3882680Sktlim@umich.edu vector<System *>::iterator end = systemList.end(); 3892SN/A for (; i != end; ++i) { 3902680Sktlim@umich.edu System *sys = *i; 3912206SN/A cerr << "System " << sys->name() << ": " << hex << sys << endl; 3922680Sktlim@umich.edu } 3932252SN/A} 3942680Sktlim@umich.edu 3952SN/Avoid 3962680Sktlim@umich.eduprintSystems() 3972447SN/A{ 3982680Sktlim@umich.edu System::printSystems(); 3992447SN/A} 4002159SN/A 4012680Sktlim@umich.eduMasterID 4022SN/ASystem::getMasterId(std::string master_name) 4032159SN/A{ 4042680Sktlim@umich.edu // strip off system name if the string starts with it 4052SN/A if (master_name.size() > name().size() && 4062159SN/A master_name.compare(0, name().size(), name()) == 0) 4072680Sktlim@umich.edu master_name = master_name.erase(0, name().size() + 1); 4082SN/A 4092159SN/A // CPUs in switch_cpus ask for ids again after switching 4102680Sktlim@umich.edu for (int i = 0; i < masterIds.size(); i++) { 4112190SN/A if (masterIds[i] == master_name) { 4122190SN/A return i; 4132680Sktlim@umich.edu } 4142190SN/A } 4152190SN/A 4162680Sktlim@umich.edu // Verify that the statistics haven't been enabled yet 4171858SN/A // Otherwise objects will have sized their stat buckets and 4182680Sktlim@umich.edu // they will be too small 4192SN/A 4202SN/A if (Stats::enabled()) 4212190SN/A fatal("Can't request a masterId after regStats(). \ 4222680Sktlim@umich.edu You must do so in init().\n"); 4232190SN/A 4241858SN/A masterIds.push_back(master_name); 4252680Sktlim@umich.edu 426360SN/A return masterIds.size() - 1; 427360SN/A} 4282190SN/A 4292680Sktlim@umich.edustd::string 430360SN/ASystem::getMasterName(MasterID master_id) 4311450SN/A{ 4322680Sktlim@umich.edu if (master_id >= masterIds.size()) 433360SN/A fatal("Invalid master_id passed to getMasterName()\n"); 4342190SN/A 4352680Sktlim@umich.edu return masterIds[master_id]; 4362SN/A} 4372525SN/A 4382525SN/Aconst char *System::MemoryModeStrings[3] = {"invalid", "atomic", 4392525SN/A "timing"}; 4402525SN/A 4412680Sktlim@umich.eduSystem * 4422525SN/ASystemParams::create() 4432SN/A{ 4442SN/A return new System(this); 4452190SN/A} 446