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