system.cc revision 7770:6286bb50127e
1/* 2 * Copyright (c) 2003-2006 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Steve Reinhardt 29 * Lisa Hsu 30 * Nathan Binkert 31 * Ali Saidi 32 */ 33 34#include "arch/isa_traits.hh" 35#include "arch/remote_gdb.hh" 36#include "arch/utility.hh" 37#include "base/loader/object_file.hh" 38#include "base/loader/symtab.hh" 39#include "base/trace.hh" 40#include "cpu/thread_context.hh" 41#include "config/full_system.hh" 42#include "config/the_isa.hh" 43#include "mem/mem_object.hh" 44#include "mem/physical.hh" 45#include "sim/byteswap.hh" 46#include "sim/system.hh" 47#include "sim/debug.hh" 48 49#if FULL_SYSTEM 50#include "arch/vtophys.hh" 51#include "kern/kernel_stats.hh" 52#include "mem/vport.hh" 53#else 54#include "params/System.hh" 55#endif 56 57using namespace std; 58using namespace TheISA; 59 60vector<System *> System::systemList; 61 62int System::numSystemsRunning = 0; 63 64System::System(Params *p) 65 : SimObject(p), physmem(p->physmem), _numContexts(0), 66#if FULL_SYSTEM 67 init_param(p->init_param), 68 loadAddrMask(p->load_addr_mask), 69#else 70 pagePtr(0), 71 nextPID(0), 72#endif 73 memoryMode(p->mem_mode), _params(p) 74{ 75 // add self to global system list 76 systemList.push_back(this); 77 78#if FULL_SYSTEM 79 kernelSymtab = new SymbolTable; 80 if (!debugSymbolTable) 81 debugSymbolTable = new SymbolTable; 82 83 84 /** 85 * Get a functional port to memory 86 */ 87 Port *mem_port; 88 functionalPort = new FunctionalPort(name() + "-fport"); 89 mem_port = physmem->getPort("functional"); 90 functionalPort->setPeer(mem_port); 91 mem_port->setPeer(functionalPort); 92 93 virtPort = new VirtualPort(name() + "-fport"); 94 mem_port = physmem->getPort("functional"); 95 virtPort->setPeer(mem_port); 96 mem_port->setPeer(virtPort); 97 98 99 /** 100 * Load the kernel code into memory 101 */ 102 if (params()->kernel == "") { 103 inform("No kernel set for full system simulation. Assuming you know what" 104 " you're doing...\n"); 105 } else { 106 // Load kernel code 107 kernel = createObjectFile(params()->kernel); 108 inform("kernel located at: %s", params()->kernel); 109 110 if (kernel == NULL) 111 fatal("Could not load kernel file %s", params()->kernel); 112 113 // Load program sections into memory 114 kernel->loadSections(functionalPort, loadAddrMask); 115 116 // setup entry points 117 kernelStart = kernel->textBase(); 118 kernelEnd = kernel->bssBase() + kernel->bssSize(); 119 kernelEntry = kernel->entryPoint(); 120 121 // load symbols 122 if (!kernel->loadGlobalSymbols(kernelSymtab)) 123 fatal("could not load kernel symbols\n"); 124 125 if (!kernel->loadLocalSymbols(kernelSymtab)) 126 fatal("could not load kernel local symbols\n"); 127 128 if (!kernel->loadGlobalSymbols(debugSymbolTable)) 129 fatal("could not load kernel symbols\n"); 130 131 if (!kernel->loadLocalSymbols(debugSymbolTable)) 132 fatal("could not load kernel local symbols\n"); 133 134 DPRINTF(Loader, "Kernel start = %#x\n", kernelStart); 135 DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd); 136 DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry); 137 DPRINTF(Loader, "Kernel loaded...\n"); 138 } 139#endif // FULL_SYSTEM 140 141 // increment the number of running systms 142 numSystemsRunning++; 143} 144 145System::~System() 146{ 147#if FULL_SYSTEM 148 delete kernelSymtab; 149 delete kernel; 150#else 151 panic("System::fixFuncEventAddr needs to be rewritten " 152 "to work with syscall emulation"); 153#endif // FULL_SYSTEM} 154} 155 156void 157System::setMemoryMode(Enums::MemoryMode mode) 158{ 159 assert(getState() == Drained); 160 memoryMode = mode; 161} 162 163bool System::breakpoint() 164{ 165 if (remoteGDB.size()) 166 return remoteGDB[0]->breakpoint(); 167 return false; 168} 169 170/** 171 * Setting rgdb_wait to a positive integer waits for a remote debugger to 172 * connect to that context ID before continuing. This should really 173 be a parameter on the CPU object or something... 174 */ 175int rgdb_wait = -1; 176 177int 178System::registerThreadContext(ThreadContext *tc, int assigned) 179{ 180 int id; 181 if (assigned == -1) { 182 for (id = 0; id < threadContexts.size(); id++) { 183 if (!threadContexts[id]) 184 break; 185 } 186 187 if (threadContexts.size() <= id) 188 threadContexts.resize(id + 1); 189 } else { 190 if (threadContexts.size() <= assigned) 191 threadContexts.resize(assigned + 1); 192 id = assigned; 193 } 194 195 if (threadContexts[id]) 196 fatal("Cannot have two CPUs with the same id (%d)\n", id); 197 198 threadContexts[id] = tc; 199 _numContexts++; 200 201 int port = getRemoteGDBPort(); 202 if (port) { 203 RemoteGDB *rgdb = new RemoteGDB(this, tc); 204 GDBListener *gdbl = new GDBListener(rgdb, port + id); 205 gdbl->listen(); 206 207 if (rgdb_wait != -1 && rgdb_wait == id) 208 gdbl->accept(); 209 210 if (remoteGDB.size() <= id) { 211 remoteGDB.resize(id + 1); 212 } 213 214 remoteGDB[id] = rgdb; 215 } 216 217 return id; 218} 219 220int 221System::numRunningContexts() 222{ 223 int running = 0; 224 for (int i = 0; i < _numContexts; ++i) { 225 if (threadContexts[i]->status() != ThreadContext::Halted) 226 ++running; 227 } 228 return running; 229} 230 231void 232System::initState() 233{ 234#if FULL_SYSTEM 235 int i; 236 for (i = 0; i < threadContexts.size(); i++) 237 TheISA::startupCPU(threadContexts[i], i); 238#endif 239} 240 241void 242System::replaceThreadContext(ThreadContext *tc, int context_id) 243{ 244 if (context_id >= threadContexts.size()) { 245 panic("replaceThreadContext: bad id, %d >= %d\n", 246 context_id, threadContexts.size()); 247 } 248 249 threadContexts[context_id] = tc; 250 if (context_id < remoteGDB.size()) 251 remoteGDB[context_id]->replaceThreadContext(tc); 252} 253 254#if !FULL_SYSTEM 255Addr 256System::new_page() 257{ 258 Addr return_addr = pagePtr << LogVMPageSize; 259 ++pagePtr; 260 if (return_addr >= physmem->size()) 261 fatal("Out of memory, please increase size of physical memory."); 262 return return_addr; 263} 264 265Addr 266System::memSize() 267{ 268 return physmem->size(); 269} 270 271Addr 272System::freeMemSize() 273{ 274 return physmem->size() - (pagePtr << LogVMPageSize); 275} 276 277#endif 278 279void 280System::serialize(ostream &os) 281{ 282#if FULL_SYSTEM 283 kernelSymtab->serialize("kernel_symtab", os); 284#else // !FULL_SYSTEM 285 SERIALIZE_SCALAR(pagePtr); 286 SERIALIZE_SCALAR(nextPID); 287#endif 288} 289 290 291void 292System::unserialize(Checkpoint *cp, const string §ion) 293{ 294#if FULL_SYSTEM 295 kernelSymtab->unserialize("kernel_symtab", cp, section); 296#else // !FULL_SYSTEM 297 UNSERIALIZE_SCALAR(pagePtr); 298 UNSERIALIZE_SCALAR(nextPID); 299#endif 300} 301 302void 303System::printSystems() 304{ 305 vector<System *>::iterator i = systemList.begin(); 306 vector<System *>::iterator end = systemList.end(); 307 for (; i != end; ++i) { 308 System *sys = *i; 309 cerr << "System " << sys->name() << ": " << hex << sys << endl; 310 } 311} 312 313void 314printSystems() 315{ 316 System::printSystems(); 317} 318 319const char *System::MemoryModeStrings[3] = {"invalid", "atomic", 320 "timing"}; 321 322#if !FULL_SYSTEM 323 324System * 325SystemParams::create() 326{ 327 return new System(this); 328} 329 330#endif 331