Merge zizzer:/bk/m5 into vm1.reinhardt.house:/z/stever/bk/m5
[gem5.git] / sim / system.cc
1 /*
2 * Copyright (c) 2002-2004 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
29 #include "base/loader/object_file.hh"
30 #include "base/loader/symtab.hh"
31 #include "base/remote_gdb.hh"
32 #include "cpu/exec_context.hh"
33 #include "kern/kernel_stats.hh"
34 #include "mem/functional/memory_control.hh"
35 #include "mem/functional/physical.hh"
36 #include "targetarch/vtophys.hh"
37 #include "sim/builder.hh"
38 #include "sim/system.hh"
39 #include "base/trace.hh"
40
41 using namespace std;
42
43 vector<System *> System::systemList;
44
45 int System::numSystemsRunning = 0;
46
47 System::System(Params *p)
48 : SimObject(p->name), memctrl(p->memctrl), physmem(p->physmem),
49 init_param(p->init_param), params(p)
50 {
51 // add self to global system list
52 systemList.push_back(this);
53
54 kernelSymtab = new SymbolTable;
55 consoleSymtab = new SymbolTable;
56 palSymtab = new SymbolTable;
57 debugSymbolTable = new SymbolTable;
58
59 /**
60 * Load the kernel, pal, and console code into memory
61 */
62 // Load kernel code
63 kernel = createObjectFile(params->kernel_path);
64 if (kernel == NULL)
65 fatal("Could not load kernel file %s", params->kernel_path);
66
67 // Load Console Code
68 console = createObjectFile(params->console_path);
69 if (console == NULL)
70 fatal("Could not load console file %s", params->console_path);
71
72 // Load pal file
73 pal = createObjectFile(params->palcode);
74 if (pal == NULL)
75 fatal("Could not load PALcode file %s", params->palcode);
76
77
78 // Load program sections into memory
79 pal->loadSections(physmem, true);
80 console->loadSections(physmem, true);
81 kernel->loadSections(physmem, true);
82
83 // setup entry points
84 kernelStart = kernel->textBase();
85 kernelEnd = kernel->bssBase() + kernel->bssSize();
86 kernelEntry = kernel->entryPoint();
87
88 // load symbols
89 if (!kernel->loadGlobalSymbols(kernelSymtab))
90 panic("could not load kernel symbols\n");
91
92 if (!kernel->loadLocalSymbols(kernelSymtab))
93 panic("could not load kernel local symbols\n");
94
95 if (!console->loadGlobalSymbols(consoleSymtab))
96 panic("could not load console symbols\n");
97
98 if (!pal->loadGlobalSymbols(palSymtab))
99 panic("could not load pal symbols\n");
100
101 if (!pal->loadLocalSymbols(palSymtab))
102 panic("could not load pal symbols\n");
103
104 if (!kernel->loadGlobalSymbols(debugSymbolTable))
105 panic("could not load kernel symbols\n");
106
107 if (!kernel->loadLocalSymbols(debugSymbolTable))
108 panic("could not load kernel local symbols\n");
109
110 if (!console->loadGlobalSymbols(debugSymbolTable))
111 panic("could not load console symbols\n");
112
113 if (!pal->loadGlobalSymbols(debugSymbolTable))
114 panic("could not load pal symbols\n");
115
116 if (!pal->loadLocalSymbols(debugSymbolTable))
117 panic("could not load pal symbols\n");
118
119
120 DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
121 DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
122 DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
123 DPRINTF(Loader, "Kernel loaded...\n");
124
125 Addr addr = 0;
126 #ifdef DEBUG
127 consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic");
128 if (consoleSymtab->findAddress("panic", addr))
129 consolePanicEvent->schedule(addr);
130 #endif
131
132 /**
133 * Copy the osflags (kernel arguments) into the consoles
134 * memory. (Presently Linux does not use the console service
135 * routine to get these command line arguments, but Tru64 and
136 * others do.)
137 */
138 if (consoleSymtab->findAddress("env_booted_osflags", addr)) {
139 Addr paddr = vtophys(physmem, addr);
140 char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t));
141
142 if (osflags)
143 strcpy(osflags, params->boot_osflags.c_str());
144 }
145
146 /**
147 * Set the hardware reset parameter block system type and revision
148 * information to Tsunami.
149 */
150 if (consoleSymtab->findAddress("xxm_rpb", addr)) {
151 Addr paddr = vtophys(physmem, addr);
152 char *hwrpb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
153
154 if (!hwrpb)
155 panic("could not translate hwrpb addr\n");
156
157 *(uint64_t*)(hwrpb+0x50) = htoa(params->system_type);
158 *(uint64_t*)(hwrpb+0x58) = htoa(params->system_rev);
159 } else
160 panic("could not find hwrpb\n");
161
162 // increment the number of running systms
163 numSystemsRunning++;
164
165 kernelBinning = new Kernel::Binning(this);
166 }
167
168 System::~System()
169 {
170 delete kernelSymtab;
171 delete consoleSymtab;
172 delete kernel;
173 delete console;
174 delete pal;
175
176 delete kernelBinning;
177
178 #ifdef DEBUG
179 delete consolePanicEvent;
180 #endif
181 }
182
183 bool
184 System::breakpoint()
185 {
186 return remoteGDB[0]->trap(ALPHA_KENTRY_INT);
187 }
188
189 int
190 System::registerExecContext(ExecContext *xc)
191 {
192 int xcIndex = execContexts.size();
193 execContexts.push_back(xc);
194
195 RemoteGDB *rgdb = new RemoteGDB(this, xc);
196 GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex);
197 gdbl->listen();
198 /**
199 * Uncommenting this line waits for a remote debugger to connect
200 * to the simulator before continuing.
201 */
202 //gdbl->accept();
203
204 if (remoteGDB.size() <= xcIndex) {
205 remoteGDB.resize(xcIndex+1);
206 }
207
208 remoteGDB[xcIndex] = rgdb;
209
210 return xcIndex;
211 }
212
213 void
214 System::startup()
215 {
216 if (!execContexts.empty()) {
217 // activate with zero delay so that we start ticking right
218 // away on cycle 0
219 execContexts[0]->activate(0);
220 }
221 }
222
223 void
224 System::replaceExecContext(ExecContext *xc, int xcIndex)
225 {
226 if (xcIndex >= execContexts.size()) {
227 panic("replaceExecContext: bad xcIndex, %d >= %d\n",
228 xcIndex, execContexts.size());
229 }
230
231 execContexts[xcIndex] = xc;
232 remoteGDB[xcIndex]->replaceExecContext(xc);
233 }
234
235 void
236 System::regStats()
237 {
238 kernelBinning->regStats(name() + ".kern");
239 }
240
241 void
242 System::serialize(ostream &os)
243 {
244 kernelBinning->serialize(os);
245 }
246
247
248 void
249 System::unserialize(Checkpoint *cp, const string &section)
250 {
251 kernelBinning->unserialize(cp, section);
252 }
253
254 void
255 System::printSystems()
256 {
257 vector<System *>::iterator i = systemList.begin();
258 vector<System *>::iterator end = systemList.end();
259 for (; i != end; ++i) {
260 System *sys = *i;
261 cerr << "System " << sys->name() << ": " << hex << sys << endl;
262 }
263 }
264
265 extern "C"
266 void
267 printSystems()
268 {
269 System::printSystems();
270 }
271
272 BEGIN_DECLARE_SIM_OBJECT_PARAMS(System)
273
274 Param<Tick> boot_cpu_frequency;
275 SimObjectParam<MemoryController *> memctrl;
276 SimObjectParam<PhysicalMemory *> physmem;
277
278 Param<string> kernel;
279 Param<string> console;
280 Param<string> pal;
281
282 Param<string> boot_osflags;
283 Param<string> readfile;
284 Param<unsigned int> init_param;
285
286 Param<uint64_t> system_type;
287 Param<uint64_t> system_rev;
288
289 Param<bool> bin;
290 VectorParam<string> binned_fns;
291 Param<bool> bin_int;
292
293 END_DECLARE_SIM_OBJECT_PARAMS(System)
294
295 BEGIN_INIT_SIM_OBJECT_PARAMS(System)
296
297 INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
298 INIT_PARAM(memctrl, "memory controller"),
299 INIT_PARAM(physmem, "phsyical memory"),
300 INIT_PARAM(kernel, "file that contains the kernel code"),
301 INIT_PARAM(console, "file that contains the console code"),
302 INIT_PARAM(pal, "file that contains palcode"),
303 INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
304 "a"),
305 INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
306 INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
307 INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
308 INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10),
309 INIT_PARAM_DFLT(bin, "is this system to be binned", false),
310 INIT_PARAM(binned_fns, "functions to be broken down and binned"),
311 INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
312
313 END_INIT_SIM_OBJECT_PARAMS(System)
314
315 CREATE_SIM_OBJECT(System)
316 {
317 System::Params *p = new System::Params;
318 p->name = getInstanceName();
319 p->boot_cpu_frequency = boot_cpu_frequency;
320 p->memctrl = memctrl;
321 p->physmem = physmem;
322 p->kernel_path = kernel;
323 p->console_path = console;
324 p->palcode = pal;
325 p->boot_osflags = boot_osflags;
326 p->init_param = init_param;
327 p->readfile = readfile;
328 p->system_type = system_type;
329 p->system_rev = system_rev;
330 p->bin = bin;
331 p->binned_fns = binned_fns;
332 p->bin_int = bin_int;
333 return new System(p);
334 }
335
336 REGISTER_SIM_OBJECT("System", System)
337