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