sim, kvm: make KvmVM a System parameter
[gem5.git] / src / sim / system.cc
1 /*
2 * Copyright (c) 2011-2014 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 "sim/system.hh"
49
50 #include "arch/remote_gdb.hh"
51 #include "arch/utility.hh"
52 #include "base/loader/object_file.hh"
53 #include "base/loader/symtab.hh"
54 #include "base/str.hh"
55 #include "base/trace.hh"
56 #include "config/use_kvm.hh"
57 #if USE_KVM
58 #include "cpu/kvm/vm.hh"
59 #endif
60 #include "cpu/thread_context.hh"
61 #include "debug/Loader.hh"
62 #include "debug/WorkItems.hh"
63 #include "mem/abstract_mem.hh"
64 #include "mem/physical.hh"
65 #include "params/System.hh"
66 #include "sim/byteswap.hh"
67 #include "sim/debug.hh"
68 #include "sim/full_system.hh"
69
70 /**
71 * To avoid linking errors with LTO, only include the header if we
72 * actually have a definition.
73 */
74 #if THE_ISA != NULL_ISA
75 #include "kern/kernel_stats.hh"
76
77 #endif
78
79 using namespace std;
80 using namespace TheISA;
81
82 vector<System *> System::systemList;
83
84 int System::numSystemsRunning = 0;
85
86 System::System(Params *p)
87 : MemObject(p), _systemPort("system_port", this),
88 _numContexts(0),
89 multiThread(p->multi_thread),
90 pagePtr(0),
91 init_param(p->init_param),
92 physProxy(_systemPort, p->cache_line_size),
93 kernelSymtab(nullptr),
94 kernel(nullptr),
95 loadAddrMask(p->load_addr_mask),
96 loadAddrOffset(p->load_offset),
97 #if USE_KVM
98 kvmVM(p->kvm_vm),
99 #else
100 kvmVM(nullptr),
101 #endif
102 physmem(name() + ".physmem", p->memories, p->mmap_using_noreserve),
103 memoryMode(p->mem_mode),
104 _cacheLineSize(p->cache_line_size),
105 workItemsBegin(0),
106 workItemsEnd(0),
107 numWorkIds(p->num_work_ids),
108 thermalModel(p->thermal_model),
109 _params(p),
110 totalNumInsts(0),
111 instEventQueue("system instruction-based event queue")
112 {
113 // add self to global system list
114 systemList.push_back(this);
115
116 #if USE_KVM
117 if (kvmVM) {
118 kvmVM->setSystem(this);
119 }
120 #endif
121
122 if (FullSystem) {
123 kernelSymtab = new SymbolTable;
124 if (!debugSymbolTable)
125 debugSymbolTable = new SymbolTable;
126 }
127
128 // check if the cache line size is a value known to work
129 if (!(_cacheLineSize == 16 || _cacheLineSize == 32 ||
130 _cacheLineSize == 64 || _cacheLineSize == 128))
131 warn_once("Cache line size is neither 16, 32, 64 nor 128 bytes.\n");
132
133 // Get the generic system master IDs
134 MasterID tmp_id M5_VAR_USED;
135 tmp_id = getMasterId("writebacks");
136 assert(tmp_id == Request::wbMasterId);
137 tmp_id = getMasterId("functional");
138 assert(tmp_id == Request::funcMasterId);
139 tmp_id = getMasterId("interrupt");
140 assert(tmp_id == Request::intMasterId);
141
142 if (FullSystem) {
143 if (params()->kernel == "") {
144 inform("No kernel set for full system simulation. "
145 "Assuming you know what you're doing\n");
146 } else {
147 // Get the kernel code
148 kernel = createObjectFile(params()->kernel);
149 inform("kernel located at: %s", params()->kernel);
150
151 if (kernel == NULL)
152 fatal("Could not load kernel file %s", params()->kernel);
153
154 // setup entry points
155 kernelStart = kernel->textBase();
156 kernelEnd = kernel->bssBase() + kernel->bssSize();
157 kernelEntry = kernel->entryPoint();
158
159 // load symbols
160 if (!kernel->loadGlobalSymbols(kernelSymtab))
161 fatal("could not load kernel symbols\n");
162
163 if (!kernel->loadLocalSymbols(kernelSymtab))
164 fatal("could not load kernel local symbols\n");
165
166 if (!kernel->loadGlobalSymbols(debugSymbolTable))
167 fatal("could not load kernel symbols\n");
168
169 if (!kernel->loadLocalSymbols(debugSymbolTable))
170 fatal("could not load kernel local symbols\n");
171
172 // Loading only needs to happen once and after memory system is
173 // connected so it will happen in initState()
174 }
175 }
176
177 // increment the number of running systems
178 numSystemsRunning++;
179
180 // Set back pointers to the system in all memories
181 for (int x = 0; x < params()->memories.size(); x++)
182 params()->memories[x]->system(this);
183 }
184
185 System::~System()
186 {
187 delete kernelSymtab;
188 delete kernel;
189
190 for (uint32_t j = 0; j < numWorkIds; j++)
191 delete workItemStats[j];
192 }
193
194 void
195 System::init()
196 {
197 // check that the system port is connected
198 if (!_systemPort.isConnected())
199 panic("System port on %s is not connected.\n", name());
200 }
201
202 BaseMasterPort&
203 System::getMasterPort(const std::string &if_name, PortID idx)
204 {
205 // no need to distinguish at the moment (besides checking)
206 return _systemPort;
207 }
208
209 void
210 System::setMemoryMode(Enums::MemoryMode mode)
211 {
212 assert(drainState() == DrainState::Drained);
213 memoryMode = mode;
214 }
215
216 bool System::breakpoint()
217 {
218 if (remoteGDB.size())
219 return remoteGDB[0]->breakpoint();
220 return false;
221 }
222
223 /**
224 * Setting rgdb_wait to a positive integer waits for a remote debugger to
225 * connect to that context ID before continuing. This should really
226 be a parameter on the CPU object or something...
227 */
228 int rgdb_wait = -1;
229
230 ContextID
231 System::registerThreadContext(ThreadContext *tc, ContextID assigned)
232 {
233 int id;
234 if (assigned == InvalidContextID) {
235 for (id = 0; id < threadContexts.size(); id++) {
236 if (!threadContexts[id])
237 break;
238 }
239
240 if (threadContexts.size() <= id)
241 threadContexts.resize(id + 1);
242 } else {
243 if (threadContexts.size() <= assigned)
244 threadContexts.resize(assigned + 1);
245 id = assigned;
246 }
247
248 if (threadContexts[id])
249 fatal("Cannot have two CPUs with the same id (%d)\n", id);
250
251 threadContexts[id] = tc;
252 _numContexts++;
253
254 #if THE_ISA != NULL_ISA
255 int port = getRemoteGDBPort();
256 if (port) {
257 RemoteGDB *rgdb = new RemoteGDB(this, tc);
258 GDBListener *gdbl = new GDBListener(rgdb, port + id);
259 gdbl->listen();
260
261 if (rgdb_wait != -1 && rgdb_wait == id)
262 gdbl->accept();
263
264 if (remoteGDB.size() <= id) {
265 remoteGDB.resize(id + 1);
266 }
267
268 remoteGDB[id] = rgdb;
269 }
270 #endif
271
272 activeCpus.push_back(false);
273
274 return id;
275 }
276
277 int
278 System::numRunningContexts()
279 {
280 int running = 0;
281 for (int i = 0; i < _numContexts; ++i) {
282 if (threadContexts[i]->status() != ThreadContext::Halted)
283 ++running;
284 }
285 return running;
286 }
287
288 void
289 System::initState()
290 {
291 if (FullSystem) {
292 for (int i = 0; i < threadContexts.size(); i++)
293 TheISA::startupCPU(threadContexts[i], i);
294 // Moved from the constructor to here since it relies on the
295 // address map being resolved in the interconnect
296 /**
297 * Load the kernel code into memory
298 */
299 if (params()->kernel != "") {
300 if (params()->kernel_addr_check) {
301 // Validate kernel mapping before loading binary
302 if (!(isMemAddr((kernelStart & loadAddrMask) +
303 loadAddrOffset) &&
304 isMemAddr((kernelEnd & loadAddrMask) +
305 loadAddrOffset))) {
306 fatal("Kernel is mapped to invalid location (not memory). "
307 "kernelStart 0x(%x) - kernelEnd 0x(%x) %#x:%#x\n",
308 kernelStart,
309 kernelEnd, (kernelStart & loadAddrMask) +
310 loadAddrOffset,
311 (kernelEnd & loadAddrMask) + loadAddrOffset);
312 }
313 }
314 // Load program sections into memory
315 kernel->loadSections(physProxy, loadAddrMask, loadAddrOffset);
316
317 DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
318 DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
319 DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
320 DPRINTF(Loader, "Kernel loaded...\n");
321 }
322 }
323 }
324
325 void
326 System::replaceThreadContext(ThreadContext *tc, ContextID context_id)
327 {
328 if (context_id >= threadContexts.size()) {
329 panic("replaceThreadContext: bad id, %d >= %d\n",
330 context_id, threadContexts.size());
331 }
332
333 threadContexts[context_id] = tc;
334 if (context_id < remoteGDB.size())
335 remoteGDB[context_id]->replaceThreadContext(tc);
336 }
337
338 Addr
339 System::allocPhysPages(int npages)
340 {
341 Addr return_addr = pagePtr << PageShift;
342 pagePtr += npages;
343
344 Addr next_return_addr = pagePtr << PageShift;
345
346 AddrRange m5opRange(0xffff0000, 0xffffffff);
347 if (m5opRange.contains(next_return_addr)) {
348 warn("Reached m5ops MMIO region\n");
349 return_addr = 0xffffffff;
350 pagePtr = 0xffffffff >> PageShift;
351 }
352
353 if ((pagePtr << PageShift) > physmem.totalSize())
354 fatal("Out of memory, please increase size of physical memory.");
355 return return_addr;
356 }
357
358 Addr
359 System::memSize() const
360 {
361 return physmem.totalSize();
362 }
363
364 Addr
365 System::freeMemSize() const
366 {
367 return physmem.totalSize() - (pagePtr << PageShift);
368 }
369
370 bool
371 System::isMemAddr(Addr addr) const
372 {
373 return physmem.isMemAddr(addr);
374 }
375
376 void
377 System::drainResume()
378 {
379 totalNumInsts = 0;
380 }
381
382 void
383 System::serialize(CheckpointOut &cp) const
384 {
385 if (FullSystem)
386 kernelSymtab->serialize("kernel_symtab", cp);
387 SERIALIZE_SCALAR(pagePtr);
388 serializeSymtab(cp);
389
390 // also serialize the memories in the system
391 physmem.serializeSection(cp, "physmem");
392 }
393
394
395 void
396 System::unserialize(CheckpointIn &cp)
397 {
398 if (FullSystem)
399 kernelSymtab->unserialize("kernel_symtab", cp);
400 UNSERIALIZE_SCALAR(pagePtr);
401 unserializeSymtab(cp);
402
403 // also unserialize the memories in the system
404 physmem.unserializeSection(cp, "physmem");
405 }
406
407 void
408 System::regStats()
409 {
410 MemObject::regStats();
411
412 for (uint32_t j = 0; j < numWorkIds ; j++) {
413 workItemStats[j] = new Stats::Histogram();
414 stringstream namestr;
415 ccprintf(namestr, "work_item_type%d", j);
416 workItemStats[j]->init(20)
417 .name(name() + "." + namestr.str())
418 .desc("Run time stat for" + namestr.str())
419 .prereq(*workItemStats[j]);
420 }
421 }
422
423 void
424 System::workItemEnd(uint32_t tid, uint32_t workid)
425 {
426 std::pair<uint32_t,uint32_t> p(tid, workid);
427 if (!lastWorkItemStarted.count(p))
428 return;
429
430 Tick samp = curTick() - lastWorkItemStarted[p];
431 DPRINTF(WorkItems, "Work item end: %d\t%d\t%lld\n", tid, workid, samp);
432
433 if (workid >= numWorkIds)
434 fatal("Got workid greater than specified in system configuration\n");
435
436 workItemStats[workid]->sample(samp);
437 lastWorkItemStarted.erase(p);
438 }
439
440 void
441 System::printSystems()
442 {
443 ios::fmtflags flags(cerr.flags());
444
445 vector<System *>::iterator i = systemList.begin();
446 vector<System *>::iterator end = systemList.end();
447 for (; i != end; ++i) {
448 System *sys = *i;
449 cerr << "System " << sys->name() << ": " << hex << sys << endl;
450 }
451
452 cerr.flags(flags);
453 }
454
455 void
456 printSystems()
457 {
458 System::printSystems();
459 }
460
461 MasterID
462 System::getMasterId(std::string master_name)
463 {
464 // strip off system name if the string starts with it
465 if (startswith(master_name, name()))
466 master_name = master_name.erase(0, name().size() + 1);
467
468 // CPUs in switch_cpus ask for ids again after switching
469 for (int i = 0; i < masterIds.size(); i++) {
470 if (masterIds[i] == master_name) {
471 return i;
472 }
473 }
474
475 // Verify that the statistics haven't been enabled yet
476 // Otherwise objects will have sized their stat buckets and
477 // they will be too small
478
479 if (Stats::enabled()) {
480 fatal("Can't request a masterId after regStats(). "
481 "You must do so in init().\n");
482 }
483
484 masterIds.push_back(master_name);
485
486 return masterIds.size() - 1;
487 }
488
489 std::string
490 System::getMasterName(MasterID master_id)
491 {
492 if (master_id >= masterIds.size())
493 fatal("Invalid master_id passed to getMasterName()\n");
494
495 return masterIds[master_id];
496 }
497
498 System *
499 SystemParams::create()
500 {
501 return new System(this);
502 }