1/* 2 * Copyright (c) 2011-2014 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2003-2006 The Regents of The University of Michigan 15 * Copyright (c) 2011 Regents of the University of California 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions are 20 * met: redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer; 22 * redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution; 25 * neither the name of the copyright holders nor the names of its 26 * contributors may be used to endorse or promote products derived from 27 * this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Authors: Steve Reinhardt 42 * Lisa Hsu 43 * Nathan Binkert 44 * Ali Saidi 45 * Rick Strong 46 */ 47 48#include "arch/remote_gdb.hh" 49#include "arch/utility.hh" 50#include "base/loader/object_file.hh" 51#include "base/loader/symtab.hh" 52#include "base/str.hh" 53#include "base/trace.hh" 54#include "cpu/thread_context.hh" 55#include "debug/Loader.hh" 56#include "debug/WorkItems.hh" 57#include "mem/abstract_mem.hh" 58#include "mem/physical.hh" 59#include "params/System.hh" 60#include "sim/byteswap.hh" 61#include "sim/debug.hh" 62#include "sim/full_system.hh" 63#include "sim/system.hh" 64 65/** 66 * To avoid linking errors with LTO, only include the header if we 67 * actually have a definition. 68 */ 69#if THE_ISA != NULL_ISA 70#include "kern/kernel_stats.hh" 71#endif 72 73using namespace std; 74using namespace TheISA; 75 76vector<System *> System::systemList; 77 78int System::numSystemsRunning = 0; 79 80System::System(Params *p) 81 : MemObject(p), _systemPort("system_port", this), 82 _numContexts(0), 83 pagePtr(0), 84 init_param(p->init_param), 85 physProxy(_systemPort, p->cache_line_size), 86 kernelSymtab(nullptr), 87 kernel(nullptr), 88 loadAddrMask(p->load_addr_mask), 89 loadAddrOffset(p->load_offset), 90 nextPID(0), 91 physmem(name() + ".physmem", p->memories, p->mmap_using_noreserve), 92 memoryMode(p->mem_mode), 93 _cacheLineSize(p->cache_line_size), 94 workItemsBegin(0), 95 workItemsEnd(0), 96 numWorkIds(p->num_work_ids), 97 _params(p), 98 totalNumInsts(0), 99 instEventQueue("system instruction-based event queue") 100{ 101 // add self to global system list 102 systemList.push_back(this); 103 104 if (FullSystem) { 105 kernelSymtab = new SymbolTable; 106 if (!debugSymbolTable) 107 debugSymbolTable = new SymbolTable; 108 } 109 110 // check if the cache line size is a value known to work 111 if (!(_cacheLineSize == 16 || _cacheLineSize == 32 || 112 _cacheLineSize == 64 || _cacheLineSize == 128)) 113 warn_once("Cache line size is neither 16, 32, 64 nor 128 bytes.\n"); 114 115 // Get the generic system master IDs 116 MasterID tmp_id M5_VAR_USED; 117 tmp_id = getMasterId("writebacks"); 118 assert(tmp_id == Request::wbMasterId); 119 tmp_id = getMasterId("functional"); 120 assert(tmp_id == Request::funcMasterId); 121 tmp_id = getMasterId("interrupt"); 122 assert(tmp_id == Request::intMasterId); 123 124 if (FullSystem) { 125 if (params()->kernel == "") { 126 inform("No kernel set for full system simulation. " 127 "Assuming you know what you're doing\n"); 128 } else { 129 // Get the kernel code 130 kernel = createObjectFile(params()->kernel); 131 inform("kernel located at: %s", params()->kernel); 132 133 if (kernel == NULL) 134 fatal("Could not load kernel file %s", params()->kernel); 135 136 // setup entry points 137 kernelStart = kernel->textBase(); 138 kernelEnd = kernel->bssBase() + kernel->bssSize(); 139 kernelEntry = kernel->entryPoint(); 140 141 // load symbols 142 if (!kernel->loadGlobalSymbols(kernelSymtab)) 143 fatal("could not load kernel symbols\n"); 144 145 if (!kernel->loadLocalSymbols(kernelSymtab)) 146 fatal("could not load kernel local symbols\n"); 147 148 if (!kernel->loadGlobalSymbols(debugSymbolTable)) 149 fatal("could not load kernel symbols\n"); 150 151 if (!kernel->loadLocalSymbols(debugSymbolTable)) 152 fatal("could not load kernel local symbols\n"); 153 154 // Loading only needs to happen once and after memory system is 155 // connected so it will happen in initState() 156 } 157 } 158 159 // increment the number of running systms 160 numSystemsRunning++; 161 162 // Set back pointers to the system in all memories 163 for (int x = 0; x < params()->memories.size(); x++) 164 params()->memories[x]->system(this); 165} 166 167System::~System() 168{ 169 delete kernelSymtab; 170 delete kernel; 171 172 for (uint32_t j = 0; j < numWorkIds; j++) 173 delete workItemStats[j]; 174} 175 176void 177System::init() 178{ 179 // check that the system port is connected 180 if (!_systemPort.isConnected()) 181 panic("System port on %s is not connected.\n", name()); 182} 183 184BaseMasterPort& 185System::getMasterPort(const std::string &if_name, PortID idx) 186{ 187 // no need to distinguish at the moment (besides checking) 188 return _systemPort; 189} 190 191void 192System::setMemoryMode(Enums::MemoryMode mode) 193{ 194 assert(drainState() == DrainState::Drained); 195 memoryMode = mode; 196} 197 198bool System::breakpoint() 199{ 200 if (remoteGDB.size()) 201 return remoteGDB[0]->breakpoint(); 202 return false; 203} 204 205/** 206 * Setting rgdb_wait to a positive integer waits for a remote debugger to 207 * connect to that context ID before continuing. This should really 208 be a parameter on the CPU object or something... 209 */ 210int rgdb_wait = -1; 211
|
212int
213System::registerThreadContext(ThreadContext *tc, int assigned)
|
212ContextID 213System::registerThreadContext(ThreadContext *tc, ContextID assigned) |
214{ 215 int id;
|
216 if (assigned == -1) {
|
216 if (assigned == InvalidContextID) { |
217 for (id = 0; id < threadContexts.size(); id++) { 218 if (!threadContexts[id]) 219 break; 220 } 221 222 if (threadContexts.size() <= id) 223 threadContexts.resize(id + 1); 224 } else { 225 if (threadContexts.size() <= assigned) 226 threadContexts.resize(assigned + 1); 227 id = assigned; 228 } 229 230 if (threadContexts[id]) 231 fatal("Cannot have two CPUs with the same id (%d)\n", id); 232 233 threadContexts[id] = tc; 234 _numContexts++; 235 236#if THE_ISA != NULL_ISA 237 int port = getRemoteGDBPort(); 238 if (port) { 239 RemoteGDB *rgdb = new RemoteGDB(this, tc); 240 GDBListener *gdbl = new GDBListener(rgdb, port + id); 241 gdbl->listen(); 242 243 if (rgdb_wait != -1 && rgdb_wait == id) 244 gdbl->accept(); 245 246 if (remoteGDB.size() <= id) { 247 remoteGDB.resize(id + 1); 248 } 249 250 remoteGDB[id] = rgdb; 251 } 252#endif 253 254 activeCpus.push_back(false); 255 256 return id; 257} 258 259int 260System::numRunningContexts() 261{ 262 int running = 0; 263 for (int i = 0; i < _numContexts; ++i) { 264 if (threadContexts[i]->status() != ThreadContext::Halted) 265 ++running; 266 } 267 return running; 268} 269 270void 271System::initState() 272{ 273 if (FullSystem) { 274 for (int i = 0; i < threadContexts.size(); i++) 275 TheISA::startupCPU(threadContexts[i], i); 276 // Moved from the constructor to here since it relies on the 277 // address map being resolved in the interconnect 278 /** 279 * Load the kernel code into memory 280 */ 281 if (params()->kernel != "") { 282 if (params()->kernel_addr_check) { 283 // Validate kernel mapping before loading binary 284 if (!(isMemAddr((kernelStart & loadAddrMask) + 285 loadAddrOffset) && 286 isMemAddr((kernelEnd & loadAddrMask) + 287 loadAddrOffset))) { 288 fatal("Kernel is mapped to invalid location (not memory). " 289 "kernelStart 0x(%x) - kernelEnd 0x(%x) %#x:%#x\n", 290 kernelStart, 291 kernelEnd, (kernelStart & loadAddrMask) + 292 loadAddrOffset, 293 (kernelEnd & loadAddrMask) + loadAddrOffset); 294 } 295 } 296 // Load program sections into memory 297 kernel->loadSections(physProxy, loadAddrMask, loadAddrOffset); 298 299 DPRINTF(Loader, "Kernel start = %#x\n", kernelStart); 300 DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd); 301 DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry); 302 DPRINTF(Loader, "Kernel loaded...\n"); 303 } 304 } 305} 306 307void
|
308System::replaceThreadContext(ThreadContext *tc, int context_id)
|
308System::replaceThreadContext(ThreadContext *tc, ContextID context_id) |
309{ 310 if (context_id >= threadContexts.size()) { 311 panic("replaceThreadContext: bad id, %d >= %d\n", 312 context_id, threadContexts.size()); 313 } 314 315 threadContexts[context_id] = tc; 316 if (context_id < remoteGDB.size()) 317 remoteGDB[context_id]->replaceThreadContext(tc); 318} 319 320Addr 321System::allocPhysPages(int npages) 322{ 323 Addr return_addr = pagePtr << PageShift; 324 pagePtr += npages; 325 326 Addr next_return_addr = pagePtr << PageShift; 327 328 AddrRange m5opRange(0xffff0000, 0xffffffff); 329 if (m5opRange.contains(next_return_addr)) { 330 warn("Reached m5ops MMIO region\n"); 331 return_addr = 0xffffffff; 332 pagePtr = 0xffffffff >> PageShift; 333 } 334 335 if ((pagePtr << PageShift) > physmem.totalSize()) 336 fatal("Out of memory, please increase size of physical memory."); 337 return return_addr; 338} 339 340Addr 341System::memSize() const 342{ 343 return physmem.totalSize(); 344} 345 346Addr 347System::freeMemSize() const 348{ 349 return physmem.totalSize() - (pagePtr << PageShift); 350} 351 352bool 353System::isMemAddr(Addr addr) const 354{ 355 return physmem.isMemAddr(addr); 356} 357 358void 359System::drainResume() 360{ 361 totalNumInsts = 0; 362} 363 364void 365System::serialize(CheckpointOut &cp) const 366{ 367 if (FullSystem) 368 kernelSymtab->serialize("kernel_symtab", cp); 369 SERIALIZE_SCALAR(pagePtr); 370 SERIALIZE_SCALAR(nextPID); 371 serializeSymtab(cp); 372 373 // also serialize the memories in the system 374 physmem.serializeSection(cp, "physmem"); 375} 376 377 378void 379System::unserialize(CheckpointIn &cp) 380{ 381 if (FullSystem) 382 kernelSymtab->unserialize("kernel_symtab", cp); 383 UNSERIALIZE_SCALAR(pagePtr); 384 UNSERIALIZE_SCALAR(nextPID); 385 unserializeSymtab(cp); 386 387 // also unserialize the memories in the system 388 physmem.unserializeSection(cp, "physmem"); 389} 390 391void 392System::regStats() 393{ 394 for (uint32_t j = 0; j < numWorkIds ; j++) { 395 workItemStats[j] = new Stats::Histogram(); 396 stringstream namestr; 397 ccprintf(namestr, "work_item_type%d", j); 398 workItemStats[j]->init(20) 399 .name(name() + "." + namestr.str()) 400 .desc("Run time stat for" + namestr.str()) 401 .prereq(*workItemStats[j]); 402 } 403} 404 405void 406System::workItemEnd(uint32_t tid, uint32_t workid) 407{ 408 std::pair<uint32_t,uint32_t> p(tid, workid); 409 if (!lastWorkItemStarted.count(p)) 410 return; 411 412 Tick samp = curTick() - lastWorkItemStarted[p]; 413 DPRINTF(WorkItems, "Work item end: %d\t%d\t%lld\n", tid, workid, samp); 414 415 if (workid >= numWorkIds) 416 fatal("Got workid greater than specified in system configuration\n"); 417 418 workItemStats[workid]->sample(samp); 419 lastWorkItemStarted.erase(p); 420} 421 422void 423System::printSystems() 424{ 425 ios::fmtflags flags(cerr.flags()); 426 427 vector<System *>::iterator i = systemList.begin(); 428 vector<System *>::iterator end = systemList.end(); 429 for (; i != end; ++i) { 430 System *sys = *i; 431 cerr << "System " << sys->name() << ": " << hex << sys << endl; 432 } 433 434 cerr.flags(flags); 435} 436 437void 438printSystems() 439{ 440 System::printSystems(); 441} 442 443MasterID 444System::getMasterId(std::string master_name) 445{ 446 // strip off system name if the string starts with it 447 if (startswith(master_name, name())) 448 master_name = master_name.erase(0, name().size() + 1); 449 450 // CPUs in switch_cpus ask for ids again after switching 451 for (int i = 0; i < masterIds.size(); i++) { 452 if (masterIds[i] == master_name) { 453 return i; 454 } 455 } 456 457 // Verify that the statistics haven't been enabled yet 458 // Otherwise objects will have sized their stat buckets and 459 // they will be too small 460 461 if (Stats::enabled()) { 462 fatal("Can't request a masterId after regStats(). " 463 "You must do so in init().\n"); 464 } 465 466 masterIds.push_back(master_name); 467 468 return masterIds.size() - 1; 469} 470 471std::string 472System::getMasterName(MasterID master_id) 473{ 474 if (master_id >= masterIds.size()) 475 fatal("Invalid master_id passed to getMasterName()\n"); 476 477 return masterIds[master_id]; 478} 479 480System * 481SystemParams::create() 482{ 483 return new System(this); 484}
|