Ruby Debug Flags: Remove one, add another
[gem5.git] / src / sim / system.cc
1 /*
2 * Copyright (c) 2011 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/isa_traits.hh"
49 #include "arch/remote_gdb.hh"
50 #include "arch/utility.hh"
51 #include "base/loader/object_file.hh"
52 #include "base/loader/symtab.hh"
53 #include "base/trace.hh"
54 #include "config/full_system.hh"
55 #include "config/the_isa.hh"
56 #include "cpu/thread_context.hh"
57 #include "debug/Loader.hh"
58 #include "debug/WorkItems.hh"
59 #include "mem/mem_object.hh"
60 #include "mem/physical.hh"
61 #include "sim/byteswap.hh"
62 #include "sim/debug.hh"
63 #include "sim/system.hh"
64
65 #if FULL_SYSTEM
66 #include "arch/vtophys.hh"
67 #include "kern/kernel_stats.hh"
68 #include "mem/vport.hh"
69 #else
70 #include "params/System.hh"
71 #endif
72
73 using namespace std;
74 using namespace TheISA;
75
76 vector<System *> System::systemList;
77
78 int System::numSystemsRunning = 0;
79
80 System::System(Params *p)
81 : SimObject(p), physmem(p->physmem), _numContexts(0),
82 #if FULL_SYSTEM
83 init_param(p->init_param),
84 loadAddrMask(p->load_addr_mask),
85 #else
86 pagePtr(0),
87 nextPID(0),
88 #endif
89 memoryMode(p->mem_mode),
90 workItemsBegin(0),
91 workItemsEnd(0),
92 numWorkIds(p->num_work_ids),
93 _params(p),
94 totalNumInsts(0),
95 instEventQueue("system instruction-based event queue")
96 {
97 // add self to global system list
98 systemList.push_back(this);
99
100 /** Keep track of all memories we can execute code out of
101 * in our system
102 */
103 for (int x = 0; x < p->memories.size(); x++) {
104 if (!p->memories[x])
105 continue;
106 memRanges.push_back(RangeSize(p->memories[x]->start(),
107 p->memories[x]->size()));
108 }
109
110 #if FULL_SYSTEM
111 kernelSymtab = new SymbolTable;
112 if (!debugSymbolTable)
113 debugSymbolTable = new SymbolTable;
114
115
116 /**
117 * Get a functional port to memory
118 */
119 Port *mem_port;
120 functionalPort = new FunctionalPort(name() + "-fport");
121 mem_port = physmem->getPort("functional");
122 functionalPort->setPeer(mem_port);
123 mem_port->setPeer(functionalPort);
124
125 virtPort = new VirtualPort(name() + "-fport");
126 mem_port = physmem->getPort("functional");
127 virtPort->setPeer(mem_port);
128 mem_port->setPeer(virtPort);
129
130
131 /**
132 * Load the kernel code into memory
133 */
134 if (params()->kernel == "") {
135 inform("No kernel set for full system simulation. Assuming you know what"
136 " you're doing...\n");
137 } else {
138 // Load kernel code
139 kernel = createObjectFile(params()->kernel);
140 inform("kernel located at: %s", params()->kernel);
141
142 if (kernel == NULL)
143 fatal("Could not load kernel file %s", params()->kernel);
144
145 // Load program sections into memory
146 kernel->loadSections(functionalPort, loadAddrMask);
147
148 // setup entry points
149 kernelStart = kernel->textBase();
150 kernelEnd = kernel->bssBase() + kernel->bssSize();
151 kernelEntry = kernel->entryPoint();
152
153 // load symbols
154 if (!kernel->loadGlobalSymbols(kernelSymtab))
155 fatal("could not load kernel symbols\n");
156
157 if (!kernel->loadLocalSymbols(kernelSymtab))
158 fatal("could not load kernel local symbols\n");
159
160 if (!kernel->loadGlobalSymbols(debugSymbolTable))
161 fatal("could not load kernel symbols\n");
162
163 if (!kernel->loadLocalSymbols(debugSymbolTable))
164 fatal("could not load kernel local symbols\n");
165
166 DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
167 DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
168 DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
169 DPRINTF(Loader, "Kernel loaded...\n");
170 }
171 #endif // FULL_SYSTEM
172
173 // increment the number of running systms
174 numSystemsRunning++;
175
176 activeCpus.clear();
177 }
178
179 System::~System()
180 {
181 #if FULL_SYSTEM
182 delete kernelSymtab;
183 delete kernel;
184 #else
185 panic("System::fixFuncEventAddr needs to be rewritten "
186 "to work with syscall emulation");
187 #endif // FULL_SYSTEM}
188
189 for (uint32_t j = 0; j < numWorkIds; j++)
190 delete workItemStats[j];
191 }
192
193 void
194 System::setMemoryMode(Enums::MemoryMode mode)
195 {
196 assert(getState() == Drained);
197 memoryMode = mode;
198 }
199
200 bool System::breakpoint()
201 {
202 if (remoteGDB.size())
203 return remoteGDB[0]->breakpoint();
204 return false;
205 }
206
207 /**
208 * Setting rgdb_wait to a positive integer waits for a remote debugger to
209 * connect to that context ID before continuing. This should really
210 be a parameter on the CPU object or something...
211 */
212 int rgdb_wait = -1;
213
214 int
215 System::registerThreadContext(ThreadContext *tc, int assigned)
216 {
217 int id;
218 if (assigned == -1) {
219 for (id = 0; id < threadContexts.size(); id++) {
220 if (!threadContexts[id])
221 break;
222 }
223
224 if (threadContexts.size() <= id)
225 threadContexts.resize(id + 1);
226 } else {
227 if (threadContexts.size() <= assigned)
228 threadContexts.resize(assigned + 1);
229 id = assigned;
230 }
231
232 if (threadContexts[id])
233 fatal("Cannot have two CPUs with the same id (%d)\n", id);
234
235 threadContexts[id] = tc;
236 _numContexts++;
237
238 int port = getRemoteGDBPort();
239 if (port) {
240 RemoteGDB *rgdb = new RemoteGDB(this, tc);
241 GDBListener *gdbl = new GDBListener(rgdb, port + id);
242 gdbl->listen();
243
244 if (rgdb_wait != -1 && rgdb_wait == id)
245 gdbl->accept();
246
247 if (remoteGDB.size() <= id) {
248 remoteGDB.resize(id + 1);
249 }
250
251 remoteGDB[id] = rgdb;
252 }
253
254 activeCpus.push_back(false);
255
256 return id;
257 }
258
259 int
260 System::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
270 void
271 System::initState()
272 {
273 #if FULL_SYSTEM
274 int i;
275 for (i = 0; i < threadContexts.size(); i++)
276 TheISA::startupCPU(threadContexts[i], i);
277 #endif
278 }
279
280 void
281 System::replaceThreadContext(ThreadContext *tc, int context_id)
282 {
283 if (context_id >= threadContexts.size()) {
284 panic("replaceThreadContext: bad id, %d >= %d\n",
285 context_id, threadContexts.size());
286 }
287
288 threadContexts[context_id] = tc;
289 if (context_id < remoteGDB.size())
290 remoteGDB[context_id]->replaceThreadContext(tc);
291 }
292
293 #if !FULL_SYSTEM
294 Addr
295 System::allocPhysPages(int npages)
296 {
297 Addr return_addr = pagePtr << LogVMPageSize;
298 pagePtr += npages;
299 if (return_addr >= physmem->size())
300 fatal("Out of memory, please increase size of physical memory.");
301 return return_addr;
302 }
303
304 Addr
305 System::memSize()
306 {
307 return physmem->size();
308 }
309
310 Addr
311 System::freeMemSize()
312 {
313 return physmem->size() - (pagePtr << LogVMPageSize);
314 }
315
316 #endif
317
318 bool
319 System::isMemory(const Addr addr) const
320 {
321 std::list<Range<Addr> >::const_iterator i;
322 for (i = memRanges.begin(); i != memRanges.end(); i++) {
323 if (*i == addr)
324 return true;
325 }
326 return false;
327 }
328
329 void
330 System::resume()
331 {
332 SimObject::resume();
333 totalNumInsts = 0;
334 }
335
336 void
337 System::serialize(ostream &os)
338 {
339 #if FULL_SYSTEM
340 kernelSymtab->serialize("kernel_symtab", os);
341 #else // !FULL_SYSTEM
342 SERIALIZE_SCALAR(pagePtr);
343 SERIALIZE_SCALAR(nextPID);
344 #endif
345 }
346
347
348 void
349 System::unserialize(Checkpoint *cp, const string &section)
350 {
351 #if FULL_SYSTEM
352 kernelSymtab->unserialize("kernel_symtab", cp, section);
353 #else // !FULL_SYSTEM
354 UNSERIALIZE_SCALAR(pagePtr);
355 UNSERIALIZE_SCALAR(nextPID);
356 #endif
357 }
358
359 void
360 System::regStats()
361 {
362 for (uint32_t j = 0; j < numWorkIds ; j++) {
363 workItemStats[j] = new Stats::Histogram();
364 stringstream namestr;
365 ccprintf(namestr, "work_item_type%d", j);
366 workItemStats[j]->init(20)
367 .name(name() + "." + namestr.str())
368 .desc("Run time stat for" + namestr.str())
369 .prereq(*workItemStats[j]);
370 }
371 }
372
373 void
374 System::workItemEnd(uint32_t tid, uint32_t workid)
375 {
376 std::pair<uint32_t,uint32_t> p(tid, workid);
377 if (!lastWorkItemStarted.count(p))
378 return;
379
380 Tick samp = curTick() - lastWorkItemStarted[p];
381 DPRINTF(WorkItems, "Work item end: %d\t%d\t%lld\n", tid, workid, samp);
382
383 if (workid >= numWorkIds)
384 fatal("Got workid greater than specified in system configuration\n");
385
386 workItemStats[workid]->sample(samp);
387 lastWorkItemStarted.erase(p);
388 }
389
390 void
391 System::printSystems()
392 {
393 vector<System *>::iterator i = systemList.begin();
394 vector<System *>::iterator end = systemList.end();
395 for (; i != end; ++i) {
396 System *sys = *i;
397 cerr << "System " << sys->name() << ": " << hex << sys << endl;
398 }
399 }
400
401 void
402 printSystems()
403 {
404 System::printSystems();
405 }
406
407 const char *System::MemoryModeStrings[3] = {"invalid", "atomic",
408 "timing"};
409
410 #if !FULL_SYSTEM
411
412 System *
413 SystemParams::create()
414 {
415 return new System(this);
416 }
417
418 #endif