ca9d68d77fd9b70b2615673bfae72f1831685d6e
[gem5.git] / sim / system.cc
1 #include "arch/isa_traits.hh"
2 #include "base/loader/object_file.hh"
3 #include "base/loader/symtab.hh"
4 #include "base/trace.hh"
5 #include "cpu/exec_context.hh"
6 #include "mem/mem_object.hh"
7 #include "mem/physical.hh"
8 #include "sim/builder.hh"
9 #include "sim/byteswap.hh"
10 #include "sim/system.hh"
11 #if FULL_SYSTEM
12 #include "arch/vtophys.hh"
13 #include "base/remote_gdb.hh"
14 #include "kern/kernel_stats.hh"
15 #endif
16
17 using namespace std;
18 using namespace TheISA;
19
20 vector<System *> System::systemList;
21
22 int System::numSystemsRunning = 0;
23
24 System::System(Params *p)
25 : SimObject(p->name), physmem(p->physmem), numcpus(0),
26 #if FULL_SYSTEM
27 init_param(p->init_param),
28 #else
29 page_ptr(0),
30 #endif
31 _params(p)
32 {
33 // add self to global system list
34 systemList.push_back(this);
35
36 #if FULL_SYSTEM
37 kernelSymtab = new SymbolTable;
38 debugSymbolTable = new SymbolTable;
39
40
41 /**
42 * Get a functional port to memory
43 */
44 Port *mem_port;
45 mem_port = physmem->getPort("functional");
46 functionalPort.setPeer(mem_port);
47 mem_port->setPeer(&functionalPort);
48
49 mem_port = physmem->getPort("functional");
50 virtPort.setPeer(mem_port);
51 mem_port->setPeer(&virtPort);
52
53
54 /**
55 * Load the kernel code into memory
56 */
57 // Load kernel code
58 kernel = createObjectFile(params()->kernel_path);
59 if (kernel == NULL)
60 fatal("Could not load kernel file %s", params()->kernel_path);
61
62 // Load program sections into memory
63 kernel->loadSections(&functionalPort, LoadAddrMask);
64
65 // setup entry points
66 kernelStart = kernel->textBase();
67 kernelEnd = kernel->bssBase() + kernel->bssSize();
68 kernelEntry = kernel->entryPoint();
69
70 // load symbols
71 if (!kernel->loadGlobalSymbols(kernelSymtab))
72 panic("could not load kernel symbols\n");
73
74 if (!kernel->loadLocalSymbols(kernelSymtab))
75 panic("could not load kernel local symbols\n");
76
77 if (!kernel->loadGlobalSymbols(debugSymbolTable))
78 panic("could not load kernel symbols\n");
79
80 if (!kernel->loadLocalSymbols(debugSymbolTable))
81 panic("could not load kernel local symbols\n");
82
83 DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
84 DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
85 DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
86 DPRINTF(Loader, "Kernel loaded...\n");
87
88 kernelBinning = new Kernel::Binning(this);
89 #endif // FULL_SYSTEM
90
91 // increment the number of running systms
92 numSystemsRunning++;
93 }
94
95 System::~System()
96 {
97 #if FULL_SYSTEM
98 delete kernelSymtab;
99 delete kernel;
100
101 delete kernelBinning;
102 #else
103 panic("System::fixFuncEventAddr needs to be rewritten "
104 "to work with syscall emulation");
105 #endif // FULL_SYSTEM}
106 }
107
108 #if FULL_SYSTEM
109
110
111 int rgdb_wait = -1;
112
113 #endif // FULL_SYSTEM
114
115 int
116 System::registerExecContext(ExecContext *xc, int id)
117 {
118 if (id == -1) {
119 for (id = 0; id < execContexts.size(); id++) {
120 if (!execContexts[id])
121 break;
122 }
123 }
124
125 if (execContexts.size() <= id)
126 execContexts.resize(id + 1);
127
128 if (execContexts[id])
129 panic("Cannot have two CPUs with the same id (%d)\n", id);
130
131 execContexts[id] = xc;
132 numcpus++;
133
134 #if FULL_SYSTEM
135 RemoteGDB *rgdb = new RemoteGDB(this, xc);
136 GDBListener *gdbl = new GDBListener(rgdb, 7000 + id);
137 gdbl->listen();
138 /**
139 * Uncommenting this line waits for a remote debugger to connect
140 * to the simulator before continuing.
141 */
142 if (rgdb_wait != -1 && rgdb_wait == id)
143 gdbl->accept();
144
145 if (remoteGDB.size() <= id) {
146 remoteGDB.resize(id + 1);
147 }
148
149 remoteGDB[id] = rgdb;
150 #endif // FULL_SYSTEM
151
152 return id;
153 }
154
155 void
156 System::startup()
157 {
158 int i;
159 for (i = 0; i < execContexts.size(); i++)
160 execContexts[i]->activate(0);
161 }
162
163 void
164 System::replaceExecContext(ExecContext *xc, int id)
165 {
166 if (id >= execContexts.size()) {
167 panic("replaceExecContext: bad id, %d >= %d\n",
168 id, execContexts.size());
169 }
170
171 execContexts[id] = xc;
172 #if FULL_SYSTEM
173 remoteGDB[id]->replaceExecContext(xc);
174 #endif // FULL_SYSTEM
175 }
176
177 #if !FULL_SYSTEM
178 Addr
179 System::new_page()
180 {
181 Addr return_addr = page_ptr << LogVMPageSize;
182 ++page_ptr;
183 return return_addr;
184 }
185 #endif
186
187 void
188 System::regStats()
189 {
190 #if FULL_SYSTEM
191 kernelBinning->regStats(name() + ".kern");
192 #endif // FULL_SYSTEM
193 }
194
195 void
196 System::serialize(ostream &os)
197 {
198 #if FULL_SYSTEM
199 kernelBinning->serialize(os);
200
201 kernelSymtab->serialize("kernel_symtab", os);
202 #endif // FULL_SYSTEM
203 }
204
205
206 void
207 System::unserialize(Checkpoint *cp, const string &section)
208 {
209 #if FULL_SYSTEM
210 kernelBinning->unserialize(cp, section);
211
212 kernelSymtab->unserialize("kernel_symtab", cp, section);
213 #endif // FULL_SYSTEM
214 }
215
216 void
217 System::printSystems()
218 {
219 vector<System *>::iterator i = systemList.begin();
220 vector<System *>::iterator end = systemList.end();
221 for (; i != end; ++i) {
222 System *sys = *i;
223 cerr << "System " << sys->name() << ": " << hex << sys << endl;
224 }
225 }
226
227 extern "C"
228 void
229 printSystems()
230 {
231 System::printSystems();
232 }
233
234 #if FULL_SYSTEM
235
236 // In full system mode, only derived classes (e.g. AlphaLinuxSystem)
237 // can be created directly.
238
239 DEFINE_SIM_OBJECT_CLASS_NAME("System", System)
240
241 #else
242
243 BEGIN_DECLARE_SIM_OBJECT_PARAMS(System)
244
245 SimObjectParam<PhysicalMemory *> physmem;
246
247 END_DECLARE_SIM_OBJECT_PARAMS(System)
248
249 BEGIN_INIT_SIM_OBJECT_PARAMS(System)
250
251 INIT_PARAM(physmem, "physical memory")
252
253 END_INIT_SIM_OBJECT_PARAMS(System)
254
255 CREATE_SIM_OBJECT(System)
256 {
257 System::Params *p = new System::Params;
258 p->name = getInstanceName();
259 p->physmem = physmem;
260 return new System(p);
261 }
262
263 REGISTER_SIM_OBJECT("System", System)
264
265 #endif